R 使用“填充”有条件地填充NA值,而不使用循环
我正在寻找一种方法,在满足条件的情况下,有条件地使用fill()命令或类似的命令来基于前一行值填充NA值。我一直在寻找解决方案,但没有找到任何有效的方法 数据如下所示,但存在多个“caseval”测量值:R 使用“填充”有条件地填充NA值,而不使用循环,r,date,dplyr,tidyr,R,Date,Dplyr,Tidyr,我正在寻找一种方法,在满足条件的情况下,有条件地使用fill()命令或类似的命令来基于前一行值填充NA值。我一直在寻找解决方案,但没有找到任何有效的方法 数据如下所示,但存在多个“caseval”测量值: casedate = seq(as.Date('2018/1/1'),as.Date('2018/3/5'),b='week') caseid = c(rep(1,10),rep(2,10),rep(3,10)) caseval = c(80,rep(NA,4),rep(80,5),40,re
casedate = seq(as.Date('2018/1/1'),as.Date('2018/3/5'),b='week')
caseid = c(rep(1,10),rep(2,10),rep(3,10))
caseval = c(80,rep(NA,4),rep(80,5),40,rep(NA,2),rep(40,4),rep(50,3),rep(NA,7),rep(70,3))
df = cbind.data.frame(casedate,caseid, caseval)
每个记录代表一个日期和一个度量。对于某些项目,当测量值没有变化时跳过测量值,对于其他项目,在日期上没有相关测量值(由案例ID为NA的第一条记录指示),如下面第21行。使用“无条件填充”时,第21:27行用caseid 2的值填充,这是不正确的
casedate caseid caseval
1 2018-01-01 1 80
2 2018-01-08 1 NA
3 2018-01-15 1 NA
4 2018-01-22 1 NA
5 2018-01-29 1 NA
6 2018-02-05 1 80
7 2018-02-12 1 80
8 2018-02-19 1 80
9 2018-02-26 1 80
10 2018-03-05 1 80
11 2018-01-01 2 40
12 2018-01-08 2 NA
13 2018-01-15 2 NA
14 2018-01-22 2 40
15 2018-01-29 2 40
16 2018-02-05 2 40
17 2018-02-12 2 40
18 2018-02-19 2 50
19 2018-02-26 2 50
20 2018-03-05 2 50
**21 2018-01-01 3 NA**
22 2018-01-08 3 NA
23 2018-01-15 3 NA
24 2018-01-22 3 NA
25 2018-01-29 3 NA
26 2018-02-05 3 NA
27 2018-02-12 3 NA
28 2018-02-19 3 70
29 2018-02-26 3 70
30 2018-03-05 3 70
我试过一个循环,它可以工作,但速度很慢
for (i in 1:nrow(df)) {
for (item in list_casevals) {
if (df[i,'caseid']==df[i-1,'caseid'] && is.na(df[i,item])) {
df[i,item]=df[i-1,item]
}
}
}
我尝试过在ifelse中使用fill,但它只替换第2行中的NA,没有其他的,除非它在替换第3行时再次运行,等等
df = df %>%
mutate(., caseval = ifelse(lag(caseid)==caseid & is.na(caseval),fill(caseval),caseval))
除了使用循环之外,还有没有更快的方法来完成这项工作?您可以按照
caseid
进行分组吗?比如说,
df <- df %>%
group_by(caseid) %>%
fill(caseval) %>%
ungroup()
df%
分组依据(案例ID)%>%
填充(caseval)%>%
解组()
谢谢!在水平切片上测试,这似乎有效,但我从未以这种方式使用group_by。您能解释一下这是如何工作的吗?groupby
的要点是使用分组变量对数据的每个子集执行后续操作。这可能不是通常使用它的地方,但它确实值得尝试。。。它成功了。