我有以下表单的数据框 列表:
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)
我可以看到如何用for循环来做这件事......
...或者通过创建每个变量的数据框,
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)
...
但这比我更喜欢复制并且看起来不像惯用的R;所以我试图用其中一个应用函数来做。
由于这是一个列表,lapply似乎是正确的,除了它似乎跨越了错误的边界 - 也就是说,它在列表中意味着,而不是列表中的平均值。 / p>
> lapply(mylist, FUN=mean)
$df1
[1] NA
$df2
[1] NA
Warning messages:
1: In mean.default(X[[1L]], ...) :
argument is not numeric or logical: returning NA
2: In mean.default(X[[2L]], ...) :
argument is not numeric or logical: returning NA
对于另一个边距,交叉列表而不是列表中没有设置lapply。
定期应用,这让我设置一个边距,这是一个列表,而不是矩阵或数据框。
> apply(mylist, MARGIN = 2, FUN=mean)
Error in apply(mylist, MARGIN = 2, FUN = mean) :
dim(X) must have a positive length
(我的实际列表有超过2个数据帧,所以很多更简单的loopy或merge-y解决方案很快就会变得多毛 - 或者至少我对循环太笨拙了over getattribute东西知道如何干净地完成N的长度。)
我是否会在一个解决这个问题的rapply,tapply,eapply,* apply函数中缺少某些东西,或者一般来说我是愚蠢的东西?
更新
感谢大家提供的有用答案。当我测试Amelia库进行多次插补时,我遇到了这个问题,并且想要了解模拟时刻的长期传播方式。 (它们返回的对象形状如下,并且具有与原始数据框相对应的上述属性,并且没有丢失的数据。)
Here's a gist我整理了它。
我喜欢user20650的答案不需要额外的复制(gist中的imputer2),所以当我开始扩展到1000的列表时,它变得比需要合并新数据帧的速度快得多。
什么是古怪的,我还没有完全解决的是,我运行的imputer1与imputer2产生的值看起来相同,但是a == b是假的。我假设一个四舍五入的问题。
我还在寻找一种方法在这个结构上应用像mean或sd这样的通用函数(没有复制),而不是逐项计算它们,但无论如何我的问题已经解决了,我会把它留给另一个问题。
答案 0 :(得分: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)
答案 1 :(得分: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
答案 2 :(得分: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)
。
答案 3 :(得分: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)
答案 4 :(得分:1)
(我认为)如果每个数据框中的某些变量不同或者它们的顺序不同,那么之前的答案将会失败(当然是我之前的答案)。下面是一个相当可怕的功能,但似乎有效。
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)
答案 5 :(得分:0)
使用@ user20650&#39>测试。两个相等数字的平均值应该是相同的数字。
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代码:对于每个列名,我们使用数字索引来获取数据帧和字符索引以获取列,然后这些列被绑定&#39;一起传递给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