我有一个看起来像这样的数据框
a b c d
1 1 1 0
1 1 1 200
1 1 1 300
1 1 2 0
1 1 2 600
1 2 3 0
1 2 3 100
1 2 3 200
1 3 1 0
我有一个看起来像这样的数据框
a b c d
1 1 1 250
1 1 2 600
1 2 3 150
1 3 1 0
我目前正在这样做 {
n=nrow(subset(Wallmart, a==i & b==j & c==k ))
sum=subset(Wallmart, a==i & b==j & c==k )
#sum
sum1=append(sum1,sum(sum$d)/(n-1))
}
我想添加' d' coloumn并通过计算行数而不计算0来取平均值。例如,第一行是(200 + 300)/ 2 = 250。 目前我正在建立一个存储“' d”的列表。 coloumn但理想情况下我想要它以上面的格式。例如,第一行看起来像
a b c d
1 1 1 250
这是一种非常低效的方法来完成这项工作。代码需要很长时间才能在循环中运行。 所以任何帮助都会受到赞赏,这会让它跑得更快。原始数据框有大约一百万行。
答案 0 :(得分:6)
您可以尝试aggregate
:
aggregate(d ~ a + b + c, data = df, sum)
# a b c d
# 1 1 1 1 500
# 2 1 3 1 0
# 3 1 1 2 600
# 4 1 2 3 300
正如@Roland所述,对于更大的数据集,您可以尝试data.table
或dplyr
,例如:
library(dplyr)
df %>%
group_by(a, b, c) %>%
summarise(
sum_d = sum(d))
# Source: local data frame [4 x 4]
# Groups: a, b
#
# a b c sum_d
# 1 1 1 1 500
# 2 1 1 2 600
# 3 1 2 3 300
# 4 1 3 1 0
更新后的问题修改。 如果要计算分组均值,排除零行,可以尝试:
aggregate(d ~ a + b + c, data = df, function(x) mean(x[x > 0]))
# a b c d
# 1 1 1 1 250
# 2 1 3 1 NaN
# 3 1 1 2 600
# 4 1 2 3 150
df %>%
filter(d != 0) %>%
group_by(a, b, c) %>%
summarise(
mean_d = mean(d))
# a b c mean_d
# 1 1 1 1 250
# 2 1 1 2 600
# 3 1 2 3 150
但是,因为您似乎希望将零视为缺失值而不是数字零,我认为在准备数据集时将它们转换为NA
会更好 > em>计算。
df$d[df$d == 0] <- NA
df %>%
group_by(a, b, c) %>%
summarise(
mean_d = mean(d, na.rm = TRUE))
# a b c mean_d
# 1 1 1 1 250
# 2 1 1 2 600
# 3 1 2 3 150
# 4 1 3 1 NaN
答案 1 :(得分:3)
这是您上次编辑的data.table
解决方案。
library(data.table)
DT <- setDT(df)[, if(any(d[d > 0])) mean(d[d > 0]) else 0, by = c("a","b","c")]
# a b c V1
# 1: 1 1 1 250
# 2: 1 1 2 600
# 3: 1 2 3 150
# 4: 1 3 1 0
setDT(df)[, mean(d[d > 0]), by = c("a","b","c")][is.nan(V1), V1 := 0]
@eddis建议
setDT(df)[, sum(d) / pmax(1, sum(d > 0)), by = list(a, b, c)]
答案 2 :(得分:2)
这是另一种方式:
步骤1:设置数据表:
df <- read.table(text=" a b c d
1 1 1 0
1 1 1 200
1 1 1 300
1 1 2 0
1 1 2 600
1 2 3 0
1 2 3 100
1 2 3 200
1 3 1 0",header=T)
library(data.table)
setDT(df)
setkey(df,a,b,c)
第二步:做计算:
df[,sum(d)/ifelse((cnt=length(which(d>0)))>0,cnt,1),by=key(df)]
请注意,此处不建议循环。 最佳策略是对解决方案进行矢量化,如上例所示。
步骤3:让我们测试时间:
> dt<-df
> for(i in 1:20) dt <- rbind(dt,dt)
> dim(dt)
[1] 9437184 4
> setkey(dt,a,b,c)
> dt[,sum(d)/ifelse((cnt=length(which(d>0)))>0,cnt,1),by=key(dt)]
a b c V1
1: 1 1 1 250
2: 1 1 2 600
3: 1 2 3 150
4: 1 3 1 0
> system.time(dt[,sum(d)/ifelse((cnt=length(which(d>0)))>0,cnt,1),by=key(dt)])
user system elapsed
0.495 0.090 0.609
所以近0.5M记录的计算大约需要0.5秒!
希望这会有所帮助!!