【问题标题】:In R, how does group_by in dplyr work?在 R 中,dplyr 中的 group_by 是如何工作的?
【发布时间】:2016-06-23 15:54:24
【问题描述】:

这个问题适合理解 group_by 函数的正确功能。

假设我有一个数据框,其中包含 5 个二进制变量(这些变量的含义并不重要)和一个代表一些用户的变量 id。例如:

id<- c("A","A" , "B" , "B")
d<- as.data.frame(id) 
d$d1<- c(1,0,1,0)
d$d2<- c(1,0,1,0)
d$d3<- c(0,1,1,0)
d$d4<- c(0,1,0,1)
d$d5<- c(0,1,0,0)
> d
  id d1 d2 d3 d4 d5
1  A  1  1  0  0  0
2  A  0  0  1  1  1
3  B  1  1  1  0  0
4  B  0  0  0  1  0

我将构造一个函数,该函数能够检查每个用户 A 和 B,变量 d1 到 d5 是否都包含 1。

verificator<- function(d )
 {
  r<- prod(apply(d[,2:6],2, sum)) 
  r<- as.logical(r)
  return(r)
 } 

例如,对于A用户,d1到d5中的每一个,都有第一个。

verificator(d[1:2,]) 
[1] TRUE

但是,对于 B 用户,我们有

verificator(d[3:4,])
[1] FALSE

当我使用 dplyr 函数计算 d 矩阵时,出现了问题:

d2<- d %>% group_by(id) %>% summarise(one = verificator(.))
d2
Source: local data frame [2 x 2]

  id  one
1  A TRUE
2  B TRUE

为什么这会为 B 用户返回 TRUE?

【问题讨论】:

  • 我不确定这是否是最优雅的,但我可能会这样做d %&gt;% group_by(id) %&gt;% summarise_each(funs(sum)) %&gt;% group_by(id) %&gt;% summarise(one = as.logical(prod(d1:d5)))

标签: r dplyr


【解决方案1】:

如果我们需要得到预期的输出,一种选择是

d %>% 
    group_by(id) %>% 
    summarise_each(funs(sum)) %>% rowwise()  %>% 
    do(data.frame(id = .[1L], one = as.logical(prod(unlist(.[-1])))))
#     id   one
#  <fctr> <lgl>
#1      A  TRUE
#2      B FALSE

我们也可以使用来自base R 的by 来做到这一点

verificator <- function(x){
     as.logical(prod(colSums(x)))
    }
c(by(d[-1], d$id, FUN = verificator))
#   A     B 
#TRUE FALSE 

【讨论】:

    【解决方案2】:

    你得到错误结果的原因是在使用%&gt;%时,点(.)代表%&gt;%左边表达式的竞争结果。因此,您只需在 complete 数据框 d 上评估您的 verificator() 两次。

    您可以看到如下。首先,我检查应用到完整数据帧的verificator() 确实返回TRUE:

    verificator(d)
    ## [1] TRUE
    

    然后,我定义了verificator() 的另一个变体,它打印了它的参数:

    verificator_p <- function(d) {
      print(d)
      return(verificator(d))
    }
    

    使用您提出的代码,表明它始终是传递给函数的完整数据框:

    d %>% group_by(id) %>% summarise(one = verificator_p(.))
    ## Source: local data frame [4 x 6]
    ## Groups: id [2]
    ## 
    ##       id    d1    d2    d3    d4    d5
    ##   (fctr) (dbl) (dbl) (dbl) (dbl) (dbl)
    ## 1      A     1     1     0     0     0
    ## 2      A     0     0     1     1     1
    ## 3      B     1     1     1     0     0
    ## 4      B     0     0     0     1     0
    ## Source: local data frame [4 x 6]
    ## Groups: id [2]
    ## 
    ##       id    d1    d2    d3    d4    d5
    ##   (fctr) (dbl) (dbl) (dbl) (dbl) (dbl)
    ## 1      A     1     1     0     0     0
    ## 2      A     0     0     1     1     1
    ## 3      B     1     1     1     0     0
    ## 4      B     0     0     0     1     0
    ## Source: local data frame [4 x 6]
    ## Groups: id [2]
    ## 
    ##       id    d1    d2    d3    d4    d5
    ##   (fctr) (dbl) (dbl) (dbl) (dbl) (dbl)
    ## 1      A     1     1     0     0     0
    ## 2      A     0     0     1     1     1
    ## 3      B     1     1     1     0     0
    ## 4      B     0     0     0     1     0
    ## Source: local data frame [2 x 2]
    ## 
    ##       id   one
    ##   (fctr) (lgl)
    ## 1      A  TRUE
    ## 2      B  TRUE
    

    我承认不知道的是,为什么d 被打印了三次而不是两次...

    【讨论】:

    • > d2% group_by(id) %>% summarise(one = verificator()) 错误:参数“d”丢失,没有默认值
    • 在没有参数的情况下调用verficator() 肯定是行不通的......其他人已经更快地提供了一个可行的解决方案。但我添加了更多解释,希望能帮助您理解为什么您的第一种方法没有按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 2017-07-12
    相关资源
    最近更新 更多