smc*_*mci 4 idioms r summarization na dplyr
我正在计算dplyr::summarize销售数据的数据框.我做了一个分组(S,D,Y),然后在每个组内,计算中位数和平均值5..43,然后将它们合并回父df.变量X是销售额.X永远不是NA(即df中没有任何明确的NA),但是如果S,D,Y和周数没有数据(如,没有销售),那么就不会有这些值的行在df中(接受它意味着该特定参数集的零销售额).换句话说,在任何结构缺失的行中插入X = 0(但我希望我不需要melt/cast原始的df,以避免膨胀.类似于cast(fill....,add.missing=T)或caret::preProcess()).
关于我的代码习惯的两个问题:
使用汇总是否比使用汇总更好dplyr::filter,因为过滤器会物理地丢弃行,所以我必须将结果分配给df.tmp左 - 将其连接回原始df(如下所示)?此外,在汇总计算的每一行上重复的大子集表达式使得代码更难以阅读.我是否应该担心(或不关心)缓存子集化操作的行或逻辑索引,在我可能计算的一般情况下说n = 20个新的汇总变量?
并非所有S,D,Y组和过滤器的组合(对于那些周)都有行,那么如何在任何缺失的行上进行汇总以替换NA?目前我做如下.
很抱歉,代码和数据集都是专有的,但这里是代码习惯用法,下面是您应首先运行以生成样本数据的代码:
# Compute median, mean of X across wks 5..43, for that set of S,D,Y-values
# Issue a) filter() or repeatedly use subset() within each calculation?
df.tmp <- df %.% group_by(S,D,Y) %.% filter(Week>=5 & Week<=43) %.%
summarize(ysd_med543_X = median(X),
ysd_mean543_X = mean(X)
) %.% ungroup()
# Issue b) how to replace NAs in groups where the group_by-and-filter gave empty output?
# can you merge this code with the summarize above?
df <- left_join(df, df.tmp, copy=F)
newcols <- match(c('ysd_mean543_X','ysd_med543_X'), names(df))
df[!complete.cases(df[,newcols]), newcols] <- c(0.0,0.0)
Run Code Online (Sandbox Code Playgroud)
并首先运行以生成样本数据:
set.seed(1234)
rep_vector <- function(vv, n) {
unlist(as.vector(lapply(vv, function(...) {rep(...,n)} )))
}
n=7
m=3
df = data.frame(S = rep_vector(10:12, n), D = 20:26,
Y = rep_vector(2005:2007, n),
Week = round(52*runif(m*n)),
X = 4e4*runif(m*n) + 1e4 )
# Now drop some rows, to model structurally missing rows
I <- sort(sample(1:nrow(df),0.6*nrow(df)))
df = df[I,]
require(dplyr)
Run Code Online (Sandbox Code Playgroud)
我不认为这与您在评论下链接的功能有任何关系(因为IIUC该功能与未使用的因子级别有关).一旦过滤了数据,IMO summarise就不应该(或者更确切地说不能)将它们包含在结果中(除了factors).您应该在项目页面上与开发人员澄清这一点.
我不是dplyr专家,但我认为,首先,最好filter先跟随group_by + summarise.否则,你将为每个组过滤,这是不必要的.那是:
df.tmp <- df %.% filter(Week>=5 & Week<=43) %.% group_by(S,D,Y) %.% ...
Run Code Online (Sandbox Code Playgroud)
这只是为了让您在将来的任何情况下都能意识到这一点.
IMO,最好在mutate这里使用而不是summarise,因为它将消除对left_joinIIUC的需求.那是:
df.tmp <- df %.% group_by(S,D,Y) %.% mutate(
md_X = median(X[Week >=5 & Week <= 43]),
mn_X = mean(X[Week >=5 & Week <= 43]))
Run Code Online (Sandbox Code Playgroud)
在这里,我们仍然存在更换NA/NaN的问题.这里没有简单/直接的分配方式.那么,你将不得不ifelse再次使用IIUC.但如果mutate支持表达式,这会更好一些.
我的想法是这样的:
df.tmp <- df %.% group_by(S,D,Y) %.% mutate(
{ tmp = Week >= 5 & Week <= 43;
md_X = ifelse(length(tmp), median(X[tmp]), 0),
md_Y = ifelse(length(tmp), mean(X[tmp]), 0)
})
Run Code Online (Sandbox Code Playgroud)
所以,我们必须以这种方式解决方法:
df.tmp = df %.% group_by(S,D,Y) %.% mutate(tmp = Week >=5 & Week <= 43)
df.tmp %.% mutate(md_X = ifelse(tmp[1L], median(X), 0),
mn_X = ifelse(tmp[1L], mean(X), 0))
Run Code Online (Sandbox Code Playgroud)
或者把事情放在一起:
df %.% group_by(S,D,Y) %.% mutate(tmp = Week >=5 & Week <= 43,
md_X = ifelse(tmp[1L], median(X), 0),
mn_X = ifelse(tmp[1L], median(X), 0))
# S D Y Week X tmp md_X mn_X
# 1 10 20 2005 6 22107.73 TRUE 22107.73 22107.73
# 2 10 23 2005 32 18751.98 TRUE 18751.98 18751.98
# 3 10 25 2005 33 31027.90 TRUE 31027.90 31027.90
# 4 10 26 2005 0 46586.33 FALSE 0.00 0.00
# 5 11 20 2006 12 43253.80 TRUE 43253.80 43253.80
# 6 11 22 2006 27 28243.66 TRUE 28243.66 28243.66
# 7 11 23 2006 36 20607.47 TRUE 20607.47 20607.47
# 8 11 24 2006 28 22186.89 TRUE 22186.89 22186.89
# 9 11 25 2006 15 30292.27 TRUE 30292.27 30292.27
# 10 12 20 2007 15 40386.83 TRUE 40386.83 40386.83
# 11 12 21 2007 44 18049.92 FALSE 0.00 0.00
# 12 12 26 2007 16 35856.24 TRUE 35856.24 35856.24
Run Code Online (Sandbox Code Playgroud)
这不需要df.tmp.
HTH
| 归档时间: |
|
| 查看次数: |
4075 次 |
| 最近记录: |