R сумма строк для разных групп столбцов, которые начинаются с аналогичной строки

Я совершенно новичок в R, и это первый раз, когда я осмеливаюсь задать вопрос здесь.

Я работаю с набором данных с масштабами likert, и я хочу, чтобы сумма строк по другой группе столбцов, которые разделяют первые строки в их имени.

df <- as.data.frame(rbind(rep(sample(1:5),4),rep(sample(1:5),4)))

var.names <- c("emp_1","emp_2","emp_3","emp_4","sat_1","sat_2"
           ,"sat_3","res_1","res_2","res_3","res_4","com_1",
           "com_2","com_3","com_4","com_5","cap_1","cap_2",
           "cap_3","cap_4")

names(df) <- var.names

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

df$emp_t <- rowSums(df[, grep("bemp.", names(df))])
df$sat_t <- rowSums(df[, grep("bsat.", names(df))])
df$res_t <- rowSums(df[, grep("bres.", names(df))])
df$com_t <- rowSums(df[, grep("bcom.", names(df))])
df$cap_t <- rowSums(df[, grep("bcap.", names(df))])

но в наборе данных гораздо больше переменных, и я хотел бы знать, есть ли способ сделать это только с одной строкой кода. Например, можно каким-то образом сгруппировать переменные, начинающиеся с одних и тех же строк, а затем применить строку функция.

спасибо заранее!

3 ответов


одним из возможных решений является транспонирование df и вычислить суммы для правильных столбцов, используя базу R


согласитесь с MrFlick, что вы можете поместить свои данные в длинный формат (см. reshape2, tidyr), но чтобы ответить на ваш вопрос:

cbind(
  df, 
  sapply(split.default(df, sub("_.*$", "_t", names(df))), rowSums)
)

сделает трюк


вам будет лучше в долгосрочной перспективе, если вы поместите свои данные в опрятный вид. Проблема в том, что данные имеют широкий, а не длинный формат. И имена переменных, например, emp_1, на самом деле две отдельные части данных: класс человека и идентификационный номер человека (или что-то в этом роде). Вот решение вашей проблемы с dplyr и tidyr.

library(dplyr)
library(tidyr)
df %>% 
  gather(key, value) %>% 
  extract(key, c("class", "id"), "([[:alnum:]]+)_([[:alnum:]]+)") %>% 
  group_by(class) %>% 
  summarize(class_sum = sum(value))

Сначала мы преобразуем фрейм данных из широкого в длинный формат с gather(). Тогда мы разделить значения emp_1 в отдельных столбцах class и id С extract(). Наконец, мы группируем по классу и суммируем значения в каждом классе. Результат:

Source: local data frame [5 x 2]

  class class_sum
1   cap        26
2   com        30
3   emp        23
4   res        22
5   sat        19