long - funcion melt en r
Calcule la media y la desviación estándar por grupo para múltiples variables en un data.frame (5)
Editar : esta pregunta se tituló originalmente << Remodelación de datos de largo a ancho en R >>
Solo estoy aprendiendo R e intentando encontrar maneras de aplicarlo para ayudar a otros en mi vida. Como un caso de prueba, estoy trabajando en la remodelación de algunos datos y tengo problemas para seguir los ejemplos que he encontrado en línea. Lo que estoy empezando se ve así:
ID Obs 1 Obs 2 Obs 3
1 43 48 37
1 27 29 22
1 36 32 40
2 33 38 36
2 29 32 27
2 32 31 35
2 25 28 24
3 45 47 42
3 38 40 36
Y lo que quiero terminar se verá así:
ID Obs 1 mean Obs 1 std dev Obs 2 mean Obs 2 std dev
1 x x x x
2 x x x x
3 x x x x
Etcétera. Lo que no estoy seguro es si necesito información adicional en mis datos de formato largo, o qué. Me imagino que la parte de matemáticas (encontrar la media y las desviaciones estándar) será la parte fácil, pero no he podido encontrar una manera que parezca trabajar para remodelar los datos correctamente para comenzar ese proceso.
Muchas gracias por la ayuda.
Añado la solución dplyr
.
set.seed(1)
df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
library(dplyr)
df %>% 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
# (int) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl)
# 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
Aquí hay otra data.table
respuestas de la data.table
de datos, utilizando los datos de @ Carson, que es un poco más legible (y también un poco más rápido, debido al uso de lapply
lugar de sapply
):
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 mean.Obs_1 mean.Obs_2 mean.Obs_3 sd.Obs_1 sd.Obs_2 sd.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
Esta es probablemente la forma más sencilla de hacerlo (con un ejemplo reproducible ):
library(plyr)
df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
ddply(df, .(ID), summarize, Obs_1_mean=mean(Obs_1), Obs_1_std_dev=sd(Obs_1),
Obs_2_mean=mean(Obs_2), Obs_2_std_dev=sd(Obs_2))
ID Obs_1_mean Obs_1_std_dev Obs_2_mean Obs_2_std_dev
1 1 -0.13994642 0.8258445 -0.15186380 0.4251405
2 2 1.49982393 0.2282299 0.50816036 0.5812907
3 3 -0.09269806 0.6115075 -0.01943867 1.3348792
EDITAR: El siguiente enfoque le ahorra muchos tipos de escritura al tratar con muchas columnas.
ddply(df, .(ID), colwise(mean))
ID Obs_1 Obs_2 Obs_3
1 1 -0.3748831 0.1787371 1.0749142
2 2 -1.0363973 0.0157575 -0.8826969
3 3 1.0721708 -1.1339571 -0.5983944
ddply(df, .(ID), colwise(sd))
ID Obs_1 Obs_2 Obs_3
1 1 0.8732498 0.4853133 0.5945867
2 2 0.2978193 1.0451626 0.5235572
3 3 0.4796820 0.7563216 1.4404602
Este es un problema de agregación, no un problema de remodelación como lo sugirió originalmente la pregunta. Deseamos agregar cada columna en una media y desviación estándar por ID. Hay muchos paquetes que manejan tales problemas. En la base de R se puede hacer usando un aggregate
como este (asumiendo que DF
es el marco de datos de entrada):
ag <- aggregate(. ~ ID, DF, function(x) c(mean = mean(x), sd = sd(x)))
Nota 1: Un comentarista señaló que ag
es un marco de datos para el cual algunas columnas son matrices. Aunque inicialmente pueda parecer extraño, de hecho simplifica el acceso. ag
tiene el mismo número de columnas que la entrada DF
. Su primera columna ag[[1]]
es ID
y la columna i del resto ag[[i+1]]
(o equivalanetly ag[-1][[i]]
) es la matriz de estadísticas para la observación i entrada columna. Si uno desea acceder a la estadística jth de la observación i, entonces es ag[[i+1]][, j]
que también puede escribirse como ag[-1][[i]][, j]
.
Por otro lado, supongamos que hay k
columnas estadísticas para cada observación en la entrada (donde k = 2 en la pregunta). Luego, si aplanamos la salida, para acceder a la estadística jth de la columna de observación i debemos usar ag[[k*(i-1)+j+1]]
más complejo o equivalentemente ag[-1][[k*(i-1)+j]]
.
Por ejemplo, compare la simplicidad de la primera expresión con la segunda:
ag[-1][[2]]
## mean sd
## [1,] 36.333 10.2144
## [2,] 32.250 4.1932
## [3,] 43.500 4.9497
ag_flat <- do.call("data.frame", ag) # flatten
ag_flat[-1][, 2 * (2-1) + 1:2]
## Obs_2.mean Obs_2.sd
## 1 36.333 10.2144
## 2 32.250 4.1932
## 3 43.500 4.9497
Nota 2: La entrada en forma reproducible es:
Lines <- "ID Obs_1 Obs_2 Obs_3
1 43 48 37
1 27 29 22
1 36 32 40
2 33 38 36
2 29 32 27
2 32 31 35
2 25 28 24
3 45 47 42
3 38 40 36"
DF <- read.table(text = Lines, header = TRUE)
Hay algunas maneras diferentes de hacerlo. reshape2
es un paquete útil. Personalmente, me gusta usar data.table
A continuación se muestra un paso a paso
Si myDF
es tu data.frame
:
library(data.table)
DT <- data.table(myDF)
DT
# this will get you your mean and SD''s for each column
DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x)))]
# adding a `by` argument will give you the groupings
DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x))), by=ID]
# If you would like to round the values:
DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID]
# If we want to add names to the columns
wide <- setnames(DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID], c("ID", sapply(names(DT)[-1], paste0, c(".men", ".SD"))))
wide
ID Obs.1.men Obs.1.SD Obs.2.men Obs.2.SD Obs.3.men Obs.3.SD
1: 1 35.333 8.021 36.333 10.214 33.0 9.644
2: 2 29.750 3.594 32.250 4.193 30.5 5.916
3: 3 41.500 4.950 43.500 4.950 39.0 4.243
Además, esto puede o no ser útil
> DT[, sapply(.SD, summary), .SDcols=names(DT)[-1]]
Obs.1 Obs.2 Obs.3
Min. 25.00 28.00 22.00
1st Qu. 29.00 31.00 27.00
Median 33.00 32.00 36.00
Mean 34.22 36.11 33.22
3rd Qu. 38.00 40.00 37.00
Max. 45.00 48.00 42.00