R -Поиск столбцов с одним непропущенным значением и заполнение пропущенных значений этим уникальным непропущенным значением - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть фрейм данных, который содержит недостающие данные (NA).Я хочу найти столбцы, которые имеют только одно не пропущенное значение, а затем заполнить эти столбцы этим значением.Например, если мой исходный набор данных выглядит следующим образом:

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

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

Я хочу достичь:

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

Сначала я создал эту функцию, чтобы делать то, что я хочу: (пожалуйста, дайте мнезнаю, есть ли у вас лучший вариант для этого)

fill_NAs <- function(x){
  x %>% fill(., .direction = "up") %>%
        fill(., .direction = "down")
}

А потом я попытался использовать функции mutate_at или mutate_if, но мне не удалось заставить его работать.Вот некоторые из моих попыток:

1)

df= df %>% mutate_if ( ~ length(unique(na.omit(.)))==1, ~ fill_NAs(.))

Я получил эту ошибку:

Ошибка в mutate_impl (.data, dots): оценкаошибка: нет применимого метода для 'fill_', примененного к объекту класса "c ('double', 'numeric')"

.

2)

df_PMM_imp = df_PMM_imp %>% mutate_at(.,names(select_if(.,length(unique(na.omit(.)))==1)), ~ fill_NAs(.))

Я получил эту ошибку:

Ошибка в tbl_if_vars (.tbl, .predicate, caller_env (), .include_group_vars = TRUE): длина (.p) == длина (tibble_vars) равнане ИСТИНА

В общем, я не могу понять логику mutate_if или mutate_at, я всегда сталкиваюсь с такими проблемами.Итак, мои вопросы:

1) Какой правильный синтаксис позволяет достичь того, что я хочу?2) Почему я получаю эти ошибки выше, что я делаю не так?

Заранее большое спасибо.

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019

Вы можете перебирать столбцы, проверять длину уникальных элементов, которые не являются NA, и заменять NA s в столбце, если он содержит только один уникальный элемент.

df[] <- lapply(df, function(x) {
  y <- unique(na.omit(x))
  if(length(y) == 1) {
    x <- y
  } else x
})

Результат

df
   A B C D
1  1 3 2 1
2  2 3 5 1
3 NA 3 6 1
4 NA 3 3 1
5  1 3 6 1
0 голосов
/ 25 февраля 2019

A dplyr способ:

library(dplyr)

df %>% 
  mutate_all(~ case_when(
    n_distinct(.[na.omit(.)]) == 1 ~ first(na.omit(.)),
    TRUE ~ .
    )
  )

Выход:

   A B C D
1  1 3 2 1
2  2 3 5 1
3 NA 3 6 1
4 NA 3 3 1
5  1 3 6 1
0 голосов
/ 25 февраля 2019

Привет, @Elif Cansu Akoğuz,

Вы можете довольно легко достичь своей цели, используя for() -параллель для итерации по вашему фрейму данных и проверки по столбцу, если он соответствует вашим требованиям:

for (i in 1:ncol(df)) {
    if (any(is.na(unique(df[i]))) == TRUE & nrow(unique(df[i])) == 2) {
        ...
    }
}

С помощью оператора any(is.na(unique(df[i]))) вы проверяете, есть ли где-нибудь в столбце NA, а с помощью nrow(unique(df[i])) == 2 вы проверяете, состоит ли столбец только из двух уникальных значений.Таким образом, если столбец соответствует обоим операторам, вы знаете, что он состоит из 2 значений, одно из которых в NA.

Далее, вы хотите заменить все значения в столбце значением, которое не является NA,Чтобы сделать это, вы можете использовать na.omit(), чтобы выбросить значение NA, и затем повторить оставшееся значение для того, насколько длинным является кадр данных.Проблема в том, что это вернет список в формате, поэтому вам придется использовать unlist() -функцию для решения этой проблемы.

Весь цикл будет выглядеть примерно так:

for (i in 1:ncol(df)) {
    if (any(is.na(unique(df[i]))) == TRUE & nrow(unique(df[i])) == 2) {
        df[i] <- unlist(rep(na.omit(unique(df[i])), nrow(df)))
    }
}

Удачи!

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