R 使用列表中数据帧的加权平均值创建新数据帧
我有许多数据帧存储在一个列表中,我想从这些数据帧中创建加权平均值,并将结果存储在一个新的数据帧中。例如,使用列表:R 使用列表中数据帧的加权平均值创建新数据帧,r,R,我有许多数据帧存储在一个列表中,我想从这些数据帧中创建加权平均值,并将结果存储在一个新的数据帧中。例如,使用列表: dfs <- structure(list(df1 = structure(list(A = 4:5, B = c(8L, 4L), Weight = c(TRUE, TRUE), Site = c("X", "X")), .Names = c("A", "B", "Weight", "Site")
dfs <- structure(list(df1 = structure(list(A = 4:5, B = c(8L, 4L), Weight = c(TRUE, TRUE), Site = c("X", "X")),
.Names = c("A", "B", "Weight", "Site"), row.names = c(NA, -2L), class = "data.frame"),
df2 = structure(list(A = c(6L, 8L), B = c(9L, 4L), Weight = c(FALSE, TRUE), Site = c("Y", "Y")),
.Names = c("A", "B", "Weight", "Site"), row.names = c(NA, -2L), class = "data.frame")),
.Names = c("df1", "df2"))
上面只是一个非常简单的例子,但我的真实数据在列表中有许多数据帧,并且比我想要计算加权平均值的a
和B
更多的列。我还有几个类似于Site
的列,它们在每个数据帧中都是常量,我希望移动到结果
我可以使用以下方法手动计算加权平均值
weighted.mean(dfs$df1$A, dfs$df1$Weight)
weighted.mean(dfs$df1$B, dfs$df1$Weight)
weighted.mean(dfs$df2$A, dfs$df2$Weight)
weighted.mean(dfs$df2$B, dfs$df2$Weight)
但我不确定如何以一种更短、更少“手动”的方式完成这项工作。有人有什么建议吗?我最近学会了如何在列表中跨数据帧
lappy
,但到目前为止,我的尝试还不太成功 诀窍是创建一个适用于单个data.frame的函数,然后使用lappy
在列表中迭代。由于lappy
返回一个列表,因此我们将使用do.call
将结果对象合并到一起:
foo <- function(data, meanCols = LETTERS[1:2], weightCol = "Weight", otherCols = "Site") {
means <- t(sapply(data[, meanCols], weighted.mean, w = data[, weightCol]))
sumWeight <- sum(data[, weightCol])
others <- data[1, otherCols, drop = FALSE] #You said all the other data was constant, so we can just grab first row
out <- data.frame(others, means, sumWeight)
return(out)
}
既然您说这是一个最小的示例,那么这里有一种方法可以将其扩展到其他列。我们将使用grepl()
并使用正则表达式来标识正确的列。或者,您可以将它们全部写在一个向量中。大概是这样的:
do.call(rbind, lapply(dfs, foo,
meanCols = grepl("A|B", names(dfs[[1]])),
otherCols = grepl("Site", names(dfs[[1]]))
))
使用
dplyr
library(dplyr)
library('devtools')
install_github('hadley/tidyr')
library(tidyr)
unnest(dfs) %>%
group_by(Site) %>%
filter(Weight) %>%
mutate(Sum=n()) %>%
select(-Weight) %>%
summarise_each(funs(mean=mean(., na.rm=TRUE)))
给出了结果
# Site A B Sum
#1 X 4.5 6 2
#2 Y 8.0 4 1
或使用data.table
library(data.table)
DT <- rbindlist(dfs)
DT[(Weight)][, c(lapply(.SD, mean, na.rm = TRUE),
Sum=.N), by = Site, .SDcols = c("A", "B")]
# Site A B Sum
#1: X 4.5 6 2
#2: Y 8.0 4 1
我有
每个人的总结(funs(weighted.mean(,Weight)),list(quote(-Weight))
,但我不能用这种方式处理权重。是否可以对每个摘要中的特定列应用不同的FUN?例如,我们是否可以在summary\u each\u q
中为A和B应用weighted.mean(,Weight)
,为Weight
应用summary\u each\u q
在dplyr\u 0.3
中不推荐使用sum()。对于特定的列,我无法使用summary\u each\u
获得成功。啊,是这样吗?知道这件事很好。谢谢你的更新。@jazzurro没问题。很高兴它帮助了你。谢谢阿克伦,我真的很感谢你的帮助!谢谢Chase,我现在理解得更好了,并且能够在我更大的数据集中实现这一点。再次感谢!
# Site A B Sum
#1 X 4.5 6 2
#2 Y 8.0 4 1
library(data.table)
DT <- rbindlist(dfs)
DT[(Weight)][, c(lapply(.SD, mean, na.rm = TRUE),
Sum=.N), by = Site, .SDcols = c("A", "B")]
# Site A B Sum
#1: X 4.5 6 2
#2: Y 8.0 4 1
unnest(dfs) %>%
group_by(Site) %>%
summarise_each(funs(weighted.mean=stats::weighted.mean(., Weight),
Sum.Weight=sum(Weight)), -starts_with("Weight")) %>%
select(Site:B_weighted.mean, Sum.Weight=A_Sum.Weight)
# Site A_weighted.mean B_weighted.mean Sum.Weight
#1 X 4.5 6 2
#2 Y 8.0 4 1