如何计算 R 数据表中的日期范围
How do I count across a date range in an R datatable
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 个休假日期,从和到,我想知道任何给定月份有多少人在休假。
我试过了:
dt[, .N, by=.(year(FROM), month(FROM))]
但显然它会排除跨两个月休假的人。 IE。从 1 月到 2 月休假的人只会出现在 1 月的计数中,而不是 2 月的计数,即使他们在 2 月仍在休假
上面显示年、月和数字的代码的输出正是我正在寻找的。
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会在六月,七月,八月和九月被统计
编辑 2:
运行 uwe 在完整数据集上的代码生成下面的总计数列。
对休假时间 <= 30 天和 > 30 天的人的完整数据集进行子集生成下面各列中的计数。这些相加的列应等于总计数,因此 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(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
OP没有说明具体的统计规则是什么,比如同一个ID在同一个月份有多个non-overlapping段假期怎么算
下面的解决方案基于以下规则:
- 每个
ID
可能出现在不止一行中。
- 对于每一行,计算
FROM
和 TO
之间的月份总数(包括 FROM
和 TO
月份)。例如,ID
111 是在 2015 年 6 月、7 月、8 月和 9 月计算的。
- 一个月的最后一天和第一天的假期全部计算在内,例如,从 5 月 31 日开始到 6 月 1 日结束的假期都计算在两个月中。
- 如果
ID
在一个月内有多个假期,则只计算一次。
为了验证代码是否实现了这些规则,我必须使用其他用例增强 OP 提供的示例数据集(请参阅下面的 Data 部分)
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"
)
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 个休假日期,从和到,我想知道任何给定月份有多少人在休假。
我试过了:
dt[, .N, by=.(year(FROM), month(FROM))]
但显然它会排除跨两个月休假的人。 IE。从 1 月到 2 月休假的人只会出现在 1 月的计数中,而不是 2 月的计数,即使他们在 2 月仍在休假
上面显示年、月和数字的代码的输出正是我正在寻找的。
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会在六月,七月,八月和九月被统计
编辑 2:
运行 uwe 在完整数据集上的代码生成下面的总计数列。
对休假时间 <= 30 天和 > 30 天的人的完整数据集进行子集生成下面各列中的计数。这些相加的列应等于总计数,因此 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(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
OP没有说明具体的统计规则是什么,比如同一个ID在同一个月份有多个non-overlapping段假期怎么算
下面的解决方案基于以下规则:
- 每个
ID
可能出现在不止一行中。 - 对于每一行,计算
FROM
和TO
之间的月份总数(包括FROM
和TO
月份)。例如,ID
111 是在 2015 年 6 月、7 月、8 月和 9 月计算的。 - 一个月的最后一天和第一天的假期全部计算在内,例如,从 5 月 31 日开始到 6 月 1 日结束的假期都计算在两个月中。
- 如果
ID
在一个月内有多个假期,则只计算一次。
为了验证代码是否实现了这些规则,我必须使用其他用例增强 OP 提供的示例数据集(请参阅下面的 Data 部分)
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"
)