Мутировать с помощью оператора apply в цепочке dplyr - PullRequest
1 голос
/ 21 января 2020

Допустим, я хочу получить количество переменных, которые больше 5 в наборе данных радужной оболочки для каждой строки :

iris %>%
  mutate(n_greater=apply(.,1,function(x) length(x[(x>5)])),
         n_less=apply(.,1,function(x) length(x[(x<5)])))  ##Is incorrectly counting factor column

iris %>% select_if(is.numeric) %>%
  mutate(n_greater=apply(.,1,function(x) length(x[(x>5)])),
         n_less=apply(.,1,function(x) length(x[(x<5)]))) ##Correct, but I need the non-numeric columns (species) in the end

iris %>%
  mutate_if(is.numeric,n_greater=apply(.,1,function(x) length(x[(x>5)]))) ##Does not work

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

n_greater=apply(iris[,-1],1,function(x) length(x[(x>5)]))
n_less=apply(iris[,-1],1,function(x) length(x[(x<5)]))
final_iris=cbind(iris,n_greater,n_less) #This is it

1 Ответ

1 голос
/ 21 января 2020

Мы можем использовать rowSums для логического вектора. В решении OP логическое условие также применяется к нечисловым c столбцам. Здесь он удаляет нечисловые столбцы c с select_if

library(dplyr)
iris %>%
     mutate(n_greater = rowSums(select_if(., is.numeric) > 5),
            n_less = (ncol(.)-1) - n_greater )

Также может быть лучше либо создать столбец с количеством числовых столбцов c, либо получить names столбцов с номерами c first

nm1 <- iris %>%
            select_if(is.numeric) %>% 
            names
iris %>%
      mutate(n_greater = rowSums(select(., nm1) > 5),
             n_less = length(nm1) - n_greater)

Или другой вариант - сделать + с reduce после создания столбцов с map и затем связать столбцы с Исходный набор данных

library(purrr)
iris %>%
    select_if(is.numeric) %>%
    transmute(n_greater = map(., `>`, 5) %>% 
                reduce(`+`), n_less = ncol(.) - n_greater) %>% 
    bind_cols(iris, .)

Или вместо map мы можем использовать mutate_all

iris %>%
   select_if(is.numeric) %>%
   mutate_all(~ . > 5) %>%
   transmute(n_greater = reduce(., `+`), 
            n_less = ncol(.) - n_greater) %>%
   bind_cols(iris, .)

На всякий случай, опция base R равна

iris$n_greater <- rowSums(iris[nm1] > 5)
iris$n_less <- length(nm1) - iris$n_greater
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...