Добавьте логический столбец в data.frame, указав, что все более конкретные столбцы являются NA - PullRequest
0 голосов
/ 28 января 2019

У меня есть data.frame, который имеет NA в нескольких столбцах:

df <- data.frame(a0 = 1:3, a1 = c("A","B",NA), a2 = c("a",NA,NA), 
                 a3 = rep(NA,3), stringsAsFactors = FALSE)

Я хотел бы добавить новый столбец all.na, указывающий, являются ли столбцы: c("a1","a2","a3")равны all(is.na) для каждой строки.

Это можно сделать с помощью sapply:

df$all.na <- sapply(1:nrow(df), function(x) all(is.na(df[x,c("a1","a2","a3")])))

Но я ищу что-то быстрее.

Я думал, что использование dplyr::mutate может быть хорошим решением, но:

> df %>% dplyr::mutate(all(is.na(c(a1,a2,a3))))
  a0   a1   a2 a3 all(is.na(c(a1, a2, a3)))
1  1    A    a NA                     FALSE
2  2    B <NA> NA                     FALSE
3  3 <NA> <NA> NA                     FALSE

Не дает мне желаемого результата.

Любая идея, как получить dplyr::mutate дать:

df$all.na <- c(FALSE, FALSE, TRUE)

На это?

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Вот один вариант с tidyverse, использующим pmap

library(tidyverse)
df %>%
     mutate(all.na = pmap_lgl(.[cols], ~ all(is.na(c(...))))) 
#   a0   a1   a2 a3 all.na
#1  1    A    a NA  FALSE
#2  2    B <NA> NA  FALSE
#3  3 <NA> <NA> NA   TRUE

Или другой вариант - преобразовать его в логический вектор с map и reduce обратно водин логический vector

df %>% 
    mutate(all.na = map(.[cols], is.na) %>%
         reduce(`&`))

С base R это может быть достигнуто с использованием Reduce и lapply

df$all.na <- Reduce(`&`, lapply(df[cols], is.na))

данных

cols <- c("a1","a2","a3")
0 голосов
/ 28 января 2019

Мы могли бы использовать rowwise с do

library(dplyr)

cols <- c("a1","a2","a3")

df %>%
  rowwise() %>%
  do( (.) %>% as.data.frame %>% 
  mutate(all.na = all(is.na(.[cols]))))

#     a0 a1    a2    a3    all.na
#  <int> <chr> <chr> <lgl> <lgl> 
#1     1 A     a     NA    FALSE 
#2     2 B     NA    NA    FALSE 
#3     3 NA    NA    NA    TRUE  

Или более общий подход с использованием tidyverse gather и spread

library(tidyverse)

df %>%
  gather(key, value, -a0) %>%
  group_by(a0) %>%
  mutate(all.na = all(is.na(value))) %>%
  spread(key, value)

Однако, в базе R есть лучший подход с использованием is.na и rowSums

df$all.na <- rowSums(is.na(df[cols])) == length(cols)

df
#  a0   a1   a2 a3 all.na
#1  1    A    a NA  FALSE
#2  2    B <NA> NA  FALSE
#3  3 <NA> <NA> NA   TRUE

Этого также можно добиться, используя apply построчно (MARGIN = 1)но это не поможет с улучшениями скорости.

df$all.na <- apply(df[cols], 1, function(x) all(is.na(x)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...