基于特定条件过滤和添加的有效方法(在这种情况下为3个条件)

use*_*429 3 r plyr subset-sum dplyr data.table

我有一个看起来像这样的数据框

     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
Run Code Online (Sandbox Code Playgroud)

我有一个看起来像这样的数据框

     a    b    c   d
     1    1    1   250
     1    1    2   600
     1    2    3   150
     1    3    1   0
Run Code Online (Sandbox Code Playgroud)

我目前在做{

  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))
Run Code Online (Sandbox Code Playgroud)

}

我想添加'd'coloumn并通过计算行数而不计算0来取平均值.例如,第一行是(200 + 300)/ 2 = 250.目前我正在构建一个存储'的列表' d'coloumn但理想情况下我希望它采用上述格式.例如,第一行看起来像

     a    b    c   d
     1    1    1   250
Run Code Online (Sandbox Code Playgroud)

这是一种非常低效的方法来完成这项工作.代码需要很长时间才能在循环中运行.所以任何帮助都会受到赞赏,这会让它跑得更快.原始数据框有大约一百万行.

Hen*_*rik 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
Run Code Online (Sandbox Code Playgroud)

如@Roland所述,对于更大的数据集,您可以尝试data.tabledplyr替代,例如:

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
Run Code Online (Sandbox Code Playgroud)

编辑以下更新的问题.如果要计算分组均值,排除零行,您可以尝试这样做:

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
Run Code Online (Sandbox Code Playgroud)

但是,因为您似乎希望将零视为缺失值而不是数字零,我认为在计算之前将它们转换为NA准备数据集时会更好.

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
Run Code Online (Sandbox Code Playgroud)