列表中的数据帧; 添加名为dataframe的新变量

Loo*_*eft 15 r list names lapply dataframe

我有一个数据帧列表,我最终想要合并,同时保留其原始数据帧名称或列表索引的记录.这将允许我跨所有行的子集等.为了实现这一点,我想为每个数据帧添加一个新的变量"id",其中包含它所属的数据帧的名称/索引.

编辑:"在我的真实代码中,数据框变量是通过使用以下代码读取多个文件而创建的,所以我没有实际名称只有'files.to.read'列表中的那些我不确定它们是否会对齐使用数据框顺序:

mylist <- llply(files.to.read, read.csv)
Run Code Online (Sandbox Code Playgroud)

在几个帖子中突出了一些方法: 使用数据框架在列表中的drop-variables-add-new-ones使用lapply-with-changing-arguments

我尝试了两种类似的方法,第一种使用索引列表:

df1 <- data.frame(x=c(1:5),y=c(11:15))
df2 <- data.frame(x=c(1:5),y=c(11:15))
mylist <- list(df1,df2)

# Adds a new coloumn 'id' with a value of 5 to every row in every dataframe.
# I WANT to change the value based on the list index.
mylist1 <- lapply(mylist, 
    function(x){
        x$id <- 5
        return (x)
    }
)
#Example of what I WANT, instead of '5'.
#> mylist1
#[[1]]
  #x  y id
#1 1 11  1
#2 2 12  1
#3 3 13  1
#4 4 14  1
#5 5 15  1
#
#[[2]]
  #x  y id
#1 1 11  2
#2 2 12  2
#3 3 13  2
#4 4 14  2
#5 5 15  2
Run Code Online (Sandbox Code Playgroud)

第二次尝试传递列表的名称().

# I WANT it to add a new coloumn 'id' with the name of the respective dataframe
# to every row in every dataframe.
mylist2 <- lapply(names(mylist), 
    function(x){
        portfolio.results[[x]]$id <- "dataframe name here"
        return (portfolio.results[[x]])
    }
)
#Example of what I WANT, instead of 'dataframe name here'.
# mylist2
#[[1]]
  #x  y id
#1 1 11  df1
#2 2 12  df1
#3 3 13  df1
#4 4 14  df1
#5 5 15  df1
#
#[[2]]
  #x  y id
#1 1 11  df2
#2 2 12  df2
#3 3 13  df2
#4 4 14  df2
#5 5 15  df2
Run Code Online (Sandbox Code Playgroud)

但是names()函数不适用于数据帧列表; 它返回NULL.我可以在第一个例子中使用seq_along(mylist)吗?

处理整个"与源ID合并"的任何想法或更好的方法

编辑 - 下面添加的解决方案:我已经使用Hadleys建议和Tommy的推动实现了一个解决方案,看起来像这样.

files.to.read <- list.files(datafolder, pattern="\\_D.csv$", full.names=FALSE)
mylist <- llply(files.to.read, read.csv)
all <- do.call("rbind", mylist)
all$id <- rep(files.to.read, sapply(mylist, nrow))
Run Code Online (Sandbox Code Playgroud)

我使用files.to.read向量作为每个数据帧的id

我也改变了使用merge_recurse()因为某些原因它非常慢.

 all <- merge_recurse(mylist)
Run Code Online (Sandbox Code Playgroud)

感谢大家.

had*_*ley 18

就个人而言,我认为崩溃后添加名称更容易:

df1 <- data.frame(x=c(1:5),y=c(11:15))
df2 <- data.frame(x=c(1:5),y=c(11:15))
mylist <- list(df1 = df1, df2 = df2)

all <- do.call("rbind", mylist)
all$id <- rep(names(mylist), sapply(mylist, nrow))
Run Code Online (Sandbox Code Playgroud)


Tom*_*mmy 8

你的第一次尝试非常接近.通过使用索引而不是值,它将起作用.您的第二次尝试失败,因为您没有为列表中的元素命名.

下面的两个解决方案都使用lapply可以将额外参数(mylist)传递给函数的事实.

df1 <- data.frame(x=c(1:5),y=c(11:15))
df2 <- data.frame(x=c(1:5),y=c(11:15))
mylist <- list(df1=df1,df2=df2) # Name each data.frame!
# names(mylist) <- c("df1", "df2") # Alternative way of naming...

# Use indices - and pass in mylist
mylist1 <- lapply(seq_along(mylist), 
        function(i, x){
            x[[i]]$id <- i
            return (x[[i]])
        }, mylist
)

# Now the names work - but I pass in mylist instead of using portfolio.results.
mylist2 <- lapply(names(mylist), 
    function(n, x){
        x[[n]]$id <- n
        return (x[[n]])
    }, mylist
)
Run Code Online (Sandbox Code Playgroud)