#r
Вопрос:
Я пытаюсь изменить новую переменную из расчета строки, скажем 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))
Комментарии:
1. Действительно странно, что
iris %>% select(Sepal.Length:Petal.Width) %>% rowSums()
это работает нормально, ноiris %>% mutate(sumVar = iris %>% select(Sepal.Length:Petal.Width) %>% rowSums())
выдает сообщение «Ошибка: плохие индексы 1» предупреждение.2. Я пытаюсь работать над этим с разными подходами, но эта ошибка появляется очень часто
.
(иногда я тоже делаю что-то глупое).3.Для подобных операций
sum
, у которых уже есть эффективная векторизованная альтернатива по строкам, в настоящее время правильный способ:df %>% mutate(total = rowSums(across(where(is.numeric))))
across
может взять все, чтоselect
может (напримерrowSums(across(Sepal.Length:Petal.Width))
, также работает). Смотрите полный рассказ о том, как по рядам и поперек
Ответ №1:
Это скорее обходной путь, но его можно использовать
iris %>% mutate(sumVar = rowSums(.[1:4]))
Как написано в комментариях, вы также можете использовать select
внутри mutate, чтобы получить столбцы, которые вы хотите подвести итог, например
iris %>%
mutate(sumVar = rowSums(select(., contains("Sepal")))) %>%
head
или
iris %>%
mutate(sumVar = select(., contains("Sepal")) %>% rowSums()) %>%
head
Комментарии:
2. Если это кому-то полезно, причина, по которой я получал ошибку
Error in is.data.frame(x) : object '.' not found
, заключалась в том, что у меня была старая версияmagrittr
. Когда я обновился сmagrittr_1.0.1
доmagrittr_1.5
, все работало нормально.3. @Конрад, ты мог бы сделать что-то вроде
iris %>% mutate(sumVar = rowSums(select(., contains("Sepal")))) %>% head
илиiris %>% mutate(sumVar = select(., contains("Sepal")) %>% rowSums()) %>% head
4. Комментарий @docendodiscimus действительно должен быть другим (с правом голоса) ответом. Это самое надежное решение в стиле dplyr.
5. Приятно, что это работает, хотя Хэдли говорит, что подобное решение «работает по совпадению, а не по замыслу. Я бы не стал на это полагаться». Но, может быть, сейчас это поддерживается? Кто-нибудь знает? github.com/tidyverse/dplyr/issues/2050
Ответ №2:
Вы можете использовать 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
в конце для выхода из rowwise.
Комментарии:
1.Для подобных операций
sum
, у которых уже есть эффективная векторизованная альтернатива по строкам, в настоящее время правильный способ:df %>% mutate(total = rowSums(across(where(is.numeric))))
across
может взять все, чтоselect
может (напримерrowSums(across(Sepal.Length:Petal.Width))
, также работает). Прокрутите виньетку по строкам вниз, чтобы найти это и взглянуть на
Ответ №3:
Более сложным способом было бы:
iris %>% select(Sepal.Length:Petal.Width) %>%
mutate(sumVar = rowSums(.)) %>% left_join(iris)
Комментарии:
1. Спасибо, Давид.
left_join
звучит неплохо, если использовать его сby
ключом; однако для этого обстоятельства он не настолько надежен и интуитивно понятен2. Я также беспокоюсь, что автоматический выбор параметра «по» в соединении может вызвать некоторые проблемы.. в некоторых строках столбцы могут содержать неуникальные значения ..
Ответ №4:
Добавление комментария @docendodiscimus в качестве ответа. 1 к нему!
iris %>% mutate(sumVar = rowSums(select(., contains("Sepal"))))
Ответ №5:
Я использую это простое решение, которое является более надежной модификацией ответа Давиде Пассаретти:
iris %>% select(Sepal.Length:Petal.Width) %>%
transmute(sumVar = rowSums(.)) %>% bind_cols(iris, .)
(Но для этого требуется определенный порядок строк, что должно быть нормально, если вы, возможно, не работаете с удаленными наборами данных..)
Комментарии:
1. Привет, не могли бы вы, пожалуйста, объяснить мне значение точки между круглыми скобками?
rowSums(.)
Ответ №6:
Вы также можете использовать grep вместо contains
или matches
, на всякий случай, если вам нужно пофантазировать с регулярными выражениями ( matches
по моему опыту, это не очень похоже на негативные взгляды и тому подобное).
iris %>% mutate(sumVar = rowSums(select(., grep("Sepal", names(.)))))