我有一个包含不同 ID、日期、数量的数据集。所有 ID 都具有相同的确切开始日期,但有些 ID 的起始数量为 0,因此基本上开始日期应该更晚。
我正在尝试过滤行,以便每个 ID
df <- data.frame(ID = c("1", "1", "1", "1", "1", "1",
"2", "2", "2", "2", "2", "2",
"3", "3", "3", "3", "3", "3"),
Date = c(seq(as.Date("2000/1/1"), by = "month", length.out = 6),
seq(as.Date("2000/1/1"), by = "month", length.out = 6),
seq(as.Date("2000/1/1"), by = "month", length.out = 6)),
QTY = c(0, 0, 0, 40, 0, 60, 50, 55, 0, 70, 88, 64, 0, 43, 43, 0, 99, 99))
基本上在上面的 df 示例中,我希望 ID 号 1 从第四个 QTY 值开始,而 ID 号 3 从第二个 QTY 值开始。
我尝试使用 group by 并使用 ifelse 改变一个新列,但我遇到了一些错误。
我预期的 df 应该是从第一个到下面的一个转换,所以只需删除每个 ID 的第一行,直到 QTY 开始大于 0
df <- data.frame(ID = c("1", "1", "1",
"2", "2", "2", "2", "2", "2",
"3", "3", "3", "3", "3"),
Date = c(seq(as.Date("2000/4/1"), by = "month", length.out = 3),
seq(as.Date("2000/1/1"), by = "month", length.out = 6),
seq(as.Date("2000/2/1"), by = "month", length.out = 5)),
QTY = c(40, 0, 60, 50, 55, 0, 70, 88, 64, 43, 43, 0, 99, 99))
最佳答案
如果数据与您的示例中的一样(即没有 NA
或负值),仅此 base
解决方案就足够了:
df[with(df, ave(QTY, ID, FUN = cumsum)) > 0, ]
或 subset(df, ave(QTY, ID, FUN = cumsum) > 0)
,但可能稍微慢一点。
输出:
ID Date QTY
4 1 2000-04-01 40
5 1 2000-05-01 0
6 1 2000-06-01 60
7 2 2000-01-01 50
8 2 2000-02-01 55
9 2 2000-03-01 0
10 2 2000-04-01 70
11 2 2000-05-01 88
12 2 2000-06-01 64
14 3 2000-02-01 43
15 3 2000-03-01 43
16 3 2000-04-01 0
17 3 2000-05-01 99
18 3 2000-06-01 99
这与 dplyr
中的相同:
library(dplyr)
df %>%
group_by(ID) %>%
filter(cumsum(QTY) > 0)
关于根据列值删除分组依据后的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60952796/