2012-03-13 8 views
14

Sé que se me ha preguntado por mucho tiempo, pero no entiendo cómo convertir lo siguiente en formato largo. Dispara Incluso pedí uno de ancho a largo con 2 medidas repetidas en SO. Me estoy frustrando con mi incapacidad para convertir mis datos. ¿Cómo puedo convertir esto (orden de la variable no importa):medidas múltiples de ancho a largo cada vez

 id trt work.T1 play.T1 talk.T1 total.T1 work.T2 play.T2 talk.T2 total.T2 
1 x1.1 cnt 0.34434350 0.7841665 0.1079332 0.88803151 0.64836951 0.87954320 0.7233519 0.5630988 
2 x1.2 tr 0.06132255 0.8426960 0.3338658 0.04685878 0.23478670 0.19711687 0.5164015 0.7617968 
3 x1.3 tr 0.36897981 0.1834721 0.3241316 0.76904051 0.07629721 0.06945971 0.4118995 0.7452974 
4 x1.4 tr 0.40759356 0.5285396 0.5654258 0.23022542 0.92309504 0.15733957 0.4132653 0.7078273 
5 x1.5 cnt 0.91433676 0.7029476 0.2031782 0.31518412 0.14721669 0.33345678 0.7620444 0.9868082 
6 x1.6 tr 0.88870525 0.9132728 0.2197045 0.28266959 0.82239037 0.18006177 0.2591765 0.4516309 
7 x1.7 cnt 0.98373218 0.2591739 0.6331153 0.71319565 0.41351839 0.14648269 0.7631898 0.1182174 
8 x1.8 tr 0.47719528 0.7926248 0.3525205 0.86213792 0.61252061 0.29057544 0.9824048 0.2386353 
9 x1.9 tr 0.69350823 0.6144696 0.8568732 0.10632352 0.06812050 0.93606889 0.6701190 0.4705228 
10 x1.10 cnt 0.42574646 0.7006205 0.9507216 0.55032776 0.90413220 0.10246047 0.5899279 0.3523231 

en esto:

 id trt time  work  play  talk  total 
1 x1.1 cnt 1 0.34434350 0.78416653 0.1079332 0.88803151 
2 x1.2 tr 1 0.06132255 0.84269599 0.3338658 0.04685878 
3 x1.3 tr 1 0.36897981 0.18347215 0.3241316 0.76904051 
4 x1.4 tr 1 0.40759356 0.52853960 0.5654258 0.23022542 
5 x1.5 cnt 1 0.91433676 0.70294755 0.2031782 0.31518412 
6 x1.6 tr 1 0.88870525 0.91327276 0.2197045 0.28266959 
7 x1.7 cnt 1 0.98373218 0.25917392 0.6331153 0.71319565 
8 x1.8 tr 1 0.47719528 0.79262477 0.3525205 0.86213792 
9 x1.9 tr 1 0.69350823 0.61446955 0.8568732 0.10632352 
10 x1.10 cnt 1 0.42574646 0.70062053 0.9507216 0.55032776 
11 x1.1 cnt 2 0.64836951 0.87954320 0.7233519 0.56309884 
12 x1.2 tr 2 0.23478670 0.19711687 0.5164015 0.76179680 
13 x1.3 tr 2 0.07629722 0.06945971 0.4118995 0.74529740 
14 x1.4 tr 2 0.92309504 0.15733957 0.4132653 0.70782726 
15 x1.5 cnt 2 0.14721669 0.33345678 0.7620444 0.98680824 
16 x1.6 tr 2 0.82239038 0.18006177 0.2591765 0.45163091 
17 x1.7 cnt 2 0.41351839 0.14648269 0.7631898 0.11821741 
18 x1.8 tr 2 0.61252061 0.29057544 0.9824048 0.23863532 
19 x1.9 tr 2 0.06812050 0.93606889 0.6701190 0.47052276 
20 x1.10 cnt 2 0.90413220 0.10246047 0.5899279 0.35232307 

el conjunto de datos

id <- paste('x', "1.", 1:10, sep="") 
set.seed(10) 
DF <- data.frame(id, trt=sample(c('cnt', 'tr'), 10, T), work.T1=runif(10), 
    play.T1=runif(10), talk.T1=runif(10), total.T1=runif(10), 
    work.T2=runif(10), play.T2=runif(10), talk.T2=runif(10), 
    total.T2=runif(10)) 

gracias de antemano!

EDITAR: Algo sucedió cuando estaba usando set.seed (sin duda un error que hice). Los datos de arriba no son los datos que obtendrá si usa set.seed(10). Dejo el error por precisión histórica y realmente no afecta las soluciones que las personas dieron.

+0

Pregunta clara, ejemplo reproducible. +1 –

Respuesta

8

Esto es bastante estrecha y cambiar los nombres de las columnas debe estar dentro de su conjunto de habilidades:

reshape(DF, 
     varying=c(work= c(3, 7), play= c(4,8), talk= c(5,9), total= c(6,10)), 
     direction="long") 

EDIT: Adición de una versión que es casi una solución exacta:

reshape(DF, varying=list(work= c(3, 7), play= c(4,8), talk= c(5,9), total= c(6,10)), 
     v.names=c("Work", "Play", "Talk", "Total"), 
      # that was needed after changed 'varying' arg to a list to allow 'times' 
     direction="long", 
     times=1:2,  # substitutes number for T1 and T2 
     timevar="times") # to name the time col 
+1

muchas gracias! Estaba cerca de eso, pero no entendía muy bien lo que estaba haciendo. Muy fácil y aprendí un poco más sobre la remodelación en la base (función potente pero a veces confusa. –

+0

) Estoy totalmente de acuerdo en que puede ser confuso. Al igual que Ben Bolker, solía usar remodelar :: fundir. –

+0

acabo de regresar aquí (Deseo que SO te haya dicho que si alguien edita su respuesta, solo una sugerencia de que agregas un comentario cuando lo haces, SO informa los carteles) y me gustó tu respuesta antes. Realmente me gusta ahora. Las anotaciones son geniales. ¡Gracias! –

3

extraño que parezca que Don parece obtener los mismos números que usted (que yo debería ya que ambos usamos set.seed(10)?) pero de lo contrario esto parece hacer el truco:

library(reshape) #this might work with reshape2 as well, I haven't tried ... 
DF2 <- melt(DF,id.vars=1:2) 
## split 'activity.time' label into two separate variables 
DF3 <- cbind(DF2, 
      colsplit(as.character(DF2$variable),"\\.", 
         names=c("activity","time"))) 
## rename time, reorder factors: 
DF4 <- transform(DF3, 
       time=as.numeric(gsub("^T","",time)), 
       activity=factor(activity, 
        levels=c("work","play","talk","total")), 
       id=factor(id,levels=paste("x1",1:10,sep="."))) 
## reshape back to wide 
DF5 <- cast(subset(DF4,select=-variable),id+trt+time~activity) 
## reorder 
DF6 <- with(DF5,DF5[order(time,id),]) 

Es más complicado que la respuesta de @DWin pero quizás (?) Más general.

+0

Gracias usted Ben. Estoy agregando tanto su respuesta como la de Dwin a mis (ahora más de 200 páginas) notas R. Ambas respuestas fueron muy perspicaces según la situación. +1 –

2

Si realmente no desea la "T" en la variable "tiempo" en la salida, ¿no podría simplemente hacer lo siguiente?

names(DF) = sub("T", "", names(DF)) 
reshape(DF, direction="long", varying=3:10) 

O, sin cambiar names(DF), usted podría simplemente establecer el argumento sep= para incluir "T":

reshape(DF, direction="long", varying=3:10, sep=".T") 

Estoy un poco confundido, sin embargo. Como señaló Ben Bolker al a in his comment, su "código del conjunto de datos" no proporciona los mismos números que usted. Además, la salida de DWin y la mía coincide perfectamente, pero no coincide con la salida "en esto" que tiene en su pregunta original.

Comprobé esto creando un marco de datos llamado "DWin" con sus resultados, y un marco de datos llamado "mío" con mis resultados y los comparé usando DWin == mine.

¿Puedes verificar que la salida que recibimos es realmente lo que necesitabas?

+0

Sí, la salida que usted y DWin obtuvieron son correctos. set.seed. Pido disculpas. Gran solución. Muy poco código. –

0

Otra forma de abordar el problema que requiere muy poco código, pero probablemente sería más lenta ,:

DF.1 <- DF[, 1:2] 
DF.2 <- DF[, 3:6] 
DF.3 <- DF[, 7:10] 

names(DF.2) <- names(DF.3) <- unlist(strsplit(names(DF.2), ".", fixed=T))[c(T,F)] 
time <- rep(1:2, each=nrow(DF.1)) 
data.frame(rbind(DF.1, DF.1), time, rbind(DF.2, DF.3)) 
4

La forma más concisa es utilizar tidyr combinado con dplyr biblioteca.

library(tidyr) 
library(dplyr) 
result <- DF %>% 
    # transfer to 'long' format 
    gather(loc, value, work.T1:total.`enter code here`T2) %>% 
    # separate the column into location and time 
    separate(loc, into = c('loc', 'time'), '\\.') %>% 
    # transfer to 'short' format 
    spread(loc, value) %>% 
    mutate(time = as.numeric(substr(time, 2, 2))) %>% 
    arrange(time) 

tidyr está diseñado específicamente para ordenar los datos.

+0

No llamaría eso conciso en comparación con otras soluciones. –

+1

Esto es superior a las soluciones que use 'reshape', más fácil de leer gracias a su estilo funcional (el operador'%>% ') y también a más rendimiento, creo, debido a que las partes clave están escritas en C++. – GregT

+1

¿Qué se supone que es la parte de 'ingresar código aquí'? @Yingsen Mao – vashts85

Cuestiones relacionadas