【问题标题】:Conditional summarize of groups in dplyr based on date根据日期对 dplyr 中的组进行条件汇总
【发布时间】:2016-12-30 17:38:07
【问题描述】:

我是一个 R 菜鸟,并尝试对数据集执行摘要,该数据集总计每个 ID 的事件类型的数量,该 ID 的类型为“B”的事件之间发生的事件。这是一个示例来说明:

id <- c('1', '1', '1', '2', '2', '2', '3', '3', '3', '3')
type <- c('A', 'A', 'B', 'A', 'B', 'C', 'A', 'B', 'C', 'B')
datestamp <- as.Date(c('2016-06-20','2016-07-16','2016-08-14','2016-07-17'
                       ,'2016-07-18','2016-07-19','2016-07-16','2016-07-19'
                       , '2016-07-21','2016-08-20'))
df <- data.frame(id, type, datestamp)

产生:

> df
   id type  datestamp
1   1    A 2016-06-20
2   1    A 2016-07-16
3   1    B 2016-08-14
4   2    A 2016-07-17
5   2    B 2016-07-18
6   2    C 2016-07-19
7   3    A 2016-07-16
8   3    B 2016-07-19
9   3    C 2016-07-21
10  3    B 2016-08-20

每当发生事件“B”时,我想知道在该 B 事件之前但在该 ID 的任何其他 B 事件之后发生的每种事件类型的数量。 我想最终得到一张这样的表格:

  id type B_instance count
1  1    A          1     2
2  2    A          1     1
3  3    A          1     1
4  3    C          2     1

在研究中,这个问题最接近:summarizing a field based on the value of another field in dplyr

我一直在努力做到这一点:

  df2 <- df %>%
  group_by(id, type) %>%
  summarize(count = count(id[which(datestamp < datestamp[type =='B'])])) %>%
  filter(type != 'B')

但它会出错(此外,即使它有效,它也不会考虑同一 ID 中的 2 个“B”事件,例如 id=3)

【问题讨论】:

    标签: r dplyr summarize


    【解决方案1】:

    这是一个使用data.table 的选项。我们将'data.frame'转换为'data.table'(setDT(df),按'id'分组,我们得到'type'为'B'的max位置的序列,找到行索引(@ 987654324@),提取该列($V1)。然后,我们对数据集进行子集化(df[i1]),删除“type”为“B”的行,按“id”、“type”和@987654327分组@ of 'type',我们得到行数为'count'。

    library(data.table)
    i1 <- setDT(df)[, .I[seq(max(which(type=="B")))] , by = id]$V1
    df[i1][type!="B"][,  .(count = .N), .(id, type, B_instance = rleid(type))]
    #   id type B_instance count
    #1:  1    A        1     2
    #2:  2    A        1     1
    #3:  3    A        1     1
    #4:  3    C        2     1
    

    【讨论】:

    • 这也很好用,谢谢。 @Psidom 的 dplyr 解决方案对我来说更直观。但是使用我不知道的 data.table 有什么好处吗?还是只是个人喜好?
    • @feyr 它们都是很好的软件包。如果您想利用适当的分配(:=),(这里没有完成)data.table 会有效并且会很有效。然而,在这种情况下,psidom 的解决方案将和我的一样好,甚至更优雅。
    【解决方案2】:

    您可以使用cumsum 通过执行cumsum(type == "B") 来创建新的组变量B_instance,然后过滤掉落后于最后一个B 的类型以及类型B 本身,因为它们不会被计算在内。然后使用count 来统计idB_instancetype 分组的出现次数。

    df %>% 
           group_by(id) %>% 
           # create B_instance using cumsum on the type == "B" condition
           mutate(B_instance = cumsum(type == "B") + 1) %>%    
           # filter out rows with type behind the last B and all B types                 
           filter(B_instance < max(B_instance), type != "B") %>% 
           # count the occurrences of type grouped by id and B_instance
           count(id, type, B_instance) 
    
    # Source: local data frame [4 x 4]
    # Groups: id, type [?]
    
    #       id   type B_instance     n
    #   <fctr> <fctr>      <dbl> <int>
    # 1      1      A          1     2
    # 2      2      A          1     1
    # 3      3      A          1     1
    # 4      3      C          2     1
    

    【讨论】:

    • 这很完美!谢谢!出于好奇,为什么cumsum需要加1?
    • 匹配实例计数,否则从零开始,结果会像0,0,0,1而不是1,1,1,2
    猜你喜欢
    • 1970-01-01
    • 2021-07-27
    • 2020-10-17
    • 2019-03-06
    • 2020-06-25
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 2020-02-07
    相关资源
    最近更新 更多