【问题标题】:How to aggregate partial weeks in R如何在 R 中聚合部分周
【发布时间】:2018-10-31 03:33:47
【问题描述】:

有很多很棒的方法可以将基于时间戳的数据聚合到几周内。但我有一个真正艰难的,加起来不完整的一周。我已经用谷歌搜索了几天,绞尽脑汁,发现了一些非常困难和丑陋的方法来通过编程 for 循环来解决它。使用 tidyverse 一定有一个优雅的解决方案。

假设我有时间戳格式的观鸟日志。两列:时间戳、鸟名

很容易像

那样按周汇总计数
birds_per_week<- data %>%  group_by(week = cut(timestamp, "week", start.on.monday = TRUE)) %>%   summarise(n())

但我有一个真正的困难,我想知道部分周计数。假设今天是周一上午 10 点,我想知道周一上午 10 点到周三中午之间的所有每周计数。那是一个 2 天 2 小时的窗口。在我的问题中,终点总是星期三中午,但起点不同。

【问题讨论】:

    标签: r count aggregate partial


    【解决方案1】:
    library(lubridate)
    library(tidyverse)
    
    df1 <- data.frame(timestamp = structure(c(1540505400, 1539802080, 1538778660, 1538417640, 1538691660, 
    1538790780, 1538705100, 1539614520, 1539893280, 1539455520, 1540343580, 
    1540178220, 1538628960, 1539533280, 1539572700, 1538823480, 1538967480, 
    1538468400, 1540425600, 1539809880), class = c("POSIXct", "POSIXt"
    ), tzone = ""))
    

    第一个突破日期和小时部分:

    df1$day <- weekdays(df1$timestamp)
    df1$hour <- hour(df1$timestamp)
    

    然后过滤到我们的三天,然后排除周一/周三的开始和结束时间:

    df1 <- df1 %>% filter(day %in% c("Monday", "Tuesday", "Wednesday")) %>% 
      filter(!(day == "Monday" & hour < 10)) %>% 
      filter(!(day == "Wednesday" & hour > 12))
    
    df1$week <- week(df1$timestamp)
    

    然后使用week 作为您的组:

    df1 %>% group_by(week) %>% summarize(count = n())
    
    # A tibble: 3 x 2
       week count
      <int> <int>
    1    40     2
    2    42     1
    3    43     1
    

    【讨论】:

    • 嗯,这工作的第一部分。但是,如果我必须从周六凌晨 2 点到周三中午进行比较,那么周数就会减少。所以那里不好。我正在尝试合并 Jon Spring 的周拆分解决方案。
    • 保持简单,您可以像 df1$week &lt;- epiweek(df1$timestamp+days(1)) 一样调整周,使一周从周六而不是周日开始,这样您就不会失去周六的日子。
    • 好的,这行得通,但我不明白为什么。 'epiweek' 的文档很薄。你能解释一下epiweek在这里做什么吗?顺便说一句,我喜欢这个解决方案。 --edit-- 除非我了解它的工作原理,否则我不应该将它投入生产。
    • 我在这里使用了epiweek,因为它总是从周日到周六运行。 lubridate::week 返回“自 1 月 1 日以来的七天加一”的数量,我认为这可能会在年份之间产生问题。这里的主要关键是知道你一周的开始和结束日期是什么。只要您相应地补偿您的调整,今天是哪一天并不重要。在这种情况下,我知道 epiweek 运行周日至周六,所以如果我在 timestamp 上增加 1 天,这会改变您的一周,因此周六是其中的一部分(您的一周将是周六至周五)。
    【解决方案2】:

    似乎一种方法是记下每一行的“下周三中午”,然后计算它们。

    library(lubridate); library(dplyr)
    
    times_to_test <- data.frame(times = seq.POSIXt(from = ymd_h(2018102400),
                                to   = ymd_h(2018110123), by = "hour"))
    
    times_to_test %>%
      # For checking, helps to see which days are wednesdays
      mutate(weekday = wday(times, label = T)) %>%
      # Wednesday noon is 3.5 days (84 hours) into the week
      mutate(next_Wed_noon = floor_date(times + dhours(84), "1 week") + 
               dhours(84)) %>%
      count(next_Wed_noon)
    
    # A tibble: 3 x 2
      next_Wed_noon           n
      <dttm>              <int>
    1 2018-10-24 12:00:00    12
    2 2018-10-31 12:00:00   168
    3 2018-11-07 12:00:00    36
    

    【讨论】:

    • 我看到这会从周三中午到下周三中午中断,但它如何实现我的部分周总数?
    • 计算每个星期三中午前一周发生的观察次数。如果您的部分周的终点始终是周三中午,我认为这将捕获任何部分周,无论是从周二、周一还是之前的周三晚上开始。
    • 是的,但它没有任何代码可以让它知道我的部分周何时开始。 IE。如果我周五凌晨 2 点或周二下午 4 点开始。这将简单地计算所有实例。我想我可以将它与下面 Mako212 的答案结合起来。我们拭目以待。
    • 先过滤掉一周之前的任何日期是否有效?如果您可以包含输入和输出的示例,这可能会有所帮助。
    • 好吧,等一下,我不确定这是否会减少每周 7 天的时间。如果我每周做一个快速的 difftime,我应该得到 7 天,但我得到 -3.5 天。 'difftime (floor_date(now() + dhours(84), "1 week"), floor_date(now() + dhours(84), "1 week")+ dhours(84), "days")'
    猜你喜欢
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2018-08-25
    相关资源
    最近更新 更多