Jia Gao
Jia Gao

Reputation: 1292

assign column names as row names after using lapply

like the question , I want to assign the column names of which were processed by lapply and tapply in R. A simple example:

df<-data.frame('X1'=rnorm(100),
               'X2'=rnorm(100),
               'X3'=c(c(rep('A',50)),c(rep('B',50))))


var<-c('X1','X2')
plyr::ldply(lapply(var, function(v) {
  tapply(df[,v],df$X3,mean)
}),rbind)

which will result as :

            A          B
1 -0.06856352 0.08608197
2 -0.23585510 0.01551267

from which I could not tell whether row 1 is from 'X1' or 'X2'. What I want is :

            A          B
X1 -0.06856352 0.08608197
X2 -0.23585510 0.01551267

although we could do a simply manual check in this example and a bold guess that row 1 is from 'X1', however this will become tedious and risky when there are lots more variables and function much more complex than mean.

Anyone know how to achieve this? your time and knowledge would be deeply appreciated. Thanks in advance.

Upvotes: 2

Views: 225

Answers (2)

akrun
akrun

Reputation: 887048

We can also use summarise_at with column_to_rownames

library(tidyverse)
df %>% 
   group_by(X3) %>% 
   summarise_at(vars(var), mean) %>% 
   as.data.frame() %>%
   column_to_rownames("X3") %>%
   t
#           A         B
#X1 -0.1720188 0.1834966
#X2  0.1413389 0.1138864

Upvotes: 1

coffeinjunky
coffeinjunky

Reputation: 11514

Just to flesh out my comment: many people like to do Split-Apply-Combine operations with dplyr. See e.g. the following:

library(dplyr)

set.seed(1)
df<-data.frame('X1'=rnorm(100),
               'X2'=rnorm(100),
               'X3'=c(c(rep('A',50)),c(rep('B',50))))

var<-c('X1','X2')

out <- df %>% group_by(X3) %>% select_(.dots = var) %>%  summarise_each(funs(mean))
out

# A tibble: 2 × 3
      X3        X1          X2
  <fctr>     <dbl>       <dbl>
1      A 0.1004483 -0.15248544
2      B 0.1173265  0.07686929

If you want to have more functions applied, or more complicated functions applied, it works the same way. For instance, to apply two functions:

df %>% group_by(X3) %>% select_(.dots = var) %>%  summarise_each(funs(mean, sd))

# A tibble: 2 × 5
      X3   X1_mean     X2_mean     X1_sd     X2_sd
  <fctr>     <dbl>       <dbl>     <dbl>     <dbl>
1      A 0.1004483 -0.15248544 0.8313939 0.8997394
2      B 0.1173265  0.07686929 0.9688279 1.0086725

You can then easily transpose the outcome if you really wish to do so.

transposed <- t(out[,-1])
colnames(transposed) <- t(out[,1])
transposed
            A          B
X1  0.1004483 0.11732645
X2 -0.1524854 0.07686929

Upvotes: 1

Related Questions