如何使用group_by变量作为dplyr的排除值?

时间:2017-03-28 21:49:28

标签: r dplyr

我们说我有以下数据框:

(dat  = data_frame(v1 = c(rep("a", 3), rep("b", 3), rep("c", 4)), v2 = 1:10))
# A tibble: 10 × 2
#       v1    v2
#    <chr> <int>
# 1      a     1
# 2      a     2
# 3      a     3
# 4      b     4
# 5      b     5
# 6      b     6
# 7      c     7
# 8      c     8
# 9      c     9
# 10     c    10

我希望能够做的是计算每个组的总和(即&#34; a&#34;,&#34; b&#34;和&#34; c&#34;)等于v2其中v1 不等于的总和与分组值相等。所以看起来应该是这样的:

# A tibble: 3 × 2
#      v1   sum
#   <chr> <int>
# 1     a    49
# 2     b    40
# 3     c    21

基于我在网上看到的内容,这看起来像是do的工作,但我无法理解如何实现这一目标。我认为它看起来像这样:

x %>%
  group_by(v1) %>%
  do(data.frame(sum=sum(.$v2[x$v1 != unique(.$v1)])))

但这只是为我提供了一个数据框,sum等于NA所有三个组。我该怎么做呢?

5 个答案:

答案 0 :(得分:6)

使用中间栏可能更容易:

dat %>% mutate(total = sum(v2)) %>% group_by(v1) %>% summarize(sum = max(total) - sum(v2))

答案 1 :(得分:1)

您可以nest然后对列表列进行负面索引:

library(tidyverse)

dat %>% nest(v2) %>% mutate(sum = map_int(seq(n()), ~sum(unlist(data[-.x]))))

## # A tibble: 3 × 3
##      v1             data   sum
##   <chr>           <list> <int>
## 1     a <tibble [3 × 1]>    49
## 2     b <tibble [3 × 1]>    40
## 3     c <tibble [4 × 1]>    21

这种方法的优点是保存原始数据并将计算值与它们对齐非常容易。

答案 2 :(得分:0)

@ 67342343&#39342343的解决方案似乎就像去了这里。如果您有更复杂的重叠/排除组,那么以下内容可能会有所帮助:

library(tidyverse)

dat = data_frame(v1 = rep(letters[1:5], 3), v2 = 1:(5*3))

c(combn(unique(dat$v1),2, simplify=FALSE),
  combn(unique(dat$v1),3, simplify=FALSE)) %>%
  map_df(~ dat %>% 
           group_by(v1) %>% 
           summarise(v2 = sum(v2)) %>%
           filter(v1 %in% .x) %>%
           ungroup %>%
           summarise(groups = paste(.x,collapse=","),
                     sum = sum(v2)))
   groups   sum
1     a,b    39
2     a,c    42
3     a,d    45
4     a,e    48
5     b,c    45
...
18  b,c,e    75
19  b,d,e    78
20  c,d,e    81

答案 3 :(得分:0)

不使用dplyr的小函数:

dat  <- data_frame(v1 = c(rep("a", 3), rep("b", 3), rep("c", 4)), v2 = 1:10)

test_func<-function(df){
      a<-sum(df[df$v1 != "a",][,2])
      b<-sum(df[df$v1 != "b",][,2])
      c<-sum(df[df$v1 != "c",][,2])
      out<-rbind(a,b,c)
      return(out)
}

test_func(dat)

  [,1]
a   49
b   40
c   21

答案 4 :(得分:0)

保持简单:

dat %>% group_by(v1) %>% summarize(foo = sum(dat$v2) - sum(v2))

如果您处于长dplyr链的中间且修改了dat,那就太难了。 (但是,为什么不放松并只存储您的数据?)