我有一张桌子:
Name| Start | Finish |
----|-----------|-----------|
A |2015-01-22 |2015-02-04 |
B |2015-01-02 |2015-01-10 |
A |2015-01-22 |2015-02-14 |
B |2015-01-02 |2015-02-10 |
Run Code Online (Sandbox Code Playgroud)
我需要按月中断月经。如果一个时期在一个月内开始并在下一个月结束,那么我需要将其分为两个时期。如果月经在同一个月开始和结束,那么就应该如此。假设 period 不能包含超过一个月的第一天。换句话说,每行可以拆分为不超过两行。结束(周期结束)总是大于开始。
这就是我想要得到的:
Name| Start | Finish |
----|-----------|-----------|
A |2015-01-22 |2015-01-31 |
A |2015-02-01 |2015-02-04 |
A |2015-01-22 |2015-01-31 |
A |2015-02-01 |2015-02-14 |
B |2015-01-02 |2015-01-10 |
B |2015-01-02 |2015-01-31 |
B |2015-02-01 |2015-02-10 |
Run Code Online (Sandbox Code Playgroud)
输出行的顺序无关紧要。
这是该表的代码:
Name = c("A", "B", "A", "B")
Start = c(as.Date("2015-01-22"), as.Date("2015-01-02"), as.Date("2015-01-22"), as.Date("2015-01-02"))
Finish = c(as.Date("2015-02-04"), as.Date("2015-01-10"), as.Date("2015-02-14"), as.Date("2015-02-10"))
df = data.frame(Name, Start, Finish)
Run Code Online (Sandbox Code Playgroud)
有什么建议可以如何做到吗?
问题已更改。最初,该Name列唯一标识该行,但问题的更改版本不再具有该行。这里的答案已进行相应修改,以便现在我们通过行号(即 )来识别行1:nrow(df),而不是df$Name在 的第二个参数中by。否则,代码不变。
用于by按行分割数据帧,给出单行并使用匿名函数对每一行进行操作。它计算开始的月末 ( eom),如果结束较大,则输出两行数据帧,否则返回相同的数据帧。将它们全部放在一起rbind。
library(zoo)
do.call("rbind", by(df, 1:nrow(df), function(x) with(x, {
eom <- as.Date(as.yearmon(Start), frac = 1)
if (eom < Finish)
data.frame(Name, Start = c(Start, eom+1), Finish = c(eom, Finish))
else x
})))
Run Code Online (Sandbox Code Playgroud)
给予:
Name Start Finish
1.1 A 2015-01-22 2015-01-31
1.2 A 2015-02-01 2015-02-04
2 B 2015-01-02 2015-01-10
3.1 A 2015-01-22 2015-01-31
3.2 A 2015-02-01 2015-02-14
4.1 B 2015-01-02 2015-01-31
4.2 B 2015-02-01 2015-02-10
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
351 次 |
| 最近记录: |