【问题标题】:Group by summarize in between dates with dplyr使用 dplyr 在日期之间按汇总进行分组
【发布时间】:2021-01-22 19:19:35
【问题描述】:

在使用 summarise 时,我很难理解 dplyr 中的一些逻辑。

我有兴趣为每个 ID 中的每个日期计算一些感兴趣的统计数据(例如,某个列的平均值),并且我有包含 start_date 和 end_date 列的数据。

假设我有分层数据,每行有一个 IDsub 列,IDsub 所属的每个更广泛的类别都有一个 ID 列,一个 start_date,一个 end_date 和一个有意义的 value

IDsub <- c("1001", "1002", "1003", "1004")
ID <- c("id1", "id1", "id2", "id2")
start_date <- as.Date(c("2021-01-01", "2021-01-02", "2021-01-05", "2021-01-10"))
end_date <- as.Date(c("2021-01-10", "2021-01-09", "2021-01-13", "2021-01-12"))
value <- c(1, 2, 2, 0)

df <- tibble(IDsub, ID, start_date, end_date, value)

原始数据如下:

IDsub ID    start_date end_date   value
1001  id1   2021-01-01 2021-01-10     1
1002  id1   2021-01-02 2021-01-09     2
1003  id2   2021-01-05 2021-01-13     2
1004  id2   2021-01-10 2021-01-12     0

然后我转换数据,使其按date 组织:

df1 <- df %>%
  transmute(ID, IDsub, value, date = map2(min(df$start_date), max(df$end_date), seq, by = "day")) %>%
  unnest("date")

结果如下:

ID    IDsub value   date      
id1   1001      1 2021-01-01
id1   1001      1 2021-01-02
id1   1001      1 2021-01-03
id1   1001      1 2021-01-04
...
id2   1004      0 2021-01-10
id2   1004      0 2021-01-11
id2   1004      0 2021-01-12
id2   1004      0 2021-01-13

这是我被绊倒的地方。我想为每个ID 中的每个date 计算value 的平均值,但下面的代码似乎没有这样做。

df2 <- df1 %>%
  group_by(ID, date) %>%
  summarize(mean(value))

前面的代码产生以下输出:

ID    date       `mean(value)`
id1   2021-01-01           1.5
id1   2021-01-02           1.5
id1   2021-01-03           1.5
id1   2021-01-04           1.5
id1   2021-01-05           1.5

这没有意义,因为 id1 的 2020-01-01 应该具有与 id1 的 2020-01-02 不同的平均值,因为在 2021-01-01 上只存在 value=1 的 IDsub 1001,而IDsub 1001 和 1002 的值分别为 1 和 2,它们都出现在 2021 年 1 月 2 日。所以 2021-01-01 和 2021-01-02 的值应该不同,但它们不是。

我显然在这里遗漏了一些简单的东西。

【问题讨论】:

  • id1 的 2020-01-01 和 id1 的 2020-01-02 的值应该是多少? df1 %&gt;% filter(between(date, as.Date('2021-01-01'), as.Date('2021-01-02'))) %&gt;% filter(ID == "id1") %&gt;% arrange(date)
  • 对于 2021-01-01 和 id1,平均值应为 1。对于 2021-01-02 和 id1,平均值应为 1.5。

标签: r dplyr tidyverse


【解决方案1】:

我认为您的 map2 陈述不正确。
这是使用 lubridate 的 within 函数的另一个可能选项。

library(dplyr)
library(lubridate)

df <- structure(list(IDsub = c("1001", "1002", "1003", "1004"), 
                     ID = c("id1", "id1", "id2", "id2"), 
                     start_date = structure(c(18628, 18629, 18632, 18637), class = "Date"), 
                     end_date = structure(c(18637, 18636, 18640, 18639), class = "Date"), 
                     value = c(1, 2, 2, 0)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"))

#find start end date and create sequence
firstdate <- min(df$start_date)
lastdate <- max(df$end_date)
timeseq <-seq(firstdate, lastdate, by="1 day")

#split by id
dflist<-split(df, df$ID)
lapply(names(dflist), function(dfname){
   
   iddf<-dflist[[dfname]]
   #create time intervals for each row 
   intervals <-interval(iddf$start_date, iddf$end_date)
   meanvalues <- sapply(timeseq, function(nrow){
      withinresult <- nrow %within% intervals
      mean(iddf$value[withinresult], na.rm=TRUE)
   })
   tibble(dfname, timeseq, meanvalues)
})

lapply 语句的最终结果是按 ID 列出的数据帧列表。可以将它们绑定在一起并根据最终意图进行重塑。

【讨论】:

  • 谢谢,这看起来很有希望。您是否知道如何在此处按 ID 分组,以便按 ID 内的日期报告平均值(按 id1 与 id2 分开的日期)?
猜你喜欢
  • 2020-05-15
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多