2014-03-30 67 views
1

數據幀我有一個列表數據幀的形式如下功能數據幀的列表的,也返回中的R

str(mylist) 
List of 2 
$ df1:'data.frame': 50 obs. of 4 variables: 
    ..$ var1: num [1:50] 0.114 0.622 0.609 0.623 0.861 ... 
    ..$ var2: num [1:50] -1.221 1.819 0.195 1.232 0.786 ... 
    ..$ var3: num [1:50] -0.14 -1.003 -0.352 0.647 0.424 ... 
    ..$ Y : num [1:50] -1.24 1.38 0.3 2.44 2.09 ... 
$ df2:'data.frame': 50 obs. of 4 variables: 
    ..$ var1: num [1:50] 0.114 0.622 0.609 0.623 0.861 ... 
    ..$ var2: num [1:50] -1.221 1.819 0.195 1.232 0.786 ... 
    ..$ var3: num [1:50] -0.14 -1.003 -0.352 0.647 0.424 ... 
    ..$ Y : num [1:50] -1.24 1.38 0.3 2.44 2.09 ... 
- attr(*, "class")= chr [1:2] "mi" "list" 

我試圖返回的手段對應於正確的變量,也可以作爲一個數據幀列表中的數據幀,看起來像:

> str(dfnew) 
'data.frame': 50 obs. of 4 variables: 
$ var1: num 0.114 0.622 0.609 0.623 0.861 ... 
$ var2: num -1.221 1.819 0.195 1.232 0.786 ... 
$ var3: num -0.14 -1.003 -0.352 0.647 0.424 ... 
$ Y : num -1.24 1.38 0.3 2.44 2.09 ... 

所以,東西做...

dfnew[1,1] <- mean(mylist[[1]]$var1[1], mylist[[2]]$var1[1], na.rm=T) 
dfnew[2,1] <- mean(mylist[[1]]$var1[2], mylist[[2]]$var1[2], na.rm=T) 
... 
dfnew[50,1] <- mean(mylist[[1]]$var1[50], mylist[[2]]$var1[50], na.rm=T) 
... 
dfnew[1,2] <- mean(mylist[[1]]$var2[1], mylist[[2]]$var2[1], na.rm=T) 
... 
dfnew[50,4] <- mean(mylist[[1]]$var4[50], mylist[[2]]$var4[50], na.rm=T) 

我可以看到我是如何用一個循環做到這一點...

...或者通過創建每個變量的數據幀,

var1df <- cbind(df1$var1, df2$var1) 
var2df <- cbind(df1$var2, df2$var2) # and if there are up to var1000?... 
... 
dfnew$var1 <- rowMeans(var1df) 
dfnew$var2 <- rowMeans(var2df) 
... 

但是這以上的複製比我」 d喜歡,似乎比慣用的R更少;所以我正在嘗試使用其中一個應用函數來完成它。

由於這是一個列表,lapply似乎是正確的,只是它似乎跨越了錯誤的邊界---也就是說,它是在列表中的含義,而不是列表中的均值。

​​

對於其他保證金,交叉列表而非列表中沒有設置lapply。

並定期申請,這讓我設置一個保證金是令人不安的,這是一個列表,而不是一個矩陣或數據框。

> apply(mylist, MARGIN = 2, FUN=mean) 
Error in apply(mylist, MARGIN = 2, FUN = mean) : 
    dim(X) must have a positive length 

(我的實際列表有很多超過2個數據幀,所以很多容易糊塗或合併-Y方案得到那種毛茸茸的很快---或者至少,我有太多笨拙循環結束getattribute的東西,知道如​​何做到乾淨的長度爲N.)

有什麼我失蹤的其中一個rapply,tapply,eapply,*應用函數,可以解決這個問題,或一般的東西我很愚蠢?

UPDATE

感謝大家的幫助的答案。當我測試Amelia庫進行多重歸責時,我遇到了這個問題,並想看看模擬時刻的傳播是來自長期手段。 (它們返回的對象是這樣形狀的,並且具有上述對應於原始數據框的屬性,並且沒有丟失數據。)

Here's a gist我把它湊在一起擺弄它。

我喜歡user20650的回答並不需要額外的複製(在要點imputer2),所以當我開始擴展到1000列表時,它變得比要求合併新數據幀的速度快得多。

什麼是古怪的,我還沒有完全解決的是,我運行imputer1與imputer2運行的值看起來相同,但其中a == b是錯誤的。我假設一個舍入問題。

我也還在尋找一種方式,在這個結構應用等表示或SD基本功能(不復制),而不是itemwise計算它們,但無論如何,我的問題解決了,我把它留給另一個問題。

+0

你應該從一個小例子開始,手工完成。我不認爲你的尺寸正確。 –

+0

你能解釋一下你的意思嗎? – Mittenchops

+0

我打算輸出的尺寸與每個列表的尺寸相同。我想你可能誤解了這個問題。 – Mittenchops

回答

2
# data 
l <- list(df1 = mtcars[1:5,1:5] , df2 = mtcars[1:5,1:5], df3 = mtcars[1:5,1:5]) 

# note you can just add dataframes eg 
o1 <- (l[[1]] + l[[2]] + l[[3]])/3 

# So if you have many df in list - to get the average by summing and dividing by list length 
f <- function(x) Reduce("+", x) 
o2 <- f(l)/length(l) 

all.equal(o1,o2) 
+0

我很喜歡這種方法,但我有點困惑,爲什麼當我嘗試直接使用Reduce(mean,mylist)或Reduce(rowMeans,mylist)時出現錯誤。 – Mittenchops

+1

我認爲這試圖採取整個數據幀的意思 - 這是行不通的。嘗試mean(l [[1]])或者甚至意味着(mtcars)。希望有人可以提供更全面的答案 – user20650

1

嘗試合併,然後計算出你的手段:

df <- Reduce(rbind, lapply(mylist, function(df) { 
    df$id <- seq_len(nrow(df)) 
    df 
})) 
df <- aggregate(. ~ id, df, mean)[, -1] 

mylist <- lapply(seq_len(3), function(x) iris[, 1:4] + runif(1, 0, 1)) 
sapply(seq_len(3), function(i) mylist[[i]][1,1]) 
# [1] 5.368424 6.097071 5.681132 
# Apply above code 
head(df) 
# Sepal.Length Sepal.Width Petal.Length Petal.Width 
# 1  5.715542 4.115542  2.015542 0.8155424 
# 2  5.515542 3.615542  2.015542 0.8155424 
# 3  5.315542 3.815542  1.915542 0.8155424 
# 4  5.215542 3.715542  2.115542 0.8155424 
# 5  5.615542 4.215542  2.015542 0.8155424 
# 6  6.015542 4.515542  2.315542 1.0155424 

注意mean(c(5.368424, 6.097071, 5.681132)) = 5.715542)

1

這裏是mapply一個選項:

as.data.frame(mapply(function(a, b) (a + b)/2, df.lst[[1]], df.lst[[2]])) 

這將爲任意數量的列工作。 mapply將循環遍歷每個數據幀的每列。

下面是我們使用的數據:

df.lst <- replicate(2, data.frame(var1=runif(10), var2=sample(1:10)), simplify=F) 
0

測試與@ user20650的例子。兩個相同數字的平均值應該是相同的數字。

as.data.frame(setNames(
     lapply(names(mylist[[1]]), function (nm){ 
       rowMeans(cbind(mylist[[1]][[nm]], mylist[[2]][[nm]])) }), 
     names(mylist[[1]] 
     ))) 
#-------------- 
    mpg cyl disp hp drat 
1 21.0 6 160 110 3.90 
2 21.0 6 160 110 3.90 
3 22.8 4 108 93 3.85 
4 21.4 6 258 110 3.08 
5 18.7 8 360 175 3.15 

您閱讀裏面的R代碼:對於每一列的名字,我們使用數字索引來獲得dataframes和字符索引獲得的列,然後將它們「C綁定」在一起,並傳遞給rowMeans 。然後給這個rowMean -ed值列表賦予setNames名稱並最終轉換爲數據幀。

請注意,這不會獲得超過兩個列表中的所有數據幀......只有前兩個被考慮。

> str(mylist) 
List of 3 
$ df1:'data.frame': 5 obs. of 5 variables: 
    ..$ mpg : num [1:5] 21 21 22.8 21.4 18.7 
    ..$ cyl : num [1:5] 6 6 4 6 8 
    ..$ disp: num [1:5] 160 160 108 258 360 
    ..$ hp : num [1:5] 110 110 93 110 175 
    ..$ drat: num [1:5] 3.9 3.9 3.85 3.08 3.15 
$ df2:'data.frame': 5 obs. of 5 variables: 
    ..$ mpg : num [1:5] 21 21 22.8 21.4 18.7 
    ..$ cyl : num [1:5] 6 6 4 6 8 
    ..$ disp: num [1:5] 160 160 108 258 360 
    ..$ hp : num [1:5] 110 110 93 110 175 
    ..$ drat: num [1:5] 3.9 3.9 3.85 3.08 3.15 
$ df3:'data.frame': 5 obs. of 5 variables: 
    ..$ mpg : num [1:5] 21 21 22.8 21.4 18.7 
    ..$ cyl : num [1:5] 6 6 4 6 8 
    ..$ disp: num [1:5] 160 160 108 258 360 
    ..$ hp : num [1:5] 110 110 93 110 175 
    ..$ drat: num [1:5] 3.9 3.9 3.85 3.08 3.15 
1

(我認爲)以前的答案將會失敗(當然我以前的一樣),如果一些變量是在每個dataframes的不同,或者如果它們以不同的順序。下面一個相當可怕的功能,但它似乎工作。

l <- list(df1 = mtcars[1:5,1:5] , df2 = mtcars[1:5,1:5], df3 = mtcars[1:5,1:5]) 

# Allow for different variables 
l2 <- list(df1 = mtcars[1:5,1:5] , df2 = mtcars[1:5,2:6], df3 = mtcars[1:5,4:7]) 

new.f <- function(lst) { 
       l <- lst 
       un.nm <- unique(unlist(lapply(l , names))) 
       o <- lapply(un.nm , function(x) { 
         lapply(l , function(z) { 
           if(x %in% names(z)) z[x] else NA 
          }) 
         }) 
       # combine for each variable 
       l <- lapply(o , function(x) do.call(cbind, x)) 
       mn <- lapply(l , rowMeans , na.rm=TRUE) 
     names(mn) <- lapply(l ,function(i) unique(names(i)[names(i) %in% un.nm])) 
       data.frame(do.call(cbind , mn)) 
      } 


all.equal(f(l)/length(l) , new.f(l)) 

f(l2) # fails 
# Error in Ops.data.frame(init, x[[i]]) : 
    #+ only defined for equally-sized data frames 

new.f(l2) 

編輯

這個例子在這裏Join matrices by both colnames and rownames in R提供了一個更簡潔的方式,如果有在每個列表元素的不同列做到這一點。

l <- lapply(l2 , function(i) as.data.frame(as.table(as.matrix(i)))) 
tmp <- do.call(rbind , l) 
tmp <- aggregate(Freq ~ Var1 + Var2, tmp, mean) 
xtabs(Freq ~ Var1 + Var2, tmp) 
2

又一選擇,該列表l轉換爲陣列a(使用方法建議here)以及在所述第一兩名維適用mean。這假定l中的所有數據幀具有一致的結構。在這裏,我再次使用@ user20650的示例列表。

l <- list(df1=mtcars[1:5, 1:5], df2=mtcars[1:5, 1:5], df3=mtcars[1:5, 1:5]) 
a <- array(unlist(l), dim=c(nrow(l[[1]]), ncol(l[[1]]), length(l)), 
      dimnames=c(dimnames(l[[1]]), list(names(l)))) 
apply(a, 1:2, mean) 

        mpg cyl disp hp drat 
Mazda RX4   21.0 6 160 110 3.90 
Mazda RX4 Wag  21.0 6 160 110 3.90 
Datsun 710  22.8 4 108 93 3.85 
Hornet 4 Drive 21.4 6 258 110 3.08 
Hornet Sportabout 18.7 8 360 175 3.15