我的数据框data
如下所示:
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)
我需要根据数据框所属的组和周来平均数据框的“成本”和“收入”列中的值。
例如,我想要第1周A组的平均收入和成本。
结果值看起来像(我不确定格式,只显示我应该得到的值):
Week Group Avg Cost Avg Revenue
Wk1 A 103 150.5
Wk1 B 339.6 502.25
.
.
.
问题:
如何按照组和他们的周对我的列进行平均,以便获得上述所需的结果?我想使用dplyr
包来执行此操作。
的问题:
我的一些行有零。我不想平均零(所以不是(104 + 0 + 92 + 113)/4
而是忽略它们(104 + 92 + 113)/3
)。我不能简单filter()
出零的行,因为我的Cost或Revenue列中只有一个零而不是两者都有。
我知道我可以使用summarize()
与mean()
进行平均,但不知道如何按照我需要的方式对手段进行分组,并在计算中忽略零。
谢谢!
答案 0 :(得分:4)
我以为我会添加 dplyr 答案。
首先,您可以在summarise
内执行此操作,使用提取函数(Cost
)分别从Revenue
和[
删除任何0值。
require(dplyr)
dat %>% group_by(Week, Group) %>%
summarise(Cost = mean(Cost[Cost > 0]), Revenue = mean(Revenue[Revenue > 0]))
就打字效率而言,summarise_each
是另一个有用的选项,在这种情况下你想在多个列上使用相同的功能。在您使用.
时,您可以利用mean
编码从每个数字变量中删除任何0值。
dat %>% group_by(Week, Group) %>%
summarise_each(funs(mean(.[. > 0])))
答案 1 :(得分:1)
您可以使用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("Week", "Group")
DT[,list(Avg_Cost = mean(Cost),Avg_Revenue = mean(Revenue)),by = c("Week", "Group")]
查看数据表包手册以获取更多信息:http://cran.r-project.org/web/packages/data.table/index.html
要在mean
功能中忽略零,您可以将其替换为nzmean
。请参阅此帖:How can I calculate the means of rows while excluding the zero values from rows in data frame
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")]
答案 2 :(得分:0)
没有任何额外包裹的解决方案:
# Define a non-zero means function
nzmean <- function(x) {
zvals <- x==0
if (all(zvals)) 0 else mean(x[!zvals])
}
然后使用tapply
,考虑名为df
tapply(df$Cost,list(df$Week,df$Group),nzmean )