【问题标题】:How do I count across a date range in an R datatable如何计算 R 数据表中的日期范围
【发布时间】:2018-02-27 15:59:01
【问题描述】:
ID      FROM        TO
1881    11/02/2013  11/02/2013
3090    09/09/2013  09/09/2013
1113    24/11/2014  06/12/2014
1110    24/07/2013  25/07/2013
111     25/06/2015  05/09/2015

如果我有假期日期的 data.table,FROM 和 TO,我想知道任何给定月份有多少人在度假。

我试过了:

dt[, .N, by=.(year(FROM), month(FROM))]

但显然它会排除两个月内休假的人。 IE。从 1 月到 2 月休假的人只会出现在 1 月的计数中,而不会出现在 2 月的计数中,即使他们仍在 2 月休假

上面代码的输出显示年、月和数字正是我要寻找的。​​p>

    year month N
 1: 2013     2 17570
 2: 2013     9 16924
 3: 2014    11 18809
 4: 2013     7 16984
 5: 2015     6 14401
 6: 2015    12 10239
 7: 2014     3 19346
 8: 2013     5 14864

编辑:我希望每个月都有人外出度假。所以 ID 111 将在 6 月、7 月、8 月和 9 月计算。

编辑 2:

在完整数据集上运行 uwe 的代码会生成下面的 Total Count 列。
对休假 30 天的人的完整数据集进行子集化,会产生下面各列中的计数。这些相互添加的列应该等于 Total Count,因此 DIFFERENCE 应该为 0,但事实并非如此。

month Total count <=30 >30 (<=30) + (>30) DIFFERENCE 01/02/2012 899 4 895 899 0 01/03/2012 3966 2320 1646 3966 0 01/04/2012 8684 6637 2086 8723 39 01/05/2012 10287 7586 2750 10336 49 01/06/2012 12018 9080 3000 12080 62

【问题讨论】:

  • 使用melt组合FROMTO然后分组。
  • ID 111要怎么算?仅在 2015 年 6 月和 2015 年 9 月?还是在 2015 年 6 月、7 月、8 月和 9 月?
  • 我想计算 2015 年 6 月、7 月、8 月和 9 月。我想弄清楚在任何给定月份去度假的人数。 ID 111 在 2015 年 6 月、7 月、8 月和 9 月离开,因此每个月都会计算在内。
  • 上述结果是您对您提供的数据的期望吗?
  • 我同意 Uwe 的建议 - 最好发布一个新问题(使用可重现的数据),除非他以某种方式认识到根本问题并提供快速解决方案。

标签: r count data.table date-range


【解决方案1】:

OP并没有说明具体的计数规则是什么,例如,如果同一个ID在同一个月有多个不重叠的假期,如何计算。

以下解决方案基于以下规则:

  1. 每个ID 可能出现在多行中。
  2. 对于每一行,计算FROMTO 之间的总月份数(包括FROMTO 月份)。例如,ID111 计入 2015 年 6 月、7 月、8 月和 9 月的月份。
  3. 一个月的最后一天和第一天的假期全部计算在内,例如,从 5 月 31 日开始到 6 月 1 日结束的假期计入两个月。
  4. 如果ID 在一个月内有多个假期,则仅计为一次。

为了验证代码是否实现了这些规则,我必须通过其他用例增强 OP 提供的示例数据集(请参阅下面的数据部分)

library(data.table)
library(lubridate)
# coerce dt to data.table object and character dates to class Date
setDT(dt)[, (2:3) := lapply(.SD, dmy), .SDcols = 2:3]

# for each row, create sequence of first days of months 
dt[, .(month = seq(floor_date(FROM, "months"), TO, by = "months")), by = .(ID, rowid(ID))][
  # count the number of unique IDs per month, order result by month
  , uniqueN(ID), keyby = month]
         month V1
 1: 2013-02-01  1
 2: 2013-07-01  1
 3: 2013-09-01  2
 4: 2014-11-01  1
 5: 2014-12-01  1
 6: 2015-06-01  1
 7: 2015-07-01  1
 8: 2015-08-01  1
 9: 2015-09-01  1
10: 2015-11-01  1
11: 2015-12-01  1
12: 2016-06-01  1
13: 2016-07-01  1
14: 2016-08-01  1
15: 2016-09-01  1

数据

基于 OP 的示例数据集,但通过其他用例进行了扩展:

library(data.table)
dt <- fread(
  "ID      FROM        TO
1881    11/02/2013  11/02/2013
1881    23/02/2013  24/02/2013
3090    09/09/2013  09/09/2013
3091    09/09/2013  09/09/2013
1113    24/11/2014  06/12/2014
1110    24/07/2013  25/07/2013
111     25/06/2015  05/09/2015
111     25/11/2015  05/12/2015
11      25/06/2016  01/09/2016"
)

【讨论】:

  • 非常感谢。你应用的规则正是我想要的。现在我已经打开了它并开始了解它是如何工作的!
  • 我很高兴这似乎对你有用。我不确定我对如何计算每月假期的规则的解释是否符合您的要求。
  • 我认为可能有问题。我尝试在整个数据集上运行此代码。然后,我将整个数据集分成两个数据表,一个用于休假 30 天或更长时间的人,另一个用于休假少于 30 天的人。在两个不同的数据表上再次运行代码会产生不同的总数。
  • 什么问题?
  • 不用担心格式。我能够阅读表格。令我困惑的是差异。也许,最好发布一个新问题,包括子集和汇总的代码。此外,格式化比评论更容易:-)
【解决方案2】:

对于上面给出的数据,你会这样做:

melt(dat,1)[,value:=as.Date(sub("\\d+","20",value),"%d/%m/%Y")][,
         seq(value[1],value[2],by="1 month"),by=ID][,.N,by=.(year(V1),month(V1))]
   year month N
1: 2013     2 1
2: 2013     9 1
3: 2014    11 1
4: 2014    12 1
5: 2013     7 1
6: 2015     6 1
7: 2015     7 1
8: 2015     8 1
9: 2015     9 1

【讨论】:

  • 我不确定这是否是正确的结果,因为没有 2015 年 7 月和 2015 年 8 月的计数(请参阅 ID111)。我已要求 OP 进行澄清。
  • 我明白你的意思
  • 还有一个问题:OP 真的想让 ID 的 1881、3090 和 1110 计数两次吗?
  • 很好,两种方法都使用seq(),但在处理具有相同ID 的多行时存在差异。 OP 仍然必须澄清这是否可能发生在他的生产数据集中。
猜你喜欢
  • 2020-06-05
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 2020-01-13
  • 1970-01-01
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
相关资源
最近更新 更多