Как реализовать условный поиск в верхнем направлении от каждой строки с помощью dplyr? - PullRequest
0 голосов
/ 09 октября 2019

Ниже приведен пример фрейма данных:

df <- data.frame(
  A=c(1,2,3,4,5,6,7),
  B=c(1,NA,3,2,NA,4,3),
  C=c(NA,1,NA,NA,1,NA,NA),
  D=c(NA,2,NA,NA,4,NA,NA))

> df
  A  B  C  D
1 1  1 NA NA
2 2 NA  1  2
3 3  3 NA NA
4 4  2 NA NA
5 5 NA  2  4
6 6  4 NA NA
7 7  3 NA NA

Я хочу реализовать следующие манипуляции с использованием dplyr функции трубопровода в R.

  • Добавление новогостолбцы E, которые содержат D в следующих условиях.
  • Поиск !is.na(C) из каждой строки в верхнем направлении
  • Если !is.na(C), дополнить столбец E сохраненным значениемв D

Это желаемый вывод.

> df2
  A  B  C  D  E
1 1  1 NA NA NA
2 2 NA  1  2 NA
3 3  3 NA NA NA
4 4  2 NA NA NA
5 5 NA  2  4  2
6 6  4 NA NA NA
7 7  3 NA NA NA

Я предпочитаю осуществлять поиск в верхнем направлении с использованием функции трубопровода в dplyr. Я знаю функцию lag в base, но она не работает для этой проблемы. Я также пытался использовать функцию slice в dplyr, но она также не выполняет поиск по каждой строке в верхнем направлении.

Я надеюсь, что вы могли бы предложить другие решения по этому вопросу. Я пытался использовать slice в dplyr, но я не мог выполнить соответствующую фильтрацию для каждой строки.

Ответы [ 2 ]

2 голосов
/ 09 октября 2019

Мы можем скопировать содержимое D в E и использовать tidyr::fill для замены NA на недавние значения, отличные от NA, и использовать lag для получения предыдущего значения в E.

library(dplyr)

df %>%
  mutate(E = D) %>%
  tidyr::fill(E)  %>%
  mutate(E = replace(lag(E), is.na(D), NA))


#  A  B  C  D  E
#1 1  1 NA NA NA
#2 2 NA  1  2 NA
#3 3  3 NA NA NA
#4 4  2 NA NA NA
#5 5 NA  1  4  2
#6 6  4 NA NA NA
#7 7  3 NA NA NA
2 голосов
/ 09 октября 2019

Используется bind_rows для объединения значений NA C со значениями, отличными от NA C, с вашими критериями отставания:

bind_rows(df%>%
            filter(is.na(C))%>%
            mutate(E = NA)
          ,
          df%>%
            filter(!is.na(C))%>%
            mutate(E = lag(D))
          )%>%
  arrange(A)

  A  B  C  D  E
1 1  1 NA NA NA
2 2 NA  1  2 NA
3 3  3 NA NA NA
4 4  2 NA NA NA
5 5 NA  1  4  2
6 6  4 NA NA NA
7 7  3 NA NA NA

В thisочень просто:

library(data.table)

dt <- as.data.table(df)
dt[!is.na(C), E:=shift(D)][]

   A  B  C  D  E
1: 1  1 NA NA NA
2: 2 NA  1  2 NA
3: 3  3 NA NA NA
4: 4  2 NA NA NA
5: 5 NA  1  4  2
6: 6  4 NA NA NA
7: 7  3 NA NA NA

База тоже неплохая:

# base
df2 <- df

df2$E <- NA
ind <- !is.na(df2$C)
df2[ind, 'E'] <- df2[ind, 'D'][c(NA,seq_len(sum(ind)-1))]

df2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...