【问题标题】:COUNTIF equivalent in dplyr summarisedplyr 中的 COUNTIF 等效汇总
【发布时间】:2016-09-19 13:21:25
【问题描述】:

我有一个数据框,列出了参加活动的学生总数 (Stu) 和每组 (ID) 的学生人数 (Sub):

     ID   Stu   Sub
  (int) (int) (int)
1   101    80    NA
2   102   130    NA
3   103    10    NA
4   104   210    20
5   105   180    NA
6   106   150    NA

我想知道参与活动(Sub > 0)或不参与活动(Sub is.na)的大小范围(>400、>200、>100、>0)的组数

output <- structure(list(ID = c(101L, 102L, 103L, 104L, 105L, 106L), 
                       Stu = c(80L, 130L, 10L, 210L, 180L, 150L), 
                       Sub = c(NA,NA, NA, 20L, NA, NA)), 
                  .Names = c("ID", "Stu", "Sub"), 
                  class = c("tbl_df", "data.frame"), 
                  row.names = c(NA, -6L))

temp <- output %>% 
mutate(Stu = ifelse(Stu >= 400, 400,
         ifelse(Stu >= 200, 200,
             ifelse(Stu >= 100, 100, 0
                 )))) %>%
group_by(Stu) %>%
summarise(entries = length(!is.na(Sub)),
          noentries = length(is.na(Sub)))

结果应该是:

    Stu entries noentries
  (dbl)   (int)     (int)
1     0       0         2
2   100       0         3
3   200       1         0

但我明白了:

    Stu entries noentries
  (dbl)   (int)     (int)
1     0       2         2
2   100       3         3
3   200       1         1

如何使汇总中的长度函数像计数一样?

【问题讨论】:

  • 你的最后一个 ifelse 是错的
  • 对不起,错过了一个 0,它现在应该可以工作了
  • sum 是正确的解决方案,如下所述。为清楚起见,length 返回它所提供的向量的长度。在这种情况下,无论真/假值如何,长度函数都会返回每个组中的项目数。

标签: r dplyr


【解决方案1】:

另一种选择是同时按StuSub 进行分组,但要做到这一点,我们需要首先重新编码SubStu 的值以匹配我们想要的输出分组。我们还使用cut,而不是嵌套的ifelse,在Stu 中设置值中断:

library(reshape2)

output %>% 
  group_by(Sub=ifelse(is.na(Sub), "No Entries", "Entries"),
           Stu=cut(Stu, c(0,100,200,400,Inf), labels=c(0,100,200,400))) %>%
  tally %>%
  dcast(Stu ~ Sub, fill=0)
     Stu Entries No Entries
1      0       0          2
2    100       0          3
3    200       1          0

【讨论】:

    【解决方案2】:

    遵循@eipi10 提供的相同想法,但使用count() 而不是group_by() %&gt;% tally() 并表明tidyr::spread 可以模仿reshape2::dcast

    output %>%
      count(Sub = ifelse(is.na(Sub), 'No Entries', 'Entires'),
            Stu = cut(Stu, c(0, 100, 200, 400, +Inf), labels = c(0, 100, 200, 400))) %>%
      tidyr::spread(Sub, n, fill = 0)
    

    【讨论】:

      【解决方案3】:

      summarise 需要一个值,所以 sum 而不是 length 可以完成这项工作:

      output %>% 
        mutate(Stu = ifelse(Stu >= 400, 400,
                            ifelse(Stu >= 200, 200,
                                   ifelse(Stu >= 100, 100, 0
                                   )))) %>%
        group_by(Stu) %>% 
        summarise(entries = sum(!is.na(Sub)),
                  noentries = sum(is.na(Sub)))
      
      Source: local data frame [3 x 3]
      
      Stu entries noentries
      (dbl)   (int)     (int)
      1     0       0         2
      2   100       0         3
      3   200       1         0
      

      【讨论】:

      • 啊是的,我忘了is.na返回一个布尔向量,可以求和
      猜你喜欢
      • 2017-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 2021-01-20
      • 2015-06-27
      • 2015-09-18
      • 1970-01-01
      相关资源
      最近更新 更多