mutate_each / summarise_each в dplyr: как выбрать определенные столбцы и дать новые имена измененным столбцам?

Я немного смущен dplyr глагол mutate_each.

Это довольно просто использовать основные mutate преобразовать столбец данных, скажем, в z-показатели, и создать новый столбец в вашем data.frame (здесь с именем z_score_data):

newDF <- DF %>%
  select(one_column) %>%
  mutate(z_score_data = one_column - (mean(one_column) / sd(one_column))

Однако, поскольку у меня есть много столбцов данных, которые я хотел бы преобразовать, похоже, мне, вероятно, следует использовать mutate_each глагол.

newDF <- DF %>%
     mutate_each(funs(scale))

Все идет нормально. Но пока я не смог понять:

  1. Как я могу дать этим новым столбцам соответствующие имена, как я могу в mutate?
  2. Как я могу выбрать определенные столбцы, которые я хочу изменить, как я сделал с select в первом случае?

Спасибо за вашу помощь.

2 ответа

Решение

Обновление для dplyr >= 0.4.3.9000

В версии разработки dplyr 0.4.3.9000 (на момент написания), именование внутри mutate_each а также summarise_each был упрощен, как отмечено в новостях:

Поведение именования summarise_each() а также mutate_each() был изменен, так что вы можете принудительно включить как функцию, так и имя переменной: summarise_each(mtcars, funs(mean = mean), everything())

Это особенно важно, если вы хотите применить только 1 функцию внутри mutate_each / summarise_each и вы хотите дать этим столбцам новые имена.

Чтобы показать разницу, вот вывод dplyr 0.4.3.9000 с использованием новой функциональности именования, в отличие от опции a.2 ниже:

library(dplyr) # >= 0.4.3.9000
iris %>% mutate_each(funs(mysum = sum(.)), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_mysum Sepal.Width_mysum
#1          5.1         3.5          1.4         0.2  setosa              876.5             458.6
#2          4.9         3.0          1.4         0.2  setosa              876.5             458.6
#3          4.7         3.2          1.3         0.2  setosa              876.5             458.6
#4          4.6         3.1          1.5         0.2  setosa              876.5             458.6
#5          5.0         3.6          1.4         0.2  setosa              876.5             458.6
#6          5.4         3.9          1.7         0.4  setosa              876.5             458.6
#  Petal.Length_mysum Petal.Width_mysum
#1              563.7             179.9
#2              563.7             179.9
#3              563.7             179.9
#4              563.7             179.9
#5              563.7             179.9
#6              563.7             179.9

Если вы не предоставляете новые имена и только одну функцию, dplyr изменит существующие столбцы (как это было в предыдущих версиях):

iris %>% mutate_each(funs(sum), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1        876.5       458.6        563.7       179.9  setosa
#2        876.5       458.6        563.7       179.9  setosa
#3        876.5       458.6        563.7       179.9  setosa
#4        876.5       458.6        563.7       179.9  setosa
#5        876.5       458.6        563.7       179.9  setosa
#6        876.5       458.6        563.7       179.9  setosa

Я предполагаю, что эта новая функциональность будет доступна через CRAN в следующей версии 0.4.4.


dplyr verions <= 0.4.3:

Как я могу дать этим новым столбцам соответствующие имена, как я могу в mutate?

а) 1 функция применяется в mutate_each / summarise_each

Если вы применяете только 1 функцию внутри mutate_each или же summarise_each существующие столбцы будут преобразованы, а имена будут сохранены в прежнем виде, если только вы не укажете именованный вектор для mutate_each_ / summarise_each_ (см. вариант а.4)

Вот некоторые примеры:

a.1 только 1 функция -> сохранит существующие имена

iris %>% mutate_each(funs(sum), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          876         459          564         180  setosa
#2          876         459          564         180  setosa
#3          876         459          564         180  setosa
#4          876         459          564         180  setosa
#5          876         459          564         180  setosa
#6          876         459          564         180  setosa

а.2 также, если вы укажете новое расширение имени столбца:

iris %>% mutate_each(funs(mysum = sum(.)), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          876         459          564         180  setosa
#2          876         459          564         180  setosa
#3          876         459          564         180  setosa
#4          876         459          564         180  setosa
#5          876         459          564         180  setosa
#6          876         459          564         180  setosa

а.3 Вручную указать новое имя для каждого столбца (но только для нескольких столбцов):

iris %>% mutate_each(funs(sum), SLsum = Sepal.Length,SWsum = Sepal.Width,  -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species SLsum SWsum
#1          5.1         3.5          1.4         0.2  setosa   876   459
#2          4.9         3.0          1.4         0.2  setosa   876   459
#3          4.7         3.2          1.3         0.2  setosa   876   459
#4          4.6         3.1          1.5         0.2  setosa   876   459
#5          5.0         3.6          1.4         0.2  setosa   876   459
#6          5.4         3.9          1.7         0.4  setosa   876   459

а.4 Используйте именованный вектор для создания дополнительных столбцов с новыми именами:

случай 1: сохранить оригинальные столбцы

В отличие от опций a.1, a.2 и a.3, dplyr сохранит существующие столбцы без изменений и создаст новые столбцы в этом подходе. Имена новых столбцов равны именам именованного вектора, который вы создали заранее (vars в этом случае).

vars <- names(iris)[1:2]  # choose which columns should be mutated
vars <- setNames(vars, paste0(vars, "_sum")) # create new column names
iris %>% mutate_each_(funs(sum), vars) %>% head 
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum
#1          5.1         3.5          1.4         0.2  setosa            876.5           458.6
#2          4.9         3.0          1.4         0.2  setosa            876.5           458.6
#3          4.7         3.2          1.3         0.2  setosa            876.5           458.6
#4          4.6         3.1          1.5         0.2  setosa            876.5           458.6
#5          5.0         3.6          1.4         0.2  setosa            876.5           458.6
#6          5.4         3.9          1.7         0.4  setosa            876.5           458.6

случай 2: удалить оригинальные столбцы

Как видите, этот подход сохраняет существующие столбцы без изменений и добавляет новые столбцы с указанными именами. Если вы не хотите сохранять исходные столбцы, а только недавно созданные столбцы (и другие столбцы), вы можете просто добавить select заявление потом:

iris %>% mutate_each_(funs(sum), vars) %>% select(-one_of(vars)) %>% head
#  Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum
#1          1.4         0.2  setosa            876.5           458.6
#2          1.4         0.2  setosa            876.5           458.6
#3          1.3         0.2  setosa            876.5           458.6
#4          1.5         0.2  setosa            876.5           458.6
#5          1.4         0.2  setosa            876.5           458.6
#6          1.7         0.4  setosa            876.5           458.6

б) более 1 функции применяется в mutate_each / summarise_each

б.1 Позвольте dplyr выяснить новые имена

Если вы применили более 1 функции, вы можете позволить dplyr самостоятельно определять имена (и он сохранит существующие столбцы):

iris %>% mutate_each(funs(sum, mean), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum Petal.Length_sum
#1          5.1         3.5          1.4         0.2  setosa              876             459              564
#2          4.9         3.0          1.4         0.2  setosa              876             459              564
#3          4.7         3.2          1.3         0.2  setosa              876             459              564
#4          4.6         3.1          1.5         0.2  setosa              876             459              564
#5          5.0         3.6          1.4         0.2  setosa              876             459              564
#6          5.4         3.9          1.7         0.4  setosa              876             459              564
#  Petal.Width_sum Sepal.Length_mean Sepal.Width_mean Petal.Length_mean Petal.Width_mean
#1             180              5.84             3.06              3.76              1.2
#2             180              5.84             3.06              3.76              1.2
#3             180              5.84             3.06              3.76              1.2
#4             180              5.84             3.06              3.76              1.2
#5             180              5.84             3.06              3.76              1.2
#6             180              5.84             3.06              3.76              1.2

б.2 Вручную указать новые имена столбцов

Другой вариант, если используется более 1 функции, это указать расширение имени столбца самостоятельно:

iris %>% mutate_each(funs(MySum = sum(.), MyMean = mean(.)), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_MySum Sepal.Width_MySum Petal.Length_MySum
#1          5.1         3.5          1.4         0.2  setosa                876               459                564
#2          4.9         3.0          1.4         0.2  setosa                876               459                564
#3          4.7         3.2          1.3         0.2  setosa                876               459                564
#4          4.6         3.1          1.5         0.2  setosa                876               459                564
#5          5.0         3.6          1.4         0.2  setosa                876               459                564
#6          5.4         3.9          1.7         0.4  setosa                876               459                564
#  Petal.Width_MySum Sepal.Length_MyMean Sepal.Width_MyMean Petal.Length_MyMean Petal.Width_MyMean
#1               180                5.84               3.06                3.76                1.2
#2               180                5.84               3.06                3.76                1.2
#3               180                5.84               3.06                3.76                1.2
#4               180                5.84               3.06                3.76                1.2
#5               180                5.84               3.06                3.76                1.2
#6               180                5.84               3.06                3.76                1.2

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

Вы можете сделать это, ссылаясь на столбцы, которые должны быть видоизменены (или опущены), указав их имена как здесь (mutate Sepal.Length, но не Species):

iris %>% mutate_each(funs(sum), Sepal.Length, -Species) %>% head()

Кроме того, вы можете использовать специальные функции для выбора столбцов, которые должны быть изменены, все столбцы, которые начинаются с определенного слова или содержат его и т. Д., Используя, например:

iris %>% mutate_each(funs(sum), contains("Sepal"),  -Species) %>% head()

Для получения дополнительной информации об этих функциях см. ?mutate_each а также ?select,

Изменить 1 после комментария:

Если вы хотите использовать стандартную оценку, dplyr предоставляет SE-версии большинства функций, заканчивающиеся дополнительным "_". Так что в этом случае вы бы использовали:

x <- c("Sepal.Width", "Sepal.Length") # vector of column names 
iris %>% mutate_each_(funs(sum), x) %>% head()

Обратите внимание на mutate_each_ Я использовал здесь.


Редактировать 2: обновлено с опцией а.4

mutate_each будет устаревшим, рассмотрите возможность использования mutate_at, От dplyr_0.5.0 документация:

В будущем mutate_each () и summarise_each () будут устаревшими в пользу более интересного семейства функций: mutate_all (), mutate_at (), mutate_if (), summarise_all (), summarise_at () и summarise_if ().

Применить функцию ко всем переменным, кроме Species:

Предупреждение: параметр.cols устарел, см. Примечание внизу!

iris %>% mutate_at(.cols=vars(-Species), .funs=funs(mysum = sum(.))) %>% head()

 Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_mysum Sepal.Width_mysum
1          5.1         3.5          1.4         0.2  setosa              876.5             458.6
2          4.9         3.0          1.4         0.2  setosa              876.5             458.6
3          4.7         3.2          1.3         0.2  setosa              876.5             458.6
4          4.6         3.1          1.5         0.2  setosa              876.5             458.6
5          5.0         3.6          1.4         0.2  setosa              876.5             458.6
6          5.4         3.9          1.7         0.4  setosa              876.5             458.6
  Petal.Length_mysum Petal.Width_mysum
1              563.7             179.9
2              563.7             179.9
3              563.7             179.9
4              563.7             179.9
5              563.7             179.9
6              563.7             179.9

Применить функцию к подмножеству переменных

vars_to_process=c("Petal.Length","Petal.Width")
iris %>% mutate_at(.cols=vars_to_process, .funs=funs(mysum = sum(.))) %>% head()

 Sepal.Length Sepal.Width Petal.Length Petal.Width Species Petal.Length_mysum Petal.Width_mysum
1          5.1         3.5          1.4         0.2  setosa              563.7             179.9
2          4.9         3.0          1.4         0.2  setosa              563.7             179.9
3          4.7         3.2          1.3         0.2  setosa              563.7             179.9
4          4.6         3.1          1.5         0.2  setosa              563.7             179.9
5          5.0         3.6          1.4         0.2  setosa              563.7             179.9
6          5.4         3.9          1.7         0.4  setosa              563.7             179.9

Обновить! для версии dplyr 0.7.1 (2017-08-08)

Если вы видите сообщение:

.cols был переименован и устарел, пожалуйста, используйте .vars

затем изменить .cols от .vars,

iris %>% mutate_at(.vars=vars(-Species), .funs=funs(mysum = sum(.))) %>% head()

Другой пример:

iris %>% mutate_at(.vars=vars(Sepal.Width), .funs=funs(mysum = sum(.))) %>% head()

Эквивалентно:

iris %>% mutate_at(.vars=vars("Sepal.Width"), .funs=funs(mysum = sum(.))) %>% head()

Кроме того, в этой версии mutate_each устарела:

mutate_each() устарела. использование mutate_all(), mutate_at() или же mutate_if() вместо. На карту funs по выбору переменных, используйте mutate_at()

Другие вопросы по тегам