Мой вопрос включает суммирование значений по нескольким столбцам фрейма данных и создание нового столбца, соответствующего этому суммированию, используя 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 колонок. Кроме того, имена столбцов меняются на разных итерациях цикла, в котором я хочу реализовать эту операцию, поэтому я хотел бы попытаться избежать необходимости указывать какие-либо имена столбцов.
Как я могу сделать это наиболее эффективно? Будем очень благодарны любой помощи.
dplyr
? Почему не просто простой наdf$sumrow <- rowSums(df, na.rm = TRUE)
базе R? Илиdf$sumrow <- Reduce(`+`, df)
если вы хотите в точности повторить то, что вы сделалиdplyr
.dplyr
как вdf %>% mutate(sumrow = Reduce(`+`, .))
илиdf %>% mutate(sumrow = rowSums(.))
dplyr
версии, и все будет работать.Ответы:
Как насчет
суммировать каждый столбец
df %>% replace(is.na(.), 0) %>% summarise_all(funs(sum))
суммировать каждую строку
df %>% replace(is.na(.), 0) %>% mutate(sum = rowSums(.[1:5]))
источник
summarise_each
суммирует по каждому столбцу, в то время как то, что требуется, является суммой по каждой строке(.[1:5])
часть, но, к сожалению, я не знаком с синтаксисом и не знаю, как искать по нему помощь. Пытался,mutate(sum = rowSums(is.numeric(.)))
но не получилось.df %>% replace(is.na(.), 0) %>% select_if(is.numeric) %>% summarise_each(funs(sum))
попробовать?summarise_all
вместоsummarise_each
устаревшего.mutate(sum = rowSums(.[,-1]))
может пригодиться, если вы не знаете, сколько столбцов вам нужно обработать.Если вы хотите суммировать только определенные столбцы, я бы использовал что-то вроде этого:
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
синтаксис.источник
Я бы использовал сопоставление регулярных выражений для суммирования переменных с определенными именами шаблонов. Например:
df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE), sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE))
Таким образом, вы можете создать более одной переменной как сумму определенной группы переменных вашего фрейма данных.
источник
-
знак:rowSums(.[-grep("x[3-5]", names(.))], na.rm = TRUE)
Я часто сталкиваюсь с этой проблемой, и самый простой способ сделать это - использовать
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
потоке шагов обработки. Наконец, с помощью этой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
поток шагов по очистке данных.источник
apply
когда этоrowSums
было предназначено.rowSums
работает очень хорошоrowMeans
, но я всегда чувствовал себя немного странно, задаваясь вопросом: «Что, если вещь, которую мне нужно вычислить, не является суммой или средним значением?» Однако в 99% случаев мне приходится делать что-то подобное, это либо сумма, либо среднее значение, поэтому, возможно, дополнительная гибкость при использовании общейapply
функции не оправдана.Использование
reduce()
frompurrr
немного быстрееrowSums
и определенно быстрее, чемapply
, поскольку вы избегаете итерации по всем строкам и просто пользуетесь преимуществами векторизованных операций:library(purrr) library(dplyr) iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), `+`))
Смотрите это тайминги
источник
na.rm = TRUE
rowSums(select(., matches("myregex")) , na.rm = TRUE))
так, потому что это то, что мне нужно с точки зрения игнорирования НП. Итак, если числаsum(NA, 5)
то результат равен 5. Но вы сказали, что сокращение лучше, чемrowSums
поэтому мне было интересно, есть ли способ использовать его в этой ситуации?rowSums
версия, вероятно, является лучшей. Главный недостаток в том, что доступны толькоrowSums
иrowMeans
(это немного медленнее, чем сокращение, но не намного). Если вам нужно выполнить другую операцию (не сумму), тоreduce
версия, вероятно, единственный вариант. Просто избегайте использованияapply
в этом случае.В более новых версиях
dplyr
вы можете использоватьrowwise()
вместе сc_across
для выполнения построчной агрегации для функций, не имеющих конкретных построчных вариантов, но если построчный вариант существует, он должен быть быстрее.Поскольку
rowwise()
это просто особая форма группировки и меняет способ работы глаголов, вы, вероятно, захотите передать ее по конвейеруungroup()
после выполнения построчной операции.Чтобы выбрать диапазон строк:
df %>% dplyr::rowwise() %>% dplyr::mutate(sumrange = sum(dplyr::c_across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Чтобы выбрать строки по типу:
df %>% dplyr::rowwise() %>% dplyr::mutate(sumnumeric = sum(c_across(where(is.numeric)), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
В вашем конкретном случае существует построчный вариант, поэтому вы можете сделать следующее (обратите внимание на использование
across
вместо):df %>% dplyr::mutate(sumrow = rowSums(dplyr::across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Для получения дополнительной информации см. Страницу строкам .
источник