R 按组和列加权平均数
我希望获得几列(实际上大约60列)的加权平均数。这个问题非常类似于:刚问过 到目前为止,我提出了两种获得加权平均数的方法:R 按组和列加权平均数,r,for-loop,apply,sapply,R,For Loop,Apply,Sapply,我希望获得几列(实际上大约60列)的加权平均数。这个问题非常类似于:刚问过 到目前为止,我提出了两种获得加权平均数的方法: 对每列使用单独的sapply语句 将sapply语句放入for循环中 但是,我觉得必须有一种方法可以在sapply语句中插入apply语句,反之亦然,从而消除for循环。我尝试了许多排列,但都没有成功。我还研究了sweep函数 这是我到目前为止的代码 df <- read.table(text= " region state county
sapply
语句sapply
语句放入for循环中
sapply
语句中插入apply
语句,反之亦然,从而消除for循环
。我尝试了许多排列,但都没有成功。我还研究了sweep
函数
这是我到目前为止的代码
df <- read.table(text= "
region state county weights y1980 y1990 y2000
1 1 1 10 100 200 50
1 1 2 5 50 100 200
1 1 3 120 1000 500 250
1 1 4 2 25 100 400
1 1 4 15 125 150 200
2 2 1 1 10 50 150
2 2 2 10 10 10 200
2 2 2 40 40 100 30
2 2 3 20 100 100 10
", header=TRUE, na.strings=NA)
# add a group variable to the data set
group <- paste(df$region, '_', df$state, '_', df$county, sep = "")
df <- data.frame(group, df)
# obtain weighted averages for y1980, y1990 and y2000
# one column at a time using one sapply per column
sapply(split(df, df$group), function(x) weighted.mean(x$y1980, w = x$weights))
sapply(split(df, df$group), function(x) weighted.mean(x$y1990, w = x$weights))
sapply(split(df, df$group), function(x) weighted.mean(x$y2000, w = x$weights))
# obtain weighted average for y1980, y1990 and y2000
# one column at a time using a for-loop
y <- matrix(NA, nrow=7, ncol=3)
group.b <- df[!duplicated(df$group), 1]
for(i in 6:8) {
y[,(i-5)] <- sapply(split(df[,c(1:5,i)], df$group), function(x) weighted.mean(x[,6], w = x$weights))
}
# add weighted averages to the original data set
y2 <- data.frame(group.b, y)
colnames(y2) <- c('group','ave1980','ave1990','ave2000')
y2
y3 <- merge(df, y2, by=c('group'), all = TRUE)
y3
我建议使用包数据。表:
library(data.table)
dt <- as.data.table(df)
dt2 <- dt[,lapply(.SD,weighted.mean,w=weights),by=list(region,state,county)]
print(dt2)
region state county weights y1980 y1990 y2000
1: 1 1 1 10.00000 100.0000 200.0000 50.0000
2: 1 1 2 5.00000 50.0000 100.0000 200.0000
3: 1 1 3 120.00000 1000.0000 500.0000 250.0000
4: 1 1 4 13.47059 113.2353 144.1176 223.5294
5: 2 2 1 1.00000 10.0000 50.0000 150.0000
6: 2 2 2 34.00000 34.0000 82.0000 64.0000
7: 2 2 3 20.00000 100.0000 100.0000 10.0000
我想出了如何在
中嵌套sapply
以获得分组和列的加权平均值,而无需使用显式的for循环
。下面我提供了数据集、apply
语句以及apply
语句的工作原理说明
以下是原始帖子中的数据集:
df <- read.table(text= "
region state county weights y1980 y1990 y2000
1 1 1 10 100 200 50
1 1 2 5 50 100 200
1 1 3 120 1000 500 250
1 1 4 2 25 100 400
1 1 4 15 125 150 200
2 2 1 1 10 50 150
2 2 2 10 10 10 200
2 2 2 40 40 100 30
2 2 3 20 100 100 10
", header=TRUE, na.strings=NA)
# add a group variable to the data set
group <- paste(df$region, '_', df$state, '_', df$county, sep = "")
df <- data.frame(group, df)
下面是对上述apply
/sapply
语句的解释:
请注意,apply
语句一次选择df
的第6列到第8列
对于这三列中的每一列,我创建了一个新的数据框,将单个列与df
的前五列组合在一起
然后,我通过分组变量df$group
将每个新的6列数据帧分割成块
一旦一个由六列组成的数据帧被分割成单独的数据块,我计算每个数据块最后一列(第六列)的加权平均值
结果如下:
y1980 y1990 y2000
1_1_1 100.0000 200.0000 50.0000
1_1_2 50.0000 100.0000 200.0000
1_1_3 1000.0000 500.0000 250.0000
1_1_4 113.2353 144.1176 223.5294
2_2_1 10.0000 50.0000 150.0000
2_2_2 34.0000 82.0000 64.0000
2_2_3 100.0000 100.0000 10.0000
使用packagedata.table
很好,但是在我更加熟悉它的语法以及该语法与data.frame
的语法有何不同之前,我想知道如何使用apply
和sapply
来做同样的事情会很好。现在,我可以使用这两种方法,再加上原始帖子中的方法,检查其中一种方法与其他方法的优劣,并进一步了解所有方法。继续提问,但如果您提供一些虚拟数据并演示预期结果,我(我们?)将不胜感激。对不起。我已将数据集“y3”的内容添加到我的帖子中。虚拟数据在数据集“df”中,代码似乎在我的计算机上运行。此解决方案有点复杂,其性能可能不是很好(但我还没有进行基准测试)。你基本上是在试图重新发明轮子。如果您想要好的语法,您应该查看packageplyr
。我演示了data.table
解决方案,因为它在处理大数据集时速度更快。所有split-apply-combine函数都允许您指定多个分组变量。你的速度快了2.5倍。谢谢您的建议。如何限制仅在此处的一部分列上执行weighted.mean,例如list(y1980,y1990)
仅限?@FooBar Use.SDcols
。请参阅帮助(“data.table”)
。
df <- read.table(text= "
region state county weights y1980 y1990 y2000
1 1 1 10 100 200 50
1 1 2 5 50 100 200
1 1 3 120 1000 500 250
1 1 4 2 25 100 400
1 1 4 15 125 150 200
2 2 1 1 10 50 150
2 2 2 10 10 10 200
2 2 2 40 40 100 30
2 2 3 20 100 100 10
", header=TRUE, na.strings=NA)
# add a group variable to the data set
group <- paste(df$region, '_', df$state, '_', df$county, sep = "")
df <- data.frame(group, df)
apply(df[,6:ncol(df)], 2, function(x) {sapply(split(data.frame(df[,1:5], x), df$group), function(y) weighted.mean(y[,6], w = y$weights))})
y1980 y1990 y2000
1_1_1 100.0000 200.0000 50.0000
1_1_2 50.0000 100.0000 200.0000
1_1_3 1000.0000 500.0000 250.0000
1_1_4 113.2353 144.1176 223.5294
2_2_1 10.0000 50.0000 150.0000
2_2_2 34.0000 82.0000 64.0000
2_2_3 100.0000 100.0000 10.0000