используйте fill для условного заполнения значений NA без цикла - PullRequest
0 голосов
/ 26 апреля 2018

Я ищу способ условно использовать команду 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)

Каждая запись представляет дату и измерение.Для некоторых элементов измерение было пропущено, когда оно не изменилось, для других измерения не были релевантны на дату (указанная первой записью для этого регистра, являющейся 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, но он заменяет только NA в строке 2, и никакие другие, если только он не запускается снова, когда он заменяет строку 3 и т. Д.

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

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

1 Ответ

0 голосов
/ 26 апреля 2018

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

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