2011-08-16 27 views
13

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

编辑:“在我的真实代码中,数据帧变量是通过使用以下代码读取多个文件而创建的,所以我没有实际名称,只有'files.to.read'列表中的实际名称,我不确定 Working-with-dataframes-in-a-list-drop-variables-add-new-onesUsing-lapply-with-changing-arguments

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

mylist <- llply(files.to.read, read.csv) 

的几种方法已经在几个职位得到强调:如果他们将数据帧顺序排列

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 

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

# 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 

但是names()函数在数据框列表上不起作用;它返回NULL。 我可以在第一个示例中使用seq_along(mylist)。

任何意见或更好的方式来处理整个“带源ID合并”

编辑 - 添加解决方案如下:我实现了使用哈德利暗示和汤米的轻推它看起来像一个解决方案。

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)) 

我用于每个数据帧

我也使用merge_recurse(),因为它是由于某种原因,非常缓慢的改变files.to.read矢量作为id。

all <- merge_recurse(mylist) 

谢谢大家。

回答

16

就个人而言,我认为这是比较容易的名字崩溃后添加:

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)) 
+0

谢谢我不确定崩溃是否会保留订单。为了使用qplot()来折叠列表并通过$ id指定子集。不过,它崩溃的速度非常缓慢,所以我愿意接受其他选择。 –

+0

哇,我在我的实际代码中使用了rbind()而不是merge_recurse(),总时间从〜10分钟减少到10秒。 –

2

names()可以工作它有名字,但你没有给它任何。这是一个未命名的列表。您需要使用数字索引:

> for(i in 1:length(mylist)){ mylist[[i]] <- cbind(mylist[[i]], id=rep(i, nrow(mylist[[i]]))) } 
> mylist 
[[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 
+0

感谢。在汤米,哈德利和你自己之间,我创造了一个合适的解决方案。我最终希望在这个过程中进一步确认名称。 –

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 
) 
+0

谢谢你回答这两个问题。我编辑了我的问题,说明我没有名字,但我确实是这样。将files.to.read转换为列表允许我为每个列表元素分配相应的名称,以便它们正确对齐......我没有看到树木的树林! –

1

dlply函数形式plyr包应该是一个答案:

library('plyr') 
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 <- ldply(mylist) 
相关问题