2014-05-02 15 views
4

我整個銷售數據的數據框計算dplyr::summarize。 我做一個分組(S,D,Y),然後在每個組中,計算中間值和平均值爲5..43周,然後將它們合併回父df。變量X是銷售額。 X從來就不是NA(即df中沒有顯式的NAs),但是如果沒有S,D,Y和周的數據(如在,沒有銷售),那麼這些值將不會有任何行在df中(這意味着對於特定的一組參數零銷售量)。換句話說,在任何結構上缺少的行推諉X = 0(但我希望我不需要melt/cast原來的DF,避免膨脹。至cast(fill....,add.missing=T)caret::preProcess()類似)。dplyr成語彙總()已過濾組通過,並更換任何來港由於缺少行

兩個關於我的代碼風格問題:

  1. 是它更好地使用總結比dplyr::filter,因爲過濾器物理降到行,所以我必須將結果賦予df.tmp然後左鍵加入它回到原來的df(如下)?此外,在每一行總結計算中重複的大子集表達式會使代碼難以閱讀。 我應該擔心(或不是)緩存子集操作的行或邏輯索引,在我可能計算的一般情況下,說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) 
+2

「你不會得到更多」。對不起,但是製作一些隨機數據不應該很難。 – Arun

+0

@阿倫:由於以上流行的需求是樣本數據...不是它是嚴格需要的...現在我可以期待一些答案? – smci

+0

我想根源是[dplyr總結:等效「.drop = FALSE」,以保持基團與在輸出零長度(http://stackoverflow.com/questions/22523131/dplyr-summarise-equivalent-of-丟失 - 錯誤保持組與零長度在); https://github.com/hadley/dplyr/issues/341。但今天我需要一個解決方法。 – smci

回答

8

我不認爲這有什麼與你在評論鏈接的功能做(因爲IIUC該功能有未使用的因子水平有關)。一旦你過濾了你的數據,IMO summarise不應該(或者不能?)將它們包括在結果中(factors除外)。您應該在項目頁面上向開發人員澄清這一點。


我決不是一個dplyr專家,但我認爲,首先,它會是更好的filter第一,隨後group_by + summarise。否則,您將過濾每個組,這是不必要的。那就是:

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

這只是爲了讓你知道它對於未來的任何情況。


國際海事組織,這是更好地在這裏使用mutate而不是summarise,因爲它會刪除需要left_join,IIUC。那就是:

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

+0

我想dplyr不是data.table,謝謝。這就是它標記的dplyr的原因。 – smci

+0

@smci,請在評論前閱讀*全部答案。它只是幫助我在'data.table'中思考。我提供了一個'dplyr'解決方案。 – Arun

+0

我已經*全部閱讀*全部答案。我正在對您的評論進行逐點回復。如果你一直跟我說話,這真的會變得越來越嚴重。你能解決你的態度嗎?請停止假設不正確的事情。 – smci