【问题标题】:Time series summary时间序列摘要
【发布时间】:2018-04-10 00:07:30
【问题描述】:

我试图对时间滞后为 1 的数字求和。即,我想通过添加特定组中天数仅相差一天的值的频率来总结行。我使用了滞后函数来获取差异,但不知道如何从这里开始。

df <- df %>% 
  group_by(group) %>% 
  mutate(diff = dt - lag(dt))

df[!is.na(df$diff) & df$diff > 1,]$diff <- NA

例如:

 group     dt           freq  diff  
 groupA    2016-03-21    1     NA    
 groupA    2016-03-22    1     1     
 groupA    2016-03-23    1     1     
 groupA    2016-03-26    2     NA     
 groupA    2016-03-28    1     NA     
 groupA    2016-03-29    3     1     
 groupA    2016-03-30    3     1     
 groupA    2016-03-31    5     1     
 groupB    2016-04-01    1     NA      
 groupB    2016-04-02    2     1 

我需要把它分成:

group    dt         freq  diff  duration     
groupA  2016-03-21    1     NA    3 (1 + 1 + 1)     
groupA  2016-03-22    1     1         
groupA  2016-03-23    1     1         
groupA  2016-03-26    2     NA    2     
groupA  2016-03-28    1     NA    12(1 + 3 + 3 + 5)     
groupA  2016-03-29    3     1         
groupA  2016-03-30    3     1         
groupA  2016-03-31    5     1         
groupB  2016-04-01    1     NA    3(1 + 2)     
groupB  2016-04-02    2     1 

也提到了this,但累积不起作用,因为我不考虑跳跃超过一天。循环自定义函数是唯一的方法吗?

【问题讨论】:

    标签: r dataframe dplyr


    【解决方案1】:

    您可以使用这种方法更轻松地做到这一点(以less.than 1 天的差异对行进行分组);这将创建一个帮助列 gap 稍后将用于对同一组中连续几天的 freq 求和:

    library(dplyr)
    
    df %>% 
        mutate(gap = cumsum(!c(TRUE, diff(as.Date(df$dt)) == 1)))  %>% 
        group_by(gap, group) %>% 
        mutate(duration = sum(freq, na.rm=TRUE)) %>% 
        ungroup %>% select(-gap) %>% as.data.frame
    
    #            group         dt freq duration
    #        1  groupA 2016-03-21    1        3
    #        2  groupA 2016-03-22    1        3
    #        3  groupA 2016-03-23    1        3
    #        4  groupA 2016-03-26    2        2
    #        5  groupA 2016-03-28    1       12
    #        6  groupA 2016-03-29    3       12
    #        7  groupA 2016-03-30    3       12
    #        8  groupA 2016-03-31    5       12
    #        9  groupB 2016-04-01    1        3
    #        10 groupB 2016-04-02    2        3
    

    【讨论】:

      【解决方案2】:

      这是使用dplyr::leadtidyverse 解决方案:

      library(tidyverse);
      df %>%
          mutate(dt = as.POSIXct(dt)) %>%
          group_by(group) %>%
          mutate(
              diff = pmin(c(1, diff(dt)), c(1, diff(lead(dt))), na.rm = T),
              id = cumsum(c(TRUE, diff(diff) != 0) | diff > 1)) %>%
          group_by(group, id) %>%
          mutate(duration = sum(freq)) %>%
          ungroup() %>%
          select(-diff, -id)
      ## A tibble: 10 x 4
      #   group  dt                   freq duration
      #   <fct>  <dttm>              <int>    <int>
      # 1 groupA 2016-03-21 00:00:00     1        3
      # 2 groupA 2016-03-22 00:00:00     1        3
      # 3 groupA 2016-03-23 00:00:00     1        3
      # 4 groupA 2016-03-26 00:00:00     2        2
      # 5 groupA 2016-03-28 00:00:00     1       12
      # 6 groupA 2016-03-29 00:00:00     3       12
      # 7 groupA 2016-03-30 00:00:00     3       12
      # 8 groupA 2016-03-31 00:00:00     5       12
      # 9 groupB 2016-04-01 00:00:00     1        3
      #10 groupB 2016-04-02 00:00:00     2        3
      

      解释:diff 选择前后日期之间的最小差值。然后我们寻找diff 的变化,并创建一个新的分组向量id,我们通过它计算汇总度量sum(freq)


      样本数据

      df <- read.table(text =
          " group     dt           freq  diff
       groupA    2016-03-21    1     NA
       groupA    2016-03-22    1     1
       groupA    2016-03-23    1     1
       groupA    2016-03-26    2     NA
       groupA    2016-03-28    1     NA
       groupA    2016-03-29    3     1
       groupA    2016-03-30    3     1
       groupA    2016-03-31    5     1
       groupB    2016-04-01    1     NA
       groupB    2016-04-02    2     1 ", header = T)
      

      更新

      第二个例子:

      # Sample data
      df <- read.table(text =
      " group     dt           freq  diff
      groupA    2016-03-21    1     NA
      groupA    2016-03-22    1     1
      groupA    2016-03-23    1     1
      groupA    2016-03-26    2     NA
      groupA    2016-03-28    1     NA
      groupA    2016-04-01    3     1
      groupA    2016-04-02    3     1
      groupA    2016-04-03    5     1
      groupB    2016-04-01    1     NA
      groupB    2016-04-02    2     1 ", header = T)
      
      df %>%
          mutate(dt = as.POSIXct(dt)) %>%
          group_by(group) %>%
          mutate(
              diff = pmin(c(1, diff(dt)), c(1, diff(lead(dt))), na.rm = T),
              id = cumsum(c(TRUE, diff(diff) != 0) | diff > 1)) %>%
          group_by(group, id) %>%
          mutate(duration = sum(freq)) %>%
          ungroup() %>%
          select(-diff, -id);
      ## A tibble: 10 x 4
      #   group  dt                   freq duration
      #   <fct>  <dttm>              <int>    <int>
      # 1 groupA 2016-03-21 00:00:00     1        3
      # 2 groupA 2016-03-22 00:00:00     1        3
      # 3 groupA 2016-03-23 00:00:00     1        3
      # 4 groupA 2016-03-26 00:00:00     2        2
      # 5 groupA 2016-03-28 00:00:00     1        1
      # 6 groupA 2016-04-01 00:00:00     3       11
      # 7 groupA 2016-04-02 00:00:00     3       11
      # 8 groupA 2016-04-03 00:00:00     5       11
      # 9 groupB 2016-04-01 00:00:00     1        3
      #10 groupB 2016-04-02 00:00:00     2        3        
      

      【讨论】:

      • 谢谢@Maurits。试图调整这个逻辑,不幸的是改变了 A 组中的日期以反映以下日期 - c('2016-03-21', '2016-03-22', '2016-03-23', '2016-03- 26', '2016-03-28', '2016-04-01', '2016-04-02', '2016-04-03') 将 26th 和 28th 的值加起来,因为它们的时间差变为零。
      • @naanan_ 啊,我明白你的意思了;请查看我的更新答案。我在cumsum 中缺少diff &gt; 1 条件。
      • 谢谢!根据您的想法略有不同的解决方案(可能并不理想)。 :) df % 排列(组,dt) %>% group_by(组) %>% 变异(diff = dt - lag(dt),cumsum = cumsum(频率))df[!is.na( df$diff) & df$diff > 1, ]$diff % group_by(group) %>% mutate( id = cumsum(as.numeric(diff))) %>% group_by(group, id) %>% mutate(duration = sum(freq)) %>% ungroup( )
      • 不客气。这就是 R 的优势之一:总是有不止一种解决方案;-)
      猜你喜欢
      • 1970-01-01
      • 2017-11-01
      • 2012-12-07
      • 2020-11-13
      • 1970-01-01
      • 2020-09-30
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多