R 基于分组对数据帧进行分组并对多列中的行进行平均,忽略零

R 基于分组对数据帧进行分组并对多列中的行进行平均,忽略零,r,dplyr,R,Dplyr,我的数据框数据如下所示: Week Group Cost Revenue Wk1 A 104 148 Wk1 A 0 159 Wk1 A 92 151 Wk1 A 113 144 Wk1 B 331 500 WK1 B 325 524 Wk1 B 363 488 Wk1 B 0 497 Wk2 A

我的数据框
数据
如下所示:

Week  Group   Cost   Revenue
Wk1   A       104    148
Wk1   A       0      159
Wk1   A       92     151
Wk1   A       113    144
Wk1   B       331    500
WK1   B       325    524
Wk1   B       363    488
Wk1   B       0      497
Wk2   A       132    0
.
.
.
以下是我从无序csv文件中获取的R代码:

library(dplyr)
d <- read.csv(...)
data <- tbl_df(d)
data <- arrange(data, Group, Week)
问题: 我如何平均我的专栏按他们的组和他们的星期分组,这样我就可以得到上面想要的结果?我想使用
dplyr
包来完成此操作

问题:
我的一些行有零。我不想求零的平均值(所以不是
(104+0+92+113)/4
,而是忽略它们,所以
(104+92+113)/3
)。我也不能简单地
filter()
将带有零的行过滤掉,因为通常情况下,我的成本或收入列中只有一列同时包含零而不是两列

我知道我可以使用
summary()
使用
mean()
进行平均,但不确定如何按照我需要的方式对平均值进行分组,并在计算中忽略零


谢谢

您可以使用
data.table
包。它确实快了100倍,更直观

您可以使用
fread
功能将csv文件读取到data.tables。但这里只是一个例子

DT = data.table(Week = c("wk1","wk2"),  Group = c("A","B","C","D"),   Cost = sample(1:49,30,replace=F),   Revenue = sample(1:49,10,replace=F))
#    Week Group Cost Revenue
# 1:  wk1     A   33      37
# 2:  wk2     B   17      28
# 3:  wk1     C   13       6
# 4:  wk2     D   39      25
# 5:  wk1     A   15       3
# 6:  wk2     B   34       8
# 7:  wk1     C    2      12
# 8:  wk2     D    9      11
# 9:  wk1     A   48      18
#10:  wk2     B   25      29
#11:  wk1     C   46      37
#12:  wk2     D   11      28
#13:  wk1     A   22       6
#14:  wk2     B    6      25
#15:  wk1     C   26       3
#16:  wk2     D   40       8
#17:  wk1     A   27      12
#18:  wk2     B   23      11
#19:  wk1     C   43      18
#20:  wk2     D   24      29
#21:  wk1     A   21      37
#22:  wk2     B   29      28
#23:  wk1     C   31       6
#24:  wk2     D    8      25
#25:  wk1     A   36       3
#26:  wk2     B    5       8
#27:  wk1     C    1      12
#28:  wk2     D   19      11
#29:  wk1     A    4      18
#30:  wk2     B   44      29
#    Week Group Cost Revenue
在下一行中,您应该定义用于分组的列;这里我使用
c(“周”、“组”)

有关更多信息,请参阅数据表软件包手册:

为了忽略
mean
函数中的零,可以将其替换为
nzmean
。请参阅本帖:


没有任何附加包的解决方案:

# Define a non-zero means function
nzmean <- function(x) {
  zvals <- x==0
  if (all(zvals)) 0 else mean(x[!zvals])
}
我想我应该添加一个dplyr答案

首先,您可以在
摘要
中执行此操作,使用提取功能(
[
)分别从
成本
收入
中删除任何0值

就打字效率而言,
summary\u each
是另一个有用的选项,在这种情况下,您需要在多个列上使用相同的函数。您可以利用
编码在取
平均值时从每个数值变量中删除任何0值

dat %>% group_by(Week, Group) %>%
    summarise_each(funs(mean(.[. > 0])))

您想使用
dplyr
package有什么特别的原因吗?它直观、实用(在编程范例的意义上),我正在努力更好地学习。虽然我对其他技术持开放态度。我喜欢这种方法,但如果成本或收入列中有一些0呢?我需要忽略平均值函数中的0。你可以用定义的函数替换
mean
。请看这篇文章:用
nzmean
替换
mean
,其中
nz@MahdiJadaliha是一个很好的答案,但是你在没有证据的情况下做了两个陈述:data.table“确实比原来快了100倍,而且更直观”。如果你想让我们相信它更快,至少你可以链接到另一个帖子作为证据。说到直觉,好吧,我来判断一下:-)@BarkleyBG,datatable仍然是最快的(在大多数情况下,100倍可能是夸张的)。下面是性能基准的链接:
nzmean <- function(x) {
   zvals <- x==0
   if (all(zvals)) 0 else mean(x[!zvals])
}
DT[,list(Avg_Cost = nzmean(Cost),Avg_Revenue = nzmean(Revenue)),by = c("Week", "Group")]
# Define a non-zero means function
nzmean <- function(x) {
  zvals <- x==0
  if (all(zvals)) 0 else mean(x[!zvals])
}
tapply(df$Cost,list(df$Week,df$Group),nzmean )
require(dplyr)

dat %>% group_by(Week, Group) %>%
    summarise(Cost = mean(Cost[Cost > 0]), Revenue = mean(Revenue[Revenue > 0]))
dat %>% group_by(Week, Group) %>%
    summarise_each(funs(mean(.[. > 0])))