【问题标题】:How to count and plot a cumulative number over a date range by groups如何按组计算和绘制日期范围内的累积数字
【发布时间】:2023-03-06 09:37:01
【问题描述】:

我想找到绘制图表的最佳方法,该图表根据他们进入小组的日期以及他们可能离开小组的日期显示小组中的个人累积数量。这将在日期值的最小和最大日期范围内。每一行都是一个人。

group_id    Date_started    Date_exit
1           2005-06-23      NA
1           2013-03-17      2013-09-20    
2           2019-10-24      NA  
3           2019-11-27      2019-11-27
4           2019-08-14      NA
3           2018-10-17      NA
4           2018-04-13      2019-10-12
1           2019-07-10      NA

我考虑过在最小/最大范围内每天创建一个新的数据框,然后应用某种函数来计算每行的组总数(根据是否或任何一列中都没有新值)但我不确定一个是否是解决问题的最佳方法,另一个是如何实际运行累积计数函数。

尽管我最终希望能够将其绘制为折线图,以便我可以看到每个组随时间推移的趋势,因为我怀疑其中一个或多个在总体数字方面波动更大。所以我再次不确定 ggplot2 是否已经有一些东西可以处理这个问题。

【问题讨论】:

  • 我不确定我是否理解您想要做什么。你想绘制组中的人数与时间的关系吗?
  • 是的,如果不清楚,抱歉。我想要每个日期每个组中的总人数。随着人们进出群组,这个数字会波动,我需要看到这种变化。

标签: r


【解决方案1】:

正如您所提到的,您需要创建一个包含所需日期的数据框,并为每个组计算该组中有多少人。

我很快把它放在一起,所以我确信有一个更优化的解决方案,但它应该是你正在寻找的。​​p>

library(ggplot2)
library(reshape2) # for melt

# your data
test <- read.table(
  text = 
"group_id,Date_started,Date_exit
1,2005-06-23,NA
1,2013-03-17,2013-09-20
2,2019-10-24,NA
3,2019-11-27,2019-11-27
4,2019-08-14,NA
3,2018-10-17,NA
4,2018-04-13,2019-10-12
1,2019-07-10,NA",
h = T, sep = ",", stringsAsFactors = F
)

# make date series
from <- min(as.POSIXct(test$Date_started))
to <- max(as.POSIXct(test$Date_started))
datebins <- seq(from, to, by = "1 month")

d_between <- function(d, ds, de){
  if(ds <= d & (de > d | is.na(de)))
    return(TRUE)
  return(FALSE)
}

# make df to plot
df <- data.frame(dates = datebins)
df[,paste0("g", unique(test$group_id))] <- 0

for(i in seq_len(nrow(df))){
  for(j in seq_len(nrow(test))){
    gid <- paste0("g", test$group_id[j])
    df[i, gid] <- df[i, gid] + d_between(df$dates[i], test$Date_started[j], test$Date_exit[j])
  }
}


# plot
ggplot(melt(df, id.vars = "dates"), aes(dates, value, color = variable)) + 
  geom_line(size = 1) + theme_bw()

这给出了:

如有必要,请随意使用日期箱(seq())。

编辑:for循环解释

for(i in seq_len(nrow(df))){
  for(j in seq_len(nrow(test))){
    gid <- paste0("g", test$group_id[j])
    df[i, gid] <- df[i, gid] + d_between(df$dates[i], test$Date_started[j], test$Date_exit[j])
  }
}

第一个循环遍历选定的日期。 对于每个日期,使用第二个 for 循环遍历感兴趣的数据框 (test),并使用自定义 d_between() 函数来确定个人是否属于该组。该函数返回一个布尔值(可以转换为 0/1)。然后在我们检查的日期(行i)将值 0 或 1 添加到对应于适当组(使用gid)的df 数据框列。

请注意,我认为个人一加入 (ds &lt;= d) 就成为小组的一部分,但在他们退出之日就不是小组的一部分 (de &gt; d)。

【讨论】:

  • 太好了,谢谢。如果你不介意你能解释一下for循环语句的构造,特别是附加一个'g'字符作为前缀/id的作用。那有什么作用?
  • 附加一个 'g' 只是为了让 df 中的列名以字母开头(如果您的数字实际上是字符作为列名,它可能会导致无法预料的问题)。我将编辑我对 for 循环的解释的答案
  • 仔细观察它并不能完全产生我预期的结果,每个组的图并不像我预期的那样从零开始。我将使用图表中的图像更新问题。
  • @AlexCraig 啊,是的,既然你提到了,那是我的错。当退出日期为 NA 时,我默认设置 return TRUE !这意味着如果检查的日期在该人输入之前,它将被视为真实。让我解决这个问题。
  • @AlexCraig 我已经更新了。它现在应该按预期工作。对于那个很抱歉。我走得太快了:-)
猜你喜欢
  • 2022-11-24
  • 2012-09-24
  • 2018-03-05
  • 2020-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
相关资源
最近更新 更多