valores valor studio seleccionar numero filas eliminar datos data contar columnas buscar r reshape reshape2 melt

valor - seleccionar columnas en r



Remodelación de ancho a largo con columnas de múltiples valores (5)

Necesito cambiar la forma de mi tabla ancha en formato largo, pero manteniendo varios campos para cada registro, por ejemplo:

dw <- read.table(header=T, text='' sbj f1.avg f1.sd f2.avg f2.sd blabla A 10 6 50 10 bA B 12 5 70 11 bB C 20 7 20 8 bC D 22 8 22 9 bD '') # Now I want to melt this table, keeping both AVG and SD as separate fields for each measurement, to get something like this: # sbj var avg sd blabla # A f1 10 6 bA # A f2 50 10 bA # B f1 12 5 bB # B f2 70 11 bB # C f1 20 7 bC # C f2 20 8 bC # D f1 22 8 bD # D f2 22 9 bD

Tengo un conocimiento básico del uso de melt y reshape , pero no es obvio para mí cómo aplicar este remodelado en mi caso. Agradecería cualquier sugerencia o señalaría otra publicación de SO si ya se hubiera pedido algo similar.


Esto parece hacer lo que quieres, excepto que la f se elimina de los elementos a time .

reshape(dw, idvar = "sbj", varying = list(c(2,4),c(3,5)), v.names = c("ave", "sd"), direction = "long") sbj blabla time ave sd A.1 A bA 1 10 6 B.1 B bB 1 12 5 C.1 C bC 1 20 7 D.1 D bD 1 22 8 A.2 A bA 2 50 10 B.2 B bB 2 70 11 C.2 C bC 2 20 8 D.2 D bD 2 22 9


Otra opción usando el nuevo paquete tidyr Hadley.

library(tidyr) library(dplyr) dw <- read.table(header=T, text='' sbj f1.avg f1.sd f2.avg f2.sd blabla A 10 6 50 10 bA B 12 5 70 11 bB C 20 7 20 8 bC D 22 8 22 9 bD '') dw %>% gather(v, value, f1.avg:f2.sd) %>% separate(v, c("var", "col")) %>% arrange(sbj) %>% spread(col, value)


Para agregar a las opciones disponibles aquí, también puede considerar merged.stack de mi paquete "splitstackshape":

library(splitstackshape) merged.stack(dw, var.stubs = c("avg", "sd"), sep = "var.stubs", atStart = FALSE) # sbj blabla .time_1 avg sd # 1: A bA f1. 10 6 # 2: A bA f2. 50 10 # 3: B bB f1. 12 5 # 4: B bB f2. 70 11 # 5: C bC f1. 20 7 # 6: C bC f2. 20 8 # 7: D bD f1. 22 8 # 8: D bD f2. 22 9

También puedes hacer un poco más de limpieza en la variable ".time_1" , como esta.

merged.stack(dw, var.stubs = c("avg", "sd"), sep = "var.stubs", atStart = FALSE)[, .time_1 := sub( ".", "", .time_1, fixed = TRUE)][] # sbj blabla .time_1 avg sd # 1: A bA f1 10 6 # 2: A bA f2 50 10 # 3: B bB f1 12 5 # 4: B bB f2 70 11 # 5: C bC f1 20 7 # 6: C bC f2 20 8 # 7: D bD f1 22 8 # 8: D bD f2 22 9

atStart = FALSE el uso del argumento atStart = FALSE . Esto se debe a que sus nombres están en un poco de un orden diferente al que parecen las funciones relacionadas con la reforma. En general, se espera que el "stub" venga primero, y luego los "tiempos", como este:

dw2 <- dw setnames(dw2, gsub("(.*)//.(.*)", "//2.//1", names(dw2))) names(dw2) # [1] "sbj" "avg.f1" "sd.f1" "avg.f2" "sd.f2" "blabla"

Si los nombres estaban en ese formato, tanto la merged.stack base R como la merged.stack benefician de una sintaxis más directa:

merged.stack(dw2, var.stubs = c("avg", "sd"), sep = ".") reshape(dw2, idvar = c("sbj", "blabla"), varying = 2:5, sep = ".", direction = "long")


melt desde la versión> = 1.9.6 de data.table , hace esto especificando el índice de la columna en measure.vars como una list .

melt(setDT(dw), measure.vars=list(c(2,4), c(3,5)), variable.name=''var'', value.name=c(''avg'', ''sd''))[, var:= paste0(''f'',var)][order(sbj)] # sbj blabla var avg sd #1: A bA f1 10 6 #2: A bA f2 50 10 #3: B bB f1 12 5 #4: B bB f2 70 11 #5: C bC f1 20 7 #6: C bC f2 20 8 #7: D bD f1 22 8 #8: D bD f2 22 9

O podrías usar la nueva función de patterns :

melt(setDT(dw), measure = patterns("avg", "sd"), variable.name = ''var'', value.name = c(''avg'', ''sd'')) # sbj blabla var avg sd # 1: A bA 1 10 6 # 2: B bB 1 12 5 # 3: C bC 1 20 7 # 4: D bD 1 22 8 # 5: A bA 2 50 10 # 6: B bB 2 70 11 # 7: C bC 2 20 8 # 8: D bD 2 22 9


reshape hace con los argumentos apropiados.

lista varying las columnas que existen en el formato ancho, pero se dividen en varias filas en el formato largo. v.names es el formato largo equivalente. Entre los dos, se crea un mapeo.

De ?reshape :

Además, no se intenta adivinar si v.names se da explícitamente. Observe que el orden de las variables en la variación es como x.1, y.1, x.2, y.2.

Dados estos argumentos varying y v.names , reshape es lo suficientemente inteligente como para ver que he especificado que el índice está antes del punto aquí (es decir, orden 1.x, 1.y, 2.x, 2.y). Tenga en cuenta que los datos originales tienen las columnas en este orden, por lo que podemos especificar varying=2:5 para estos datos de ejemplo, pero eso no es seguro en general.

Dados los valores de times y v.names , reshape divide las columnas varying en a . para crear las columnas en la salida.

times especifica los valores que se utilizarán en la columna var creada, y v.names se pegan en estos valores para obtener nombres de columna en el formato ancho para la asignación al resultado.

Finalmente, idvar se especifica para ser la columna sbj , que identifica registros individuales en el formato ancho (gracias @thelatemail).

reshape(dw, direction=''long'', varying=c(''f1.avg'', ''f1.sd'', ''f2.avg'', ''f2.sd''), timevar=''var'', times=c(''f1'', ''f2''), v.names=c(''avg'', ''sd''), idvar=''sbj'') ## sbj blabla var avg sd ## A.f1 A bA f1 10 6 ## B.f1 B bB f1 12 5 ## C.f1 C bC f1 20 7 ## D.f1 D bD f1 22 8 ## A.f2 A bA f2 50 10 ## B.f2 B bB f2 70 11 ## C.f2 C bC f2 20 8 ## D.f2 D bD f2 22 9