Merge (make middle) columns with a partially matching heading

I have data that looks like this:

   AAA_1   AAA_2  AAA_3  BBB_1  BBB_2  BBB_3 CCC
1   1       1      1       2     2      2     1
2   3       1      4       0     0      0     0
3   5       3      0       1     1      1     1

For each row, I want to make an average value for those columns that have a common function, as follows

feature <- c("AAA","BBB","CCC")

The desired result should look like this:

   AAA   BBB   CCC
1   1       2   1
2   2.6     0   0
3   2.6     1   1

for each template separately, I was able to do this:

data <- read.table("data.txt",header=T,row.name=1)
AAA <- as.matrix(rowMeans(data[ , grepl("AAA" , names( data ) ) ])

But I did not know how to partially match for different patterns in one line

Also tried other things like:

for (i in 1:length(features)){
feature[i] <- as.matrix(rowMeans(data[ , grepl(feature[i] , names( data ) ) ]))
}
+4
source share
3 answers
library(dplyr)
library(tidyr)
data %>%
  add_rownames() %>%
  gather("variable", "value", -rowname) %>%
  mutate(variable = gsub("_.*$", "", variable)) %>%
  group_by(rowname, variable) %>%
  summarise(mean = mean(value)) %>%
  spread(variable, mean)
+1
source

. , gsub() . ind, AAA, BBB CCC, lapply(), ind, . bind_cols() foo. , foo.

library(dplyr)

ind <- unique(gsub("_\\d+$", "", names(mydf)))

lapply(ind, function(x){
    select(mydf, contains(x)) %>%
    transmute(out = rowMeans(.))
    }) %>%
bind_cols() %>%
add_rownames -> foo

names(foo) <- ind

#       AAA   BBB   CCC
#     (dbl) (dbl) (dbl)
#1 1.000000     2     1
#2 2.666667     0     0
#3 2.666667     1     1

DATA

mydf <- structure(list(AAA_1 = c(1L, 3L, 5L), AAA_2 = c(1L, 1L, 3L), 
AAA_3 = c(1L, 4L, 0L), BBB_1 = c(2L, 0L, 1L), BBB_2 = c(2L, 
0L, 1L), BBB_3 = c(2L, 0L, 1L), CCC = c(1L, 0L, 1L)), .Names = c("AAA_1", 
"AAA_2", "AAA_3", "BBB_1", "BBB_2", "BBB_3", "CCC"), class = "data.frame", row.names = c(NA, 
-3L))
+2

Assuming yours is colnamesalways structured, as shown in your example, you can separate the names and the population.

new_names <-  unlist(strsplit(names(df),"\\_.*"))
colnames(df) <- new_names
#Testing with your data, we need to prevent the loss of dimension by using drop = FALSE  
sapply(unique(new_names), function(i) rowMeans(df[, new_names==i, drop = FALSE]))
#          AAA BBB CCC
#[1,] 1.000000   2   1
#[2,] 2.666667   0   0
#[3,] 2.666667   1   1

Data:

df <- structure(list(AAA_1 = c(1L, 3L, 5L), AAA_2 = c(1L, 1L, 3L), 
AAA_3 = c(1L, 4L, 0L), BBB_1 = c(2L, 0L, 1L), BBB_2 = c(2L, 
0L, 1L), BBB_3 = c(2L, 0L, 1L), CCC = c(1L, 0L, 1L)), .Names = c("AAA_1", 
"AAA_2", "AAA_3", "BBB_1", "BBB_2", "BBB_3", "CCC"), class = "data.frame", row.names = c(NA, 
-3L))        
+2
source

All Articles