我有一个非常简单的问题,显然没有一个非常简单的解决方案。假设我有以下数据:
> test <- data.frame(Day = c(1:10), Counts = c(0, 0, 6, 0, 0, 5, 1, 0, 3, 4))
> test
Day Counts
1 1 0
2 2 0
3 3 6
4 4 0
5 5 0
6 6 5
7 7 1
8 8 0
9 9 3
10 10 4
根据有关数据来源的知识,我可以放心地假设在随后的几天内不会发生非零计数。相反,原始日错过了一些计数。例如,第6天和第7天的计数将属于第6天(总共6个计数)。
我想找到一个可以产生所需输出的常规解决方案:
Day Counts
1 1 0
2 2 0
3 3 6
4 4 0
5 5 0
6 6 6
7 8 0
8 9 7
注意第7天和第10天是如何被删除的,并且它们的计数已被添加到第6天和第9天。这确实是我后续数据分析所需的格式,这将受到“假”计数的影响。
我已经尝试过使用zoo
和RcppRoll
包中的函数的多个“移动/滚动窗口”方法,以及使用dplyr
s lag()
and lead()
函数的所谓整洁解决方案,但没有Heureka!迄今。由于我的数据集包含数十万行(以及更多列),因此非常不希望进行手动校正。
任何帮助表示赞赏!即使它只是指向一个现有的问题......
p.s。:显示tidyverse解决方案的奖励积分,因为我打算在管道工作流程中使用它。
编辑:感谢您的解决方案,他们都完美地工作!让我的一天:)
lead
和lag
肯定是一种方法。
test %>%
mutate(lead1 = lead(Counts, 1), lag1 = lag(Counts)) %>%
mutate(Counts2 = if_else(Counts > 0, Counts + lead1, Counts)) %>%
filter(!(lag1 > 0 & Counts > 0))
代码可以缩短为
test %>%
mutate(Counts = if_else(Counts > 0, Counts + lead(Counts, 1), Counts)) %>%
filter(!(lag(Counts) > 0 & Counts > 0))
Day Counts
1 1 0
2 2 0
3 3 6
4 4 0
5 5 0
6 6 6
7 8 0
8 9 7
另一种基于lag
和lead
的简单dplyr方法:
test %>%
mutate(Counts = ifelse(Counts != 0 & lead(Counts) != 0,
Counts + lead(Counts), Counts)) %>%
mutate(Counts = ifelse(Counts != 0 & lag(Counts) != 0, NA, Counts)) %>%
na.omit()
Day Counts
1 1 0
2 2 0
3 3 6
4 4 0
5 5 0
6 6 6
8 8 0
9 9 7
1)这使用data.table包。首先将测试转换为data.table dt
,然后使用rleid
创建分组变量,该变量为每次运行的零或非零创建一个组。对于每个这样的组,返回计数的总和,后跟尾随零:
library(data.table)
dt <- as.data.table(test)
dt[, Fix := c(sum(Counts), 0 * Counts[-1]), by = rleid(Counts > 0)]
赠送:
> dt
Day Counts Fix
1: 1 0 0
2: 2 0 0
3: 3 6 6
4: 4 0 0
5: 5 0 0
6: 6 5 6
7: 7 1 0
8: 8 0 0
9: 9 3 7
10: 10 4 0
2)这使用dplyr和data.table中的rleid
:
library(dplyr)
library(data.table)
test %>%
group_by(rleid(Counts > 0)) %>%
mutate(Fix = c(sum(Counts), 0 * Counts[-1])) %>%
ungroup