R sum of rows for different group of columns that start with similar string

本秂侑毒 提交于 2020-01-03 10:45:19

问题


I'm quite new to R and this is the first time I dare to ask a question here.

I'm working with a dataset with likert scales and I want to row sum over different group of columns which share the first strings in their name.

Below I constructed a data frame of only 2 rows to illustrate the approach I followed, though I would like to receive feedback on how I can write a more efficient way of doing it.

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

So, what I did, was to use the grep function in order to be able to sum the rows of the specified variables that started with certain strings and store them in a new variable. But I have to write a new line of code for each variable.

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))])

But there is a lot more variables in the dataset and I would like to know if there is a way to do this with only one line of code. For example, some way to group the variables that start with the same strings together and then apply the row function.

Thanks in advance!


回答1:


One possible solution is to transpose df and calculate sums for the correct columns using base R rowsum function (using set.seed(123))

cbind(df, t(rowsum(t(df), sub("_.*", "_t", names(df)))))
#   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 cap_t
# 1     2     4     5     3     1     2     4     5     3     1     2     4     5     3     1     2     4     5     3     1    13
# 2     1     3     4     2     5     1     3     4     2     5     1     3     4     2     5     1     3     4     2     5    14
#   com_t emp_t res_t sat_t
# 1    15    14    11     7
# 2    15    10    12     9



回答2:


Agree with MrFlick that you may want to put your data in long format (see reshape2, tidyr), but to answer your question:

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

Will do the trick




回答3:


You'll be better off in the long run if you put your data into tidy format. The problem is that the data is in a wide rather than a long format. And the variable names, e.g., emp_1, are actually two separate pieces of data: the class of the person, and the person's ID number (or something like that). Here is a solution to your problem with dplyr and tidyr.

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

First we convert the data frame from wide to long format with gather(). Then we split the values emp_1 into separate columns class and id with extract(). Finally we group by the class and sum the values in each class. Result:

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


来源:https://stackoverflow.com/questions/30384221/r-sum-of-rows-for-different-group-of-columns-that-start-with-similar-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!