Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid same column names when multiple transformations in data.table?

Tags:

r

data.table

I tried to make multiple transformations for the same columns in a data.table and found this answer. However, if I follow the steps there I get identical column names (instead of mean.Obs_1, etc.).

library(data.table)
set.seed(1)
dt = data.table(ID=c(1:3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))

dt[, c(mean = lapply(.SD, mean), sd = lapply(.SD, sd)), by = ID]
#   ID      Obs_1      Obs_2      Obs_3     Obs_1     Obs_2     Obs_3
#1:  1  0.4854187 -0.3238542  0.7410611 1.1108687 0.2885969 0.1067961
#2:  2  0.4171586 -0.2397030  0.2041125 0.2875411 1.8732682 0.3438338
#3:  3 -0.3601052  0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692

Is there a way to avoid this behavior and get different column names for different transformations? I use the latest (1.9.4) stable version of data.table.

like image 478
janosdivenyi Avatar asked Jul 07 '15 09:07

janosdivenyi


2 Answers

You could try

library(data.table)
dt[, unlist(lapply(.SD, function(x) list(Mean=mean(x),
                    SD=sd(x))),recursive=FALSE), by=ID]
#   ID Obs_1.Mean  Obs_1.SD Obs_2.Mean  Obs_2.SD Obs_3.Mean  Obs_3.SD
#1:  1  0.4854187 1.1108687 -0.3238542 0.2885969  0.7410611 0.1067961
#2:  2  0.4171586 0.2875411 -0.2397030 1.8732682  0.2041125 0.3438338
#3:  3 -0.3601052 0.8105370  0.8195368 0.3829833 -0.4087233 1.4705692

Or a variation as suggested by @David Arenburg

 dt[, as.list(unlist(lapply(.SD, function(x) list(Mean=mean(x),
              SD=sd(x))))), by=ID]
 #   ID Obs_1.Mean  Obs_1.SD Obs_2.Mean  Obs_2.SD Obs_3.Mean  Obs_3.SD
 #1:  1  0.4854187 1.1108687 -0.3238542 0.2885969  0.7410611 0.1067961
 #2:  2  0.4171586 0.2875411 -0.2397030 1.8732682  0.2041125 0.3438338
 #3:  3 -0.3601052 0.8105370  0.8195368 0.3829833 -0.4087233 1.4705692
like image 95
akrun Avatar answered Nov 14 '22 21:11

akrun


If the data is not that big and the focus is on readability, using dplyr might be also a good idea.

library(dplyr)
dt %>% group_by(ID) %>% summarise_each(funs(mean, sd))
#  ID Obs_1_mean Obs_2_mean Obs_3_mean  Obs_1_sd  Obs_2_sd  Obs_3_sd
#1  1  0.4854187 -0.3238542  0.7410611 1.1108687 0.2885969 0.1067961
#2  2  0.4171586 -0.2397030  0.2041125 0.2875411 1.8732682 0.3438338
#3  3 -0.3601052  0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692

(As pointed out by @akrun, this won't work if you are using just one function in funs().)

like image 36
janosdivenyi Avatar answered Nov 14 '22 23:11

janosdivenyi