在R中,dplyr中的group_by如何工作?

时间:2016-06-23 15:54:25

标签: r dplyr

这个问题适合于理解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?

2 个答案:

答案 0 :(得分:3)

如果我们需要获得预期的输出,一个选项是

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

我们也可以使用by

中的base R来执行此操作
verificator <- function(x){
     as.logical(prod(colSums(x)))
    }
c(by(d[-1], d$id, FUN = verificator))
#   A     B 
#TRUE FALSE 

答案 1 :(得分:2)

您得到错误结果的原因是,当使用%>%时,点(.)代表%>%左侧表达式的竞争结果。因此,您只需在完整数据框verificator()上评估d两次。

您可以看到以下内容。首先,我检查应用于完整数据框的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被打印三次而不是两次......