4

dplyr::summarize販売データのデータフレーム全体を計算しています。group-by (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)orと同様caret::preProcess()です)。

私のコードイディオムに関する2つの質問:

  1. dplyr::filterfilter は行を物理的に削除するため、結果を割り当ててからdf.tmp元の df に左結合する必要があるため (以下のように)、summaryよりも使用する方がよいでしょうか? また、要約計算のすべての行で繰り返される大きなサブセット式により、コードが読みにくくなります。n=20 の新しい集計変数を計算する一般的なケースでは、サブセット化操作の行または論理インデックスのキャッシュについて心配する必要がありますか (または心配しないでください)。

  2. 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)

これを最初に実行して、サンプルデータを生成します。

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)
4

1 に答える 1

8

これは、コメントの下でリンクした機能とは何の関係もないと思います(その機能は未使用の因子レベルと関係があるため)。データをフィルタリングすると、IMOsummariseはそれらを結果に含めるべきではありません (または、できませんか?) (例外はfactors)。プロジェクトページで開発者にこれを明確にする必要があります。


私は決してdplyr専門家ではありませんが、まず、最初filtergroup_by + summarise. そうしないと、グループごとにフィルタリングすることになりますが、これは不要です。あれは:

df.tmp <- df %.% filter(Week>=5 & Week<=43) %.% group_by(S,D,Y) %.% ...

これは、将来のケースに備えて認識できるようにするためです。


IMO、IIUCの必要性がなくなるため、mutate代わりにここで使用することをお勧めします。あれは:summariseleft_join

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]))

ここでも、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)
              })   

したがって、おそらく次の方法で回避する必要があります。

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))

または、物事をまとめるには:

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

を必要としませんdf.tmp

HTH

于 2014-05-03T08:12:00.973 に答える