如何在嵌套列表中为不同大小的数据框的列中应用函数?

时间:2014-02-24 22:02:56

标签: r nested plyr

在R中,要将某个功能应用于列,您可以执行以下操作:

df$col <- someFunction(df$col)

现在我的问题是,当你在嵌套列表中有数据框时,你如何执行类似的任务? 假设我有一个这样的下面的列表,其中我在根目录的第二级有数据框。

                                           +------+------+
                                  type1    | id   | name |
                              +----------->|------|------|
                              |            |      |      |
                              |            |      |      |
                year1         |            +------+------+
           +------------------+
           |                  |
           |                  |            +------+------+-----+
           |                  |  type2     | meta1|meta2 | name|
           |                  +----------> |------|------|-----|
           |                               |      |      |     |
           +                               +------+------+-----+
           |                     type1    +------+------+
           |                  +---------> | id   |name  |
           |                  |           |------|------|
           |     year2        |           |      |      |
   list    +----------------->+           |      |      |
           +                  |           +------+------+
           |                  |  type2     +------+------+-----+
           |                  +--------->  | meta1|meta2 |name |
           |                               |------|------|-----|
           |                               |      |      |     |
           |                    type1      +------+------+-----+
           |                 +---------->  +------+------+
           |                 |             | id   |name  |
           |     year3       |             |------|------|
           +-----------------+             |      |      |
                             |             |      |      |
                             |  type2      +------+------+
                             +---------->  +------+------+-----+
                                           |meta1 | meta2|name |
                                           |------|------|-----|
                                           |      |      |     |
                                           +------+------+-----+

我想用一些函数修改叶子中每个数据框中的“name”列,并将结果存储在那里。你是怎么做到的?

以下是示例数据:

data<-list()

data$yr2001$type1 <- df_2001_1 <- data.frame(index=1:3,name=c("jack","king","larry"))
data$yr2001$type2 <- df_2001_2 <- data.frame(index=1:5,name=c("man","women","oliver","jack","jill"))
data$yr2002$type1 <- df_2002_1 <- data.frame(index=1:3,name=c("janet","king","larry"))
data$yr2002$type2 <- df_2002_2 <- data.frame(index=1:5,name=c("alboyr","king","larry","rachel","sam"))
data$yr2003$type1 <- df_2003_1 <- data.frame(index=1:3,name=c("dan","jay","zang"))
data$yr2003$type2 <- df_2003_2 <- data.frame(index=1:5,name=c("zang","king","larry","kim","fran"))

说我想在列表中存储的每个数据框的名称列中大写所有名称

4 个答案:

答案 0 :(得分:3)

我同意@joran上面的评论---这是通过添加类型作为列来进行整合。但这是rapply的一种方式。这假定name列是每个嵌套data.frame中唯一的factor列。和@ josilber的回答一样,我选择的函数是toupper

rapply(data, function(x) toupper(as.character(x)), classes='factor', how='replace')

这将删除data.frame类,但保留了基本结构。如果您的名称列已经是character,那么您可以使用。

rapply(data, toupper, classes='character', how='replace')

答案 1 :(得分:2)

您可以将lapply函数嵌套两次以获取内部数据帧。在这里,我将toupper应用于每个name变量:

result <- lapply(data, function(x) {
  lapply(x, function(y) {
    y$name = toupper(y$name)
    return(y)
  })
})
result

# $yr2001
# $yr2001$type1
#   index  name
# 1     1  JACK
# 2     2  KING
# 3     3 LARRY
# 
# $yr2001$type2
#   index   name
# 1     1    MAN
# 2     2  WOMEN
# 3     3 OLIVER
# 4     4   JACK
# 5     5   JILL
# 
# 
# $yr2002
# $yr2002$type1
#   index  name
# 1     1 JANET
# 2     2  KING
# 3     3 LARRY
# 
# $yr2002$type2
#   index   name
# 1     1 ALBOYR
# 2     2   KING
# 3     3  LARRY
# 4     4 RACHEL
# 5     5    SAM
# 
# 
# $yr2003
# $yr2003$type1
#   index name
# 1     1  DAN
# 2     2  JAY
# 3     3 ZANG
# 
# $yr2003$type2
#   index  name
# 1     1  ZANG
# 2     2  KING
# 3     3 LARRY
# 4     4   KIM
# 5     5  FRAN

答案 2 :(得分:2)

为了说明(使用您的简化示例):

library(reshape2)
dat1 <- melt(data,id.vars = c("index","name"))
> dat1$NAME <- toupper(dat1$name)

答案 3 :(得分:1)

这是一个基于lapply的真正递归版本(即将使用更深层次的嵌套),除了您拥有的唯一类型的终端离开是数据帧之外,不做任何其他假设。不幸的是rapply不会停止data.frames的递归,所以如果你想操作数据框,你必须使用lapply(否则马修的答案是完美的)。

samp.recur <- function(x) 
  lapply(x, 
    function(y) 
      if(is.data.frame(y)) transform(y, name=toupper(name)) else samp.recur(y))

这会产生:

samp.recur(data)
# $yr2001
# $yr2001$type1
#   index  name
# 1     1  JACK
# 2     2  KING
# 3     3 LARRY

# $yr2001$type2
#   index   name
# 1     1    MAN
# 2     2  WOMEN
# 3     3 OLIVER
# 4     4   JACK
# 5     5   JILL

# etc...

虽然我也同意其他人的意见,但您可能需要考虑重新构建数据。