我正在寻找一种方法来有条件地使用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,rep(NA,2),rep(40,4),rep(50,3),rep(NA,7),rep(70,3))
df = cbind.data.frame(casedate,caseid, caseval)
每条记录代表一个日期和一个测量。对于某些项目,当它没有改变时跳过测量,对于其他项目,没有测量与日期相关(由该caseid的第一个记录表示为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,但它只替换第2行中的NA,而不替换其他,除非它再次运行,当它替换第3行时等等。
df = df %>%
mutate(., caseval = ifelse(lag(caseid)==caseid & is.na(caseval),fill(caseval),caseval))
除了使用循环之外,还有更快的方法吗?
答案 0 :(得分:4)
你可以按caseid
分组吗?例如,
df <- df %>%
group_by(caseid) %>%
fill(caseval) %>%
ungroup()