Подтвердить что ты не робот

Сумма в нескольких столбцах с dplyr

Мой вопрос включает в себя суммирование значений по нескольким столбцам фрейма данных и создание нового столбца, соответствующего этому суммированию, с помощью dplyr. Записи данных в столбцах двоичные (0,1). Я думаю о разумном значении функции summarise_each или mutate_each dplyr. Ниже приведен минимальный пример кадра данных:

library(dplyr)
df=data.frame(
  x1=c(1,0,0,NA,0,1,1,NA,0,1),
  x2=c(1,1,NA,1,1,0,NA,NA,0,1),
  x3=c(0,1,0,1,1,0,NA,NA,0,1),
  x4=c(1,0,NA,1,0,0,NA,0,0,1),
  x5=c(1,1,NA,1,1,1,NA,1,0,1))

> df
   x1 x2 x3 x4 x5
1   1  1  0  1  1
2   0  1  1  0  1
3   0 NA  0 NA NA
4  NA  1  1  1  1
5   0  1  1  0  1
6   1  0  0  0  1
7   1 NA NA NA NA
8  NA NA NA  0  1
9   0  0  0  0  0
10  1  1  1  1  1

Я мог бы использовать что-то вроде:

df <- df %>% mutate(sumrow= x1 + x2 + x3 + x4 + x5)

но это будет связано с записью имен каждого из столбцов. У меня есть 50 столбцов. Кроме того, имена столбцов меняются при разных итерациях цикла, в котором я хочу реализовать это поэтому я хотел бы попытаться избежать необходимости указывать имена столбцов.

Как я могу сделать это наиболее эффективно? Будем очень благодарны любой помощи.

4b9b3361

Ответ 1

Как насчет

суммировать каждый столбец

df %>%
   replace(is.na(.), 0) %>%
   summarise_all(funs(sum))

подводить итоги каждого ряда

df %>%
   replace(is.na(.), 0) %>%
   mutate(sum = rowSums(.[1:5]))

Ответ 2

Я бы использовал регулярное выражение для суммирования по переменным с определенными именами шаблонов. Например:

df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE),
                    sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE))

Таким образом, вы можете создать более одной переменной в виде суммы определенной группы переменных вашего фрейма данных.

Ответ 3

Если вы хотите суммировать только определенные столбцы, я бы использовал что-то вроде этого:

library(dplyr)
df=data.frame(
  x1=c(1,0,0,NA,0,1,1,NA,0,1),
  x2=c(1,1,NA,1,1,0,NA,NA,0,1),
  x3=c(0,1,0,1,1,0,NA,NA,0,1),
  x4=c(1,0,NA,1,0,0,NA,0,0,1),
  x5=c(1,1,NA,1,1,1,NA,1,0,1))
df %>% select(x3:x5) %>% rowSums(na.rm=TRUE) -> df$x3x5.total
head(df)

Таким образом вы можете использовать синтаксис dplyr::select.

Ответ 4

Я часто сталкиваюсь с этой проблемой, и самый простой способ сделать это - использовать функцию apply() в команде mutate.

library(tidyverse)
df=data.frame(
  x1=c(1,0,0,NA,0,1,1,NA,0,1),
  x2=c(1,1,NA,1,1,0,NA,NA,0,1),
  x3=c(0,1,0,1,1,0,NA,NA,0,1),
  x4=c(1,0,NA,1,0,0,NA,0,0,1),
  x5=c(1,1,NA,1,1,1,NA,1,0,1))

df %>%
  mutate(sum = select(., x1:x5) %>% apply(1, sum, na.rm=TRUE))

Здесь вы можете использовать все, что вы хотите, чтобы выбрать столбцы, используя стандартные приемы dplyr (например, starts_with() или contains()). Выполнив всю работу в рамках одной команды mutate, это действие может произойти в любом dplyr потока обработки dplyr. Наконец, используя функцию apply(), вы можете гибко использовать любую необходимую вам сводку, включая собственную функцию суммирования.

В качестве альтернативы, если идея использования функции, отличной от tidyverse, непривлекательна, вы можете собрать столбцы, суммировать их и, наконец, присоединить результат обратно к исходному фрейму данных.

df <- df %>% mutate( id = 1:n() )   # Need some ID column for this to work

df <- df %>%
  group_by(id) %>%
  gather('Key', 'value', starts_with('x')) %>%
  summarise( Key.Sum = sum(value) ) %>%
  left_join( df, . )

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

Ответ 5

Использование purrr reduce() из purrr немного быстрее, чем rowSums и определенно быстрее, чем apply, так как вы избегаете итерации по всем строкам и просто используете векторизованные операции:

library(purrr)
library(dplyr)
iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), '+'))

Смотрите это для времени