Сумма строк зависит от имени столбца

Мой data.frage выглядит так:

   VAR1 VAR2 AUS1 AUS2 AUS3 AUS4 ... AUS56 VAR3 VAR4
   A    D    23   234  34   856  ... 99    0    FCK
   B    D    55   76   55   36   ... 6456  0    XYC

Я бы хотел, чтобы R добавил новую переменную AUS, которая показывает суммы строк переменных от AUS1 до AUS56, предпочтительно с помощью dplyr. AUS1 до AUS56 можно удалить.


person Laubsauger    schedule 20.04.2017    source источник
comment
Рассмотрите возможность использования аккуратного «длинного» формата для данных, где AUS — это один столбец, а число, следующее за ним, — это другой столбец. Тогда вы легко совместите самые традиционные глаголы dplyr, такие как group_by и summarise.   -  person liborm    schedule 20.04.2017


Ответы (3)


Вы можете попробовать использовать rowSums в сочетании с grep:

df %>% mutate(AUS_sum = rowSums(.[grep("AUS", names(.))]))
person mtoto    schedule 20.04.2017
comment
Интересно, можно ли это сделать, используя dplyr::select_if? вместо grep. - person zx8754; 20.04.2017
comment
Это работает. Но есть ли способ одновременно удалить старые переменные? Transmute удалил ВСЕ оставшиеся переменные, но я просто хочу избавиться от тех, которые использовались для расчета. - person Laubsauger; 20.04.2017

Вот еще один вариант с использованием синтаксиса tidyverse

library(tidyverse)
df1 %>% 
     select(matches("AUS")) %>% 
     reduce(`+`) %>%
     mutate(df1, AUS_sum = .)
#   VAR1 VAR2 AUS1 AUS2 AUS3 AUS4 AUS56 VAR3 VAR4 AUS_sum
#1    A    D   23  234   34  856    99    0  FCK    1246
#2    B    D   55   76   55   36  6456    0  XYC    6678

В версии для разработки dplyr (скоро будет выпущена 0.6.0) мы можем создать функцию с quosures и сделать ее более динамичной. Здесь enquo выполняет те же функции, что и substitute из base R, беря входные аргументы и преобразовывая их в quosure, с quo_name мы преобразуем его в строку, где matches принимает строковый аргумент. Имя левой стороны также может быть создано как строка («newN»), и внутри mutate/summarise/group_by мы раскавычиваем (!! или UQ) для оценки строки.

fSum <- function(dat, pat){
  pat <- quo_name(enquo(pat))
  newN <- paste0(pat, "_sum")
  newSum <- dat %>%
            select(matches(pat)) %>%
            reduce(`+`)
  dat %>%
      mutate(!!newN :=  newSum)
}

fSum(df1, AUS)
#    VAR1 VAR2 AUS1 AUS2 AUS3 AUS4 AUS56 VAR3 VAR4 AUS_sum
#1    A    D   23  234   34  856    99    0  FCK    1246
#2    B    D   55   76   55   36  6456    0  XYC    6678

Основываясь на комментарии OP к другому сообщению об удалении столбцов, которые использовались для sum, мы можем изменить функцию

fSumN <- function(dat, pat){
  pat <- quo_name(enquo(pat))
  newN <- paste0(pat, "_sum")
  newSum <- dat %>%
            select(matches(pat)) %>%
            reduce(`+`)
  dat %>%
       select(-matches(pat)) %>%
       mutate(!!newN :=  newSum)
}

fSumN(df1, AUS)
#     VAR1 VAR2 VAR3 VAR4 AUS_sum
#1    A    D    0  FCK    1246
#2    B    D    0  XYC    6678

данные

df1 <- structure(list(VAR1 = c("A", "B"), VAR2 = c("D", "D"), AUS1 = c(23L, 
55L), AUS2 = c(234L, 76L), AUS3 = c(34L, 55L), AUS4 = c(856L, 
36L), AUS56 = c(99L, 6456L), VAR3 = c(0L, 0L), VAR4 = c("FCK", 
"XYC")), .Names = c("VAR1", "VAR2", "AUS1", "AUS2", "AUS3", "AUS4", 
 "AUS56", "VAR3", "VAR4"), class = "data.frame", row.names = c(NA, 
-2L))
person akrun    schedule 20.04.2017
comment
Хороший. Также вы можете просто сделать mutate(sum1 = rowSums(.)) после select - person Sotos; 20.04.2017
comment
Первый выдает мне сообщение об ошибке: Error in function_list[[i]](value) : could not find function "reduce". Второй, честно говоря, выглядит довольно сложно для такой простой операции. - person Laubsauger; 20.04.2017
comment
@Laubsauger Если вы загрузили tidyverse, должен загрузиться library(purrr). Функция из этого пакета. Второй использует нестандартную оценку, что делает его более простым по сравнению с более ранними версиями с interp и тому подобным. Преимущество функции заключается в многократном использовании с несколькими шаблонами. - person akrun; 20.04.2017
comment
@Laubsauger Также обновлена ​​​​новая функция для get rid of those that have been used to make the calculation - person akrun; 20.04.2017
comment
Большой. Большое спасибо. Но теперь, когда я уже являюсь опцией функции, можно ли все это сделать и в цикле? Потому что у меня на самом деле есть множество групп переменных, не только AUT. Итак, могу ли я сделать следующее в одной команде: wiot <- wiot %>% mutate(AUS = rowSums(.[grep("AUS", names(.))])) %>% mutate(AUT = rowSums(.[grep("AUT", names(.))])) %>% mutate(BEL = rowSums(.[grep("BEL", names(.))])) %>% mutate(BGR = rowSums(.[grep("BGR", names(.))])) - person Laubsauger; 20.04.2017
comment
@Laubsauger Это возможно, но, пожалуйста, проверьте свой вопрос. Эти новые критерии не были упомянуты в вашем посте - person akrun; 20.04.2017
comment
если у вас есть новый вопрос, вы можете опубликовать его вместо обновления текущего с новыми требованиями. @Laubsauger - person mtoto; 20.04.2017
comment
@mtoto, ты абсолютно прав. Я разместил дополнительный вопрос: stackoverflow.com/questions/43518958/ - person Laubsauger; 20.04.2017

В базе R:

df$AUS <- rowSums(df[,grep('AUS', names(df))])
person 989    schedule 20.04.2017