используйте fill для условного заполнения значений NA без цикла


Я ищу способ условно использовать команду 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 ниже. При использовании fill without conditions строки 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]
    }
  }
}

И я пробовал использовать fill в ifelse, но он заменяет только NA в строке 2, и никаких других, если он не запускается снова, когда он заменяет строку 3 и т. д.

df = df %>%
  mutate(., caseval = ifelse(lag(caseid)==caseid & is.na(caseval),fill(caseval),caseval))

Есть ли более быстрый способ сделать это, кроме использования цикла?

1 2

1 ответ:

Можете ли вы просто сгруппироваться по caseid? Например,

df <- df %>%
  group_by(caseid) %>%
  fill(caseval) %>%
  ungroup()