2011-08-16 26 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) 
相關問題