2016-08-11 63 views
3

我有一個類似的問題與by()我接受的事實,我必須手動替換生成的NAs。現在我想彙總我的數據框架並保持結構。例如我的大型數據集有100個國家* 10年* 5個細分市場的因素,所以它應該減少到5000行。但有時一些細分因素是空的,我只得到了5000行。我不能讓我的頭周圍...與空因子聚合但保持行

我MWE仍然適用:

#All 3 categories are used 
df1<-data.frame(val=rep(seq(1:4),3), factor=cut(rep(seq(1:4),3),breaks=c(1,2,3,4), include.lowest = TRUE, ordered_results=True , labels=LETTERS[1:3])) 
# Thirds category is not used 
df2<-data.frame(val=rep(seq(1:3),4), factor=cut(rep(seq(1:3),4),breaks=c(1,2,3,4), include.lowest = TRUE, ordered_results=True , labels=LETTERS[1:3])) 

#df1 reduces to 3 rows as each category is used 
aggregate(df1$val,list(df1$factor),sum) 
#df2 reduces to 2 rows because C is empty 
aggregate(df2$val,list(df2$factor),sum) 
#I would like 
data.frame(Group.1=LETTERS[1:3], x=c(12,12,0)) 

    Group.1 x 
1  A 12 
2  B 12 
3  C 0 
+1

我一直認爲這是做什麼用的'drop'說法......顯然不是 –

+0

滑稽我居然沒有看到下降的事情,但是從描述我還以爲現在同樣的事情 –

回答

2
# create dataset 
df2 <- data.frame(val=rep(seq(1:3),4), factor=cut(rep(seq(1:3),4),breaks=c(1,2,3,4), include.lowest = TRUE, ordered_results=True , labels=LETTERS[1:3])) 

library(dplyr) 

levels(df2$factor) %>%         # get distinct levels of the factor variable 
    data.frame(factor = .) %>%        # create a data frame 
    left_join(df2 %>%          # join with 
      group_by(factor) %>%        # for each value that exists 
      summarise(x = sum(val)), by = "factor") %>%  # sum column val 
    mutate(x = coalesce(x, 0L))        # replace NAs with 0s 

# factor x 
# 1  A 12 
# 2  B 12 
# 3  C 0 

或沒有任何包裝

dd = merge(data.frame(Group.1 = levels(df2$factor)), 
      aggregate(df2$val,list(df2$factor),sum), all.x = T) 
dd$x = ifelse(is.na(dd$x), 0, dd$x) 
dd 

# Group.1 x 
# 1  A 12 
# 2  B 12 
# 3  C 0 

或者用data.table包檢查,如果它的速度更快

library(data.table) 

# assuming you start with a data frame 
df2 <- data.frame(val=rep(seq(1:3),4), factor=cut(rep(seq(1:3),4),breaks=c(1,2,3,4), include.lowest = TRUE, ordered_results=True , labels=LETTERS[1:3])) 

# create a data table with all unique values of the variable "factor" and an index (key) on that variable 
dt_levels = data.table(factor = levels(df2$factor), key = "factor") 

# make df2 a data table with an index on column "factor" and aggregate 
dt_sum = setDT(df2, key = "factor")[, list(Sum = sum(val)), by = "factor"] 

# left join the two data tables and replace NA values with 0s 
dt_result = dt_sum[dt_levels][, Sum := ifelse(is.na(Sum), 0, Sum)] 

dt_result[] 

# factor Sum 
# 1:  A 12 
# 2:  B 12 
# 3:  C 0   
+0

這如果我的數據有4'743'200行,可能需要很長時間,不會嗎? –

+0

也取決於您有多少個唯一值(級別)。這會影響連接。更好地嘗試所有的方法,並選擇我認爲更快的方法。 – AntoniosK

+0

我最喜歡合併的一個。我可能不得不做一些進一步的微基準來看哪一個是最快的。其實它跟Chase Grimm提出的很相似。我使用我的因子級別的expand.grid設置了我的目標日期框架,然後將其與aggregate()調用合併 –

1

您可以使用complete功能從tidyr明確地顯示在結果中缺少值:

library(dplyr); library(tidyr) 
df2 %>% 
     group_by(factor) %>% 
     summarise(x = sum(val)) %>% 
     complete(factor, fill = list(x = 0)) 

# Source: local data frame [3 x 2] 

# factor  x 
# <fctr> <dbl> 
# 1  A 12 
# 2  B 12 
# 3  C  0 

隨着aggregate功能:

tidyr::complete(aggregate(df2$val,list(df2$factor),sum), Group.1, fill = list(x = 0)) 

# Source: local data frame [3 x 2] 

# Group.1  x 
# <fctr> <dbl> 
#1  A 12 
#2  B 12 
#3  C  0 
+0

Thx tidyr :: complete對我來說似乎是最容易複製的,並且它很有效。至於另一個解決方案,它需要將近20秒才能運行我的原始數據。框架 –

+0

我認爲第一個選項會更快,但看起來並不如此。除非你要生產,否則20秒對我來說是可以接受的。你也可以嘗試一個通常應該更快的數據表版本。 – Psidom

+0

有沒有一種方法可以將填充選項設置爲零而不必爲所有變量命名?我的數據集有很多列彙總,所以這會有點煩人 –

1

所以這是非常基本的,但我只是做了一個新的數據與2列的框架。 一個與每個因素水平,一個與所有0.然後我用rbind,但我的新框架和df2在一起,然後使用聚合。

df2 <- data.frame(val=rep(seq(1:3),4), factor=cut(rep(seq(1:3),4),breaks=c(1,2,3,4), include.lowest = TRUE, ordered_results=True , labels=LETTERS[1:3])) 

dat <- data.frame(val = 0, factor = levels(df2$factor)) 

df3 <- rbind(df2,dat) 

aggregate(. ~ factor,df3,sum) 

# factor val 
#1  A 12 
#2  B 12 
#3  C 0