使用:
library(data.table)
setDT(df1)[a2 == 1, mon := cut(seq_along(a2), 12, sprintf('%02d',1:12)), by = City2][]
给予:
City2 a2 mon
1: City001 1 01
2: City001 1 01
3: City001 1 01
4: City001 1 01
5: City001 0 NA
---
269596: City200 1 12
269597: City200 0 NA
269598: City200 1 12
269599: City200 1 12
269600: City200 1 12
这是做什么的:
- 使用
setDT(df1) 时,data.frame 会转换为 data.table(仍然是 data.frame)。
- 使用
a2 == 1 过滤数据并使用by = City2 分组。
- 最后,通过引用为
cut 选定的行创建一个新列mon。
- 对于
City2 列的每一组,cut 将一个序列(seq_along(a2);它以1 开始并以组大小结束,即第一组的671)在 12(几乎) 相等的部分。每个部分都有一个相应的标签 (sprintf('%02d',1:12))。有关详细信息,请参阅?cut。
上述方法的缺点是记录数最少的中断不在末尾。可以通过总结结果来展示:
> df1[a2 == 1, .N, by = .(City2,mon)][1:24]
City2 mon N
1: City001 01 56
2: City001 02 56
3: City001 03 56
4: City001 04 56
5: City001 05 56
6: City001 06 56
7: City001 07 55
8: City001 08 56
9: City001 09 56
10: City001 10 56
11: City001 11 56
12: City001 12 56
13: City002 01 56
14: City002 02 55
15: City002 03 56
16: City002 04 55
17: City002 05 56
18: City002 06 55
19: City002 07 55
20: City002 08 56
21: City002 09 55
22: City002 10 56
23: City002 11 55
24: City002 12 56
要获得最后记录数较少的中断,您可以使用:
setDT(df1)[a2 == 1, mon := cut(seq_along(a2),
{n <- .N/12;
br <- c(0, rep(ceiling(n), round((n-floor(n))*12)), rep(floor(n), round((floor(n) - n + 1)*12)));
unique(c(cumsum(br),.N))},
sprintf('%02d',1:12)),
by = City2][]
第一个解决方案中的断点数 (12) 被一个断点向量替换,该向量在大括号 ({n <- .N/12 .... unique(c(cumsum(br),.N))}) 之间的部分中分别为每组 City2 计算。这部分计算间隔的方式是观察数不是随机分布在几个月内,而是观察数较少的月份总是在末尾。
除了上面的解释之外,大括号之间的部分做了以下事情:
- 首先将每组中的观察数 (
.N) 除以 12。这通常不是整数,而是小数点后的数值。
-
rep(ceiling(n), round((n-floor(n))*12)) 计算第一组 (ceiling(n)) 的较高观察次数,并重复一定次数,该次数由 n 的十进制值与 round((n-floor(n))*12) 确定。
- 较小组(中断)的组大小由
rep(floor(n), round((floor(n) - n + 1)*12)) 确定,方法类似。 floor(n) 确定组的大小,而round((floor(n) - n + 1)*12) 确定较小的组所需的组数。
- 前两个向量以起始零 (
c(0, rep ... )) 放在一起。
- 通过在其上使用 cumsum,您会得到一个以
0 开头的向量,最后添加组大小 (.N)。通过将其包装在 unique 中,您可以确保获得唯一的中断值。这是必需的,因为当 n 是一个完全四舍五入的数字(例如 600/12 的结果)时,最后一个中断值在向量中出现两次。
同样的检查现在表明已经实现了:
> df1[a2 == 1, .N, by = .(City2,mon)][1:24]
City2 mon N
1: City001 01 56
2: City001 02 56
3: City001 03 56
4: City001 04 56
5: City001 05 56
6: City001 06 56
7: City001 07 56
8: City001 08 56
9: City001 09 56
10: City001 10 56
11: City001 11 56
12: City001 12 55
13: City002 01 56
14: City002 02 56
15: City002 03 56
16: City002 04 56
17: City002 05 56
18: City002 06 56
19: City002 07 55
20: City002 08 55
21: City002 09 55
22: City002 10 55
23: City002 11 55
24: City002 12 55