Как использовать функции purrr внутри dplyr select_if - PullRequest
1 голос
/ 01 июня 2019

Я пытаюсь найти самую короткую комбинацию dplyr-purr.

Можно ли сократить следующий оператор, который объединяет select_if() и map_df()?

training.set.imputed %>% 
  select_if(~sum(is.na(.))>0) %>% map_df(~sum(is.na(.)))

Я пробовал это:

training.set.imputed %>% 
  select_if(~sum(is.na(.))>0, .funs = ~sum(is.na(.)))

который выдает эту ошибку:

Ошибка: nm должен быть NULL или символьный вектор такой же длины, как x

Что это значит? Любые идеи, как сформировать .funs термин?

Ответы [ 2 ]

3 голосов
/ 01 июня 2019

Для аргумента .funs в select_if требуется функция переименования, а не мутирующая функция, поэтому вы можете сделать что-то подобное с этим, но вы не можете изменить значения переменной:

tibble(blah = 1:2, bleh = 3:4, bluh = c(NA, NA)) %>% 
    select_if(~ sum(is.na(.x)) > 0, .funs = toupper)

#### OUTPUT ####

# A tibble: 2 x 1
  BLUH 
  <lgl>
1 NA   
2 NA   

Если вы настаиваете на использовании комбинации purrr и dplyr, то это, вероятно, ваша лучшая ставка (Edit: я только что заметил, что G. Grothendieck дал этот ответ, но я все равно включу его ради полнота) :.

df %>% 
    map_df(~ sum(is.na(.))) %>% 
    select_if(~ . > 0)

#### OUTPUT ####

# A tibble: 1 x 2
      b     d
  <int> <int>
1     4     1

Однако, вы можете немного упростить это, просто используя dplyr summarize_if:

df %>% 
    summarise_if(anyNA, ~ sum(is.na(.)))

#### OUTPUT ####

# A tibble: 1 x 2
      b     d
  <int> <int>
1     4     1

Поскольку вы действительно сразу после сумм столбцов, база R может предложить наиболее краткий вариант:

colSums(is.na(df)) %>% 
    .[. > 0]

#### OUTPUT ####

b d 
4 1

Данные

structure(list(a = c(2L, 2L, 5L, 10L, 10L, 18L, 18L, 19L, 11L, 
14L, 12L, 10L, 4L, 16L, 5L, 5L, 11L, 2L, 14L, 7L), b = c(10L, 
20L, 16L, NA, 6L, 1L, 11L, 12L, 12L, 12L, 8L, NA, NA, 8L, 11L, 
19L, 8L, 9L, NA, 19L), c = c(11L, 11L, 20L, 8L, 15L, 4L, 17L, 
4L, 4L, 11L, 20L, 11L, 6L, 12L, 17L, 7L, 14L, 18L, 15L, 19L), 
    d = c(19L, 16L, 17L, 14L, 8L, 19L, 7L, 6L, 6L, 13L, 7L, 19L, 
    11L, 17L, NA, 10L, 3L, 3L, 3L, 2L), e = c(12L, 17L, 14L, 
    5L, 8L, 19L, 8L, 3L, 17L, 1L, 2L, 6L, 5L, 17L, 14L, 5L, 8L, 
    2L, 8L, 2L)), row.names = c(NA, -20L), class = c("tbl_df", 
"tbl", "data.frame"))
0 голосов
/ 01 июня 2019

Я предполагаю, что вы хотите, чтобы количество NA в каждом столбце содержало только столбцы, которые имеют по крайней мере 1 NA.

!) Это позволяет избежать дублирования кода и не выдает ошибку. Сначала рассчитайте количество NA в каждом столбце, а затем выберите столбцы, которые больше 0.

# test input - BOD comes with R
BOD[1,2] <- NA

BOD %>%
  map_df(~ sum(is.na(.))) %>%
  select_if(~ . > 0)

дает:

# A tibble: 1 x 1
  demand
   <int>
1      1

2) Сначала выбираются столбцы с хотя бы одним NA, а затем определяется количество NA в этих столбцах, дающее тот же результат:

BOD %>%
  select_if(anyNA) %>%
  map_df(~ sum(is.na(.)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...