dplyr mutate rowSums вычисления или пользовательские функции

Я пытаюсь изменить новую переменную из вида вычисления строки, скажем rowSums, как показано ниже

iris %>% 
  mutate_(sumVar = 
            iris %>% 
            select(Sepal.Length:Petal.Width) %>%
            rowSums)

в результате "sumVar" обрезается до своего первого значения (10.2):

Source: local data frame [150 x 6]
Groups: <by row>

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species sumVar
1           5.1         3.5          1.4         0.2  setosa   10.2
2           4.9         3.0          1.4         0.2  setosa   10.2
3           4.7         3.2          1.3         0.2  setosa   10.2
4           4.6         3.1          1.5         0.2  setosa   10.2
5           5.0         3.6          1.4         0.2  setosa   10.2
6           5.4         3.9          1.7         0.4  setosa   10.2
..
Warning message:
Truncating vector to length 1 

Следует ли применять rowwise? Или какой глагол использовать в такого рода вычислениях?

Изменить:

В частности, есть ли способ реализовать встроенную пользовательскую функцию с dplyr?

Мне интересно, можно ли сделать что-то вроде:

iris %>% 
  mutate(sumVar = colsum_function(Sepal.Length:Petal.Width))

person leoluyi    schedule 08.12.2014    source источник
comment
Действительно странно, что iris %>% select(Sepal.Length:Petal.Width) %>% rowSums() работает нормально, но iris %>% mutate(sumVar = iris %>% select(Sepal.Length:Petal.Width) %>% rowSums()) выдает сообщение об ошибке: плохие индексы 1 + предупреждающее сообщение.   -  person talat    schedule 08.12.2014
comment
Я пытаюсь работать над этим разными подходами, но эта ошибка очень часто появляется при использовании . (иногда я тоже делаю что-то глупое).   -  person Davide Passaretti    schedule 08.12.2014
comment
Для таких операций, как sum, которые уже имеют эффективную векторизованную альтернативу по строкам, в настоящее время правильный способ: df %>% mutate(total = rowSums(across(where(is.numeric)))) across может принимать все, что select (например, rowSums(across(Sepal.Length:Petal.Width)) также работает). См. Полный рассказ о построчном и через   -  person Fons MA    schedule 15.04.2021


Ответы (6)


Вы можете использовать функцию rowwise():

iris %>% 
  rowwise() %>% 
  mutate(sumVar = sum(c_across(Sepal.Length:Petal.Width)))

#> # A tibble: 150 x 6
#> # Rowwise: 
#>    Sepal.Length Sepal.Width Petal.Length Petal.Width Species sumVar
#>           <dbl>       <dbl>        <dbl>       <dbl> <fct>    <dbl>
#>  1          5.1         3.5          1.4         0.2 setosa    10.2
#>  2          4.9         3            1.4         0.2 setosa     9.5
#>  3          4.7         3.2          1.3         0.2 setosa     9.4
#>  4          4.6         3.1          1.5         0.2 setosa     9.4
#>  5          5           3.6          1.4         0.2 setosa    10.2
#>  6          5.4         3.9          1.7         0.4 setosa    11.4
#>  7          4.6         3.4          1.4         0.3 setosa     9.7
#>  8          5           3.4          1.5         0.2 setosa    10.1
#>  9          4.4         2.9          1.4         0.2 setosa     8.9
#> 10          4.9         3.1          1.5         0.1 setosa     9.6
#> # ... with 140 more rows

c_across() использует аккуратный синтаксис выбора, поэтому вы можете кратко выбрать множество переменных '

Наконец, если хотите, вы можете использовать %>% ungroup в конце для выхода из построчности.

person HBat    schedule 20.08.2020
comment
Для таких операций, как sum, которые уже имеют эффективную векторизованную альтернативу по строкам, в настоящее время правильный способ: df %>% mutate(total = rowSums(across(where(is.numeric)))) across может принимать все, что select (например, rowSums(across(Sepal.Length:Petal.Width)) также работает). Прокрутите виньетку построчно, чтобы найти ее, и посмотрите через - person Fons MA; 15.04.2021

Это скорее обходной путь, но его можно использовать

iris %>% mutate(sumVar = rowSums(.[1:4]))

Как написано в комментариях, вы также можете использовать select внутри mutate, чтобы получить столбцы, которые вы хотите суммировать, например

iris %>% 
  mutate(sumVar = rowSums(select(., contains("Sepal")))) %>% 
  head 

or

iris %>% 
  mutate(sumVar = select(., contains("Sepal")) %>% rowSums()) %>% 
  head
person talat    schedule 08.12.2014
comment
Какую версию dplyr вы используете? Когда я пробую ваш пример с dplyr_0.4.1, я получаю исключение: Error in is.data.frame(x) : object '.' not found. - person Jubbles; 07.05.2015
comment
Если это кому-то пригодится, то причина, по которой я получал ошибку Error in is.data.frame(x) : object '.' not found, заключалась в том, что у меня была старая версия magrittr. Когда я обновился с magrittr_1.0.1 до magrittr_1.5, все заработало нормально. - person Jubbles; 07.05.2015
comment
Это очень полезный ответ. Мне было интересно, можно ли было бы расширить его, используя match или contains dplyr вместо .[1:4]? - person Konrad; 28.02.2016
comment
@Konrad, ты мог бы сделать что-нибудь вроде iris %>% mutate(sumVar = rowSums(select(., contains("Sepal")))) %>% head или iris %>% mutate(sumVar = select(., contains("Sepal")) %>% rowSums()) %>% head - person talat; 29.02.2016
comment
@docendodiscimus Большое спасибо за полезный комментарий. - person Konrad; 29.02.2016
comment
Комментарий @docendodiscimus действительно должен быть еще одним (правом голоса) ответом. Это самое надежное решение в духе дплира. - person D. Woods; 28.04.2016
comment
Приятно, что это работает, хотя Хэдли говорит, что подобное решение работает случайно, а не по замыслу. Я бы не стал на это полагаться. Но, может быть, он сейчас поддерживается? Кто-нибудь знает? github.com/tidyverse/dplyr/issues/2050 - person Melkor.cz; 12.03.2018

Более сложный способ:

 iris %>% select(Sepal.Length:Petal.Width) %>%
mutate(sumVar = rowSums(.)) %>% left_join(iris)
person Davide Passaretti    schedule 08.12.2014
comment
Спасибо Давиде. left_join звучит неплохо, если использовать его с клавишей by; однако это не так надежно и интуитивно понятно для этого обстоятельства. - person leoluyi; 10.12.2014
comment
Я также беспокоюсь, что автоматический выбор параметров в объединении может вызвать некоторые проблемы .. столбцы могут содержать неуникальные значения в некоторых строках .. - person Melkor.cz; 12.03.2018

Добавление комментария @ docendodiscimus в качестве ответа. +1 ему!

iris %>% mutate(sumVar = rowSums(select(., contains("Sepal"))))
person psychonomics    schedule 24.08.2017

Я использую это простое решение, которое является более надежной модификацией ответа Давиде Пассаретти:

iris %>% select(Sepal.Length:Petal.Width) %>%
  transmute(sumVar = rowSums(.)) %>% bind_cols(iris, .)

(Но для этого требуется определенный порядок строк, что должно быть нормально, если, возможно, вы не работаете с удаленными наборами данных ..)

person Melkor.cz    schedule 12.03.2018

Вы также можете использовать grep вместо contains или matches, на всякий случай, если вам нужно поработать с регулярными выражениями (по моему опыту, matches не очень похож на отрицательный просмотр вперед и тому подобное).

iris %>% mutate(sumVar = rowSums(select(., grep("Sepal", names(.)))))
person llewmills    schedule 20.09.2018