dplyr: условный выбор столбца с использованием select_if () - PullRequest
0 голосов
/ 11 января 2019

Продолжение предыдущего вопроса ...

Как выбрать все столбцы на основе типа, за исключением одного столбца на основе вспомогательной функции выбора?

select_if(iris, is.numeric, vars(-contains("Width")))
Error: No tidyselect variables were registered

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

iris %>% 
  group_by(Species) %>% 
  nest %>% 
  mutate(data = map(data, ~ .x %>% select_if(is.numeric) %>% mutate(count = sum(rowSums(.))))) %>%
  mutate(data = map(data, ~ .x %>% select_if(is.numeric) %>% 
                      mutate_all(funs((. / count) * 100 )))) %>%

  unnest 

Ответы [ 3 ]

0 голосов
/ 11 января 2019
select_if(iris[, !colnames(iris) %in% ("Sepal.Width")], is.numeric)
    Sepal.Length Petal.Length Petal.Width
1            5.1          1.4         0.2
2            4.9          1.4         0.2
3            4.7          1.3         0.2
4            4.6          1.5         0.2
5            5.0          1.4         0.2
0 голосов
/ 11 января 2019

Самый простой и понятный способ сделать это - соединить вместе 2 select функции:

iris %>%
    select_if(is.numeric) %>%       # Select all numeric columns
    select(-contains('Width')) %>%  # Then drop 'Width' column(s)
    head

  Sepal.Length Petal.Length
1          5.1          1.4
2          4.9          1.4
3          4.7          1.3
4          4.6          1.5
5          5.0          1.4
6          5.4          1.7

Это работает даже внутри map функции:

iris %>% 
    group_by(Species) %>% 
    nest %>% 
    mutate(data = map(data, ~ .x %>%
                          select_if(is.numeric) %>%
                          select(-contains('Width')) %>%
                          mutate(count = sum(rowSums(.))))) %>%
    mutate(data = map(data, ~ .x %>%
                          select_if(is.numeric) %>%
                          select(-contains('Width')) %>% 
                          mutate_all(funs((. / count) * 100 )))) %>%

    unnest 

# A tibble: 150 x 4
   Species Sepal.Length Petal.Length count
   <fct>          <dbl>        <dbl> <dbl>
 1 setosa          1.58        0.433   100
 2 setosa          1.52        0.433   100
 3 setosa          1.45        0.402   100
 4 setosa          1.42        0.464   100
 5 setosa          1.55        0.433   100
 6 setosa          1.67        0.526   100
 7 setosa          1.42        0.433   100
 8 setosa          1.55        0.464   100
 9 setosa          1.36        0.433   100
10 setosa          1.52        0.464   100
# ... with 140 more rows
0 голосов
/ 11 января 2019

Вы можете сделать:

select_if(iris %>% select_at(vars(-contains("Width"))), is.numeric)

    Sepal.Length Petal.Length
1            5.1          1.4
2            4.9          1.4
3            4.7          1.3
4            4.6          1.5
5            5.0          1.4

Ответ на обновленный вопрос:

df1 <- iris %>% 
 group_by(Species) %>% 
 nest() %>% 
 mutate(data = map(data, function(x) select_if(x %>% select_at(vars(-contains("Width"))), is.numeric) %>% mutate(count = sum(rowSums(.))))) %>%
 mutate(data = map(data, function(x) select_if(x %>% select_at(vars(-contains("Width"))), is.numeric) %>% mutate_all(funs((. / count) * 100 )))) %>%
 unnest() 

df2 <- iris %>% 
 group_by(Species) %>% 
 nest() %>% 
 mutate(data = map(data, ~ .x %>% select_if(is.numeric) %>% select_at(vars(-contains("Width"))) %>% mutate(count = sum(rowSums(.))))) %>%
 mutate(data = map(data, ~ .x %>% select_if(is.numeric) %>% select_at(vars(-contains("Width"))) %>% mutate_all(funs((. / count) * 100 )))) %>%
 unnest() 

identical(df1, df2)
[1] TRUE

Как видно из кода для df1, вы все равно можете выполнить вложенный select(), который возвращает те же результаты, что и две команды select() по отдельности.

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