按缺少数据值的组聚合数据

时间:2015-03-04 19:41:01

标签: r grouping aggregate na

我有这样的NA数据,

   D1   pobox HID S1 locID UID C1  C2 C3 C4 C5 C6
1   1 Box 134   2  1    -9   4 NA  NA NA NA NA NA
2   1 Box 134   2  1     2   4  3  99 10 10  0  0
3   1  Box 35   3 NA    NA   2 NA  NA NA NA NA NA
4   1 Box 169   7 NA    NA   3 NA  NA NA NA NA NA
5   2 Box 115  12  2    -9   4 NA  NA NA NA NA NA
6   2 Box 115  12  2     2   4  0   7 90 10 NA  0
7   2 Box 126  16  3    -9   3  0   0  0  0  0  0
8   3  Box 72  17 NA    NA   4 NA  NA NA NA NA NA
9   3  Box 54  19  4    -9   4  0   0  0  0  0  0
10  3  Box 71  22 NA    NA   2 NA  NA NA NA NA NA
11  4  Box 61  23  5    -9   4 NA  NA NA NA NA NA
12  4  Box 61  23  5     2   4  0 100  0 NA  0  0
13  4  Box 61  23  5    12   4  0  15  0 10 NA  0        
14  4   Box 4  27  6    -9   4  0   0  0  0  0  0
15  4  Box 64  29 NA    NA   3 NA  NA NA NA NA NA
16  4 Box 144  30 NA    NA   2 NA  NA NA NA NA NA

我想通过D1,pobox,HID,S1,UID聚合(Say,sum)C1,C2,C3,C4,C5,C6 我想得到的是这样的数据,当至少一个条目有数字时忽略NA,并且当所有条目都是NA时保持NA。

   D1   pobox HID S1 UID V1 V2 V3 V4 V5 V6
1:  1 Box 134   2  1   4  3 99 10 10  0  0
2:  1  Box 35   3 NA   2 NA NA NA NA NA NA
3:  1 Box 169   7 NA   3 NA NA NA NA NA NA
4:  2 Box 115  12  2   4  0  7 90 10 NA  0
5:  2 Box 126  16  3   3  0  0  0  0  0  0
6:  3  Box 72  17 NA   4 NA NA NA NA NA NA
7:  3  Box 54  19  4   4  0  0  0  0  0  0
8:  3  Box 71  22 NA   2 NA NA NA NA NA NA
9:  4  Box 61  23  5   4  0 115 0 10  0  0
10:  4   Box 4  27  6   4  0  0  0  0  0  0
11:  4  Box 64  29 NA   3 NA NA NA NA NA NA
12:  4 Box 144  30 NA   2 NA NA NA NA NA NA

我试过

  

聚合(cbind(C1,C2,C3,C4,C5,C6)~D1 + pobox + HID + S1 + UID,data = test,sum,na.action = na.pass,na.rm = TRUE)

  D1   pobox HID S1 UID C1  C2 C3 C4 C5 C6
1  2 Box 126  16  3   3  0   0  0  0  0  0
2  1 Box 134   2  1   4  3  99 10 10  0  0
3  2 Box 115  12  2   4  0   7 90 10  0  0
4  3  Box 54  19  4   4  0   0  0  0  0  0
5  4  Box 61  23  5   4  0 115  0 10  0  0
6  4   Box 4  27  6   4  0   0  0  0  0  0

这不起作用, 接下来,我尝试使用doBy包

进行summaryBy
  

summaryBy(C1 + C2 + C3 + C4 + C5~D1 + pobox + HID + S1 + UID,FUN = sum,data = test,na.rm = TRUE,na.pass = TRUE,keep.names = TRUE )

这导致所有NA得到1

D1   pobox HID S1 UID C1  C2 C3 C4 C5
1   1 Box 134   2  1   4  4 100 11 11  1
2   1 Box 169   7 NA   3  1   1  1  1  1
3   1  Box 35   3 NA   2  1   1  1  1  1
4   2 Box 115  12  2   4  1   8 91 11  1
5   2 Box 126  16  3   3  1   1  1  1  1
6   3  Box 54  19  4   4  1   1  1  1  1
7   3  Box 71  22 NA   2  1   1  1  1  1
8   3  Box 72  17 NA   4  1   1  1  1  1
9   4 Box 144  30 NA   2  1   1  1  1  1
10  4   Box 4  27  6   4  1   1  1  1  1
11  4  Box 61  23  5   4  1 116  1 11  1
12  4  Box 64  29 NA   3  1   1  1  1  1

尝试过data.table包

  

SUMT< -DT [,列表(总和(C1),和(C2),和(C3),和(C4),和(C 5),和(C6)),由=列表(D1,POBOX, HID,S1,UID)]

    D1   pobox HID S1 UID V1 V2 V3 V4 V5 V6
1:  1 Box 134   2  1   4 NA NA NA NA NA NA
2:  1  Box 35   3 NA   2 NA NA NA NA NA NA
3:  1 Box 169   7 NA   3 NA NA NA NA NA NA
4:  2 Box 115  12  2   4 NA NA NA NA NA NA
5:  2 Box 126  16  3   3  0  0  0  0  0  0
6:  3  Box 72  17 NA   4 NA NA NA NA NA NA
7:  3  Box 54  19  4   4  0  0  0  0  0  0
8:  3  Box 71  22 NA   2 NA NA NA NA NA NA
9:  4  Box 61  23  5   4 NA NA NA NA NA NA
10:  4   Box 4  27  6   4  0  0  0  0  0  0 
11:  4  Box 64  29 NA   3 NA NA NA NA NA NA
12:  4 Box 144  30 NA   2 NA NA NA NA NA NA

现在,使用na.rm = TRUE,

  

SUMT< -DT [,列表(总和(C1,na.rm = TRUE),和(C2,na.rm = TRUE),和(C3,na.rm = TRUE),和(C4,呐。 RM = TRUE),和(C5,na.rm = TRUE),和(C6,na.rm = TRUE)),通过列表=(D1,POBOX,HID,S1,UID)]

   D1   pobox HID S1 UID V1  V2 V3 V4 V5 V6
1:  1 Box 134   2  1   4  3  99 10 10  0  0
2:  1  Box 35   3 NA   2  0   0  0  0  0  0
3:  1 Box 169   7 NA   3  0   0  0  0  0  0
4:  2 Box 115  12  2   4  0   7 90 10  0  0
5:  2 Box 126  16  3   3  0   0  0  0  0  0
6:  3  Box 72  17 NA   4  0   0  0  0  0  0
7:  3  Box 54  19  4   4  0   0  0  0  0  0
8:  3  Box 71  22 NA   2  0   0  0  0  0  0
9:  4  Box 61  23  5   4  0 115  0 10  0  0
10:  4   Box 4  27  6   4  0   0  0  0  0  0
11:  4  Box 64  29 NA   3  0   0  0  0  0  0
12:  4 Box 144  30 NA   2  0   0  0  0  0  0

2 个答案:

答案 0 :(得分:3)

这是一个dplyr选项:

library(dplyr)
test %>% 
  group_by(D1,pobox,HID,S1,UID) %>% 
  summarise_each(funs(
       if(all(is.na(.))) NA else sum(., na.rm = TRUE)), 
       num_range("C", 1:6))       # could add %>% ungroup() if necessary

#Source: local data frame [12 x 11]
#Groups: D1, pobox, HID, S1
#
#   D1   pobox HID S1 UID C1  C2 C3 C4 C5 C6
#1   1 Box 134   2  1   4  3  99 10 10  0  0
#2   1 Box 169   7 NA   3 NA  NA NA NA NA NA
#3   1  Box 35   3 NA   2 NA  NA NA NA NA NA
#4   2 Box 115  12  2   4  0   7 90 10 NA  0
#5   2 Box 126  16  3   3  0   0  0  0  0  0
#6   3  Box 54  19  4   4  0   0  0  0  0  0
#7   3  Box 71  22 NA   2 NA  NA NA NA NA NA
#8   3  Box 72  17 NA   4 NA  NA NA NA NA NA
#9   4 Box 144  30 NA   2 NA  NA NA NA NA NA
#10  4   Box 4  27  6   4  0   0  0  0  0  0
#11  4  Box 61  23  5   4  0 115  0 10  0  0
#12  4  Box 64  29 NA   3 NA  NA NA NA NA NA

以上是对上述代码的一点修改:

test %>% 
    group_by(D1,pobox,HID,S1,UID) %>% 
    summarise_each(funs(sum(., na.rm = !all(is.na(.)))), num_range("C", 1:6))

这样您可以根据每个组中的值定义na.rm =参数(如果所有值都是NA则为TRUE,否则为FALSE)。


这是一个类似的data.table方法:

library(data.table)
setDT(test)[,lapply(.SD, function(x) sum(x, na.rm = !all(is.na(x)))), 
             .SDcols = paste0("C", 1:6), by = .(D1,pobox,HID,S1,UID)]
 #   D1   pobox HID S1 UID C1  C2 C3 C4 C5 C6
 #1:  1 Box 134   2  1   4  3  99 10 10  0  0
 #2:  1  Box 35   3 NA   2 NA  NA NA NA NA NA
 #3:  1 Box 169   7 NA   3 NA  NA NA NA NA NA
 #4:  2 Box 115  12  2   4  0   7 90 10 NA  0
 #5:  2 Box 126  16  3   3  0   0  0  0  0  0
 #6:  3  Box 72  17 NA   4 NA  NA NA NA NA NA
 #7:  3  Box 54  19  4   4  0   0  0  0  0  0
 #8:  3  Box 71  22 NA   2 NA  NA NA NA NA NA
 #9:  4  Box 61  23  5   4  0 115  0 10  0  0
#10:  4   Box 4  27  6   4  0   0  0  0  0  0
#11:  4  Box 64  29 NA   3 NA  NA NA NA NA NA
#12:  4 Box 144  30 NA   2 NA  NA NA NA NA NA

答案 1 :(得分:0)

这是使用plyr

的解决方案
# recreate Data (need to wrap pobox in "s)
# use clipboard on Windows
data <- read.table(pipe("pbpaste"),header = T,stringsAsFactors = T)

library(plyr)  

# create conditional sum function
sum_rmna <- function(x) {
  if(all(is.na(x))){r <- sum(x)}
  if(!(all(is.na(x)))){r <- sum(x,na.rm = TRUE)}
return(r)}

# use ddply from plyr package
cdata <- ddply(data,c("D1","pobox","HID","S1"),summarise,
               V1 = sum_rmna(C1),
               V2 = sum_rmna(C2),
               V3 = sum_rmna(C3),
               V4 = sum_rmna(C4),
               V5 = sum_rmna(C5),
               V6 = sum_rmna(C6))

这将返回

> cdata
   D1   pobox HID S1 V1  V2 V3 V4 V5 V6
1   1 Box 134   2  1  3  99 10 10  0  0
2   1 Box 169   7 NA NA  NA NA NA NA NA
3   1  Box 35   3 NA NA  NA NA NA NA NA
4   2 Box 115  12  2  0   7 90 10 NA  0
5   2 Box 126  16  3  0   0  0  0  0  0
6   3  Box 54  19  4  0   0  0  0  0  0
7   3  Box 71  22 NA NA  NA NA NA NA NA
8   3  Box 72  17 NA NA  NA NA NA NA NA
9   4 Box 144  30 NA NA  NA NA NA NA NA
10  4   Box 4  27  6  0   0  0  0  0  0
11  4  Box 61  23  5  0 115  0 10  0  0
12  4  Box 64  29 NA NA  NA NA NA NA NA