Combina múltiples columnas en datos ordenados

Lo siento, estoy seguro de que hay una manera de hacer esto. Sin embargo, tengo problemas para interpretar las soluciones para que se ajusten a mi problema.

Mi conjunto de datos se ve así:

unique.id abx.1 start.1 stop.1 abx.2 start.2 stop.2 abx.3 start.3 stop.3 abx.4 start.4 1 1 Moxi 2014-01-01 2014-01-07 PenG 2014-01-01 2014-01-07 Vanco 2014-01-01 2014-01-07 Moxi 2014-01-01 2 2 Moxi 2014-01-01 2014-01-02 Cipro 2014-01-01 2014-01-02 PenG 2014-01-01 2014-01-02 Vanco 2014-01-01 3 3 Cipro 2014-01-01 2014-01-05 Vanco 2014-01-01 2014-01-05 Cipro 2014-01-01 2014-01-05 Vanco 2014-01-01 4 4 Vanco 2014-01-02 2014-01-03 Cipro 2014-01-02 2014-01-03 Cipro 2014-01-02 2014-01-03 PenG 2014-01-02 5 5 Vanco 2014-01-01 2014-01-02 PenG 2014-01-01 2014-01-02 PenG 2014-01-01 2014-01-02 Cipro 2014-01-01 stop.4 intervention 1 2014-01-07 0 2 2014-01-02 0 3 2014-01-05 1 4 2014-01-03 1 5 2014-01-02 0 

Con algún código para crear esto:

  abxoptions <- c("Cipro", "Moxi", "PenG", "Vanco") df3 <- data.frame( unique.id = 1:5, abx.1 = sample(abxoptions,5, replace=TRUE), start.1 = as.Date(c('2014-01-01', '2014-01-01', '2014-01-01', '2014-01-02', '2014-01-01')), stop.1 = as.Date(c('2014-01-07', '2014-01-02', '2014-01-05', '2014-01-03', '2014-01-02')), abx.2 = sample(abxoptions,5, replace=TRUE), start.2 = as.Date(c('2014-01-01', '2014-01-01', '2014-01-01', '2014-01-02', '2014-01-01')), stop.2 = as.Date(c('2014-01-07', '2014-01-02', '2014-01-05', '2014-01-03', '2014-01-02')), abx.3 = sample(abxoptions,5, replace=TRUE), start.3 = as.Date(c('2014-01-01', '2014-01-01', '2014-01-01', '2014-01-02', '2014-01-01')), stop.3 = as.Date(c('2014-01-07', '2014-01-02', '2014-01-05', '2014-01-03', '2014-01-02')), abx.4 = sample(abxoptions,5, replace=TRUE), start.4 = as.Date(c('2014-01-01', '2014-01-01', '2014-01-01', '2014-01-02', '2014-01-01')), stop.4 = as.Date(c('2014-01-07', '2014-01-02', '2014-01-05', '2014-01-03', '2014-01-02')), intervention = c(0,0,1,1,0) 

)

Me gustaría ordenar estos datos para que se vean así:

 unique.id abx start stop intervention 1 Moxi 2014-01-10 2014-01-07 0 1 Pen G 2014-01-01 2014-01-07 0 1 Vanco 2014-01-01 2014-01-07 0 1 Moxi 2014-01-01 2014-01-07 0 etc etc 

He pasado las últimas dos tardes tratando de resolver esto. Miró las siguientes soluciones: Reúna múltiples conjuntos de columnas y Combinando múltiples columnas en una sola

Ojalá pudiera entender este problema. Siento que la solución debería ser bastante fácil, simplemente no puedo resolverlo. Lo siento, no es un codificador aquí. Sospecho que el increíble tidyr pakcage de Hadley es el camino a seguir … simplemente no puedo resolver esto. Cualquier ayuda sería muy apreciada.

Casi todos los problemas de preparación de datos se pueden resolver en tres pasos:

  1. Reúna todas las columnas no variables
  2. Separar columna “colname” en múltiples variables
  3. Volver a difundir los datos

(a menudo solo necesitarás uno o dos de estos, pero creo que casi siempre están en este orden).

Para sus datos:

  1. La única columna que ya es una variable es unique.id
  2. Necesita dividir los nombres de las columnas actuales en variables y números
  3. Entonces necesitas volver a poner la variable “variable” en columnas

Esto se ve así:

 library(tidyr) library(dplyr) df3 %>% gather(col, value, -unique.id, -intervention) %>% separate(col, c("variable", "number")) %>% spread(variable, value, convert = TRUE) %>% mutate(start = as.Date(start, "1970-01-01"), stop = as.Date(stop, "1970-01-01")) 

Su caso es un poco más complicado porque tiene dos tipos de variables, por lo que debe restaurar los tipos al final.

Podría intentar reshape desde la base R

 reshape(df3, direction='long', varying=2:ncol(df3), sep=".") 

O use el merged.stack de splitstackshape

  library(splitstackshape) merged.stack(df3, var.stubs=c('abx', 'start', 'stop'), sep='.')[, c('start', 'stop') := lapply(.SD, as.Date, origin='1970-01-01'), .SDcols=4:5][] 

Recientemente, se ha agregado una nueva característica a melt.data.table , que permite que la fusión en varias columnas sea indolora. Todo lo que tiene que hacer es proporcionar las columnas que desea fusionar por separado en una list en el argumento measure.vars .

Puede obtener la versión de desarrollo siguiendo estas instrucciones .

 require(data.table) ## v1.9.5 setDT(dat) # dat is now a data.table melt(dat, id = 1L, measure = patterns("^abx", "^start", "^stop"), value.name = c("abx", "start", "stop")) # unique.id variable abx start stop # 1: 1 1 Moxi 2014-01-01 2014-01-07 # 2: 2 1 Moxi 2014-01-01 2014-01-02 # 3: 3 1 Cipro 2014-01-01 2014-01-05 # 4: 4 1 Vanco 2014-01-02 2014-01-03 # 5: 5 1 Vanco 2014-01-01 2014-01-02 # 6: 1 2 PenG 2014-01-01 2014-01-07 # 7: 2 2 Cipro 2014-01-01 2014-01-02 # 8: 3 2 Vanco 2014-01-01 2014-01-05 # 9: 4 2 Cipro 2014-01-02 2014-01-03 # 10: 5 2 PenG 2014-01-01 2014-01-02 # 11: 1 3 Vanco 2014-01-01 2014-01-07 # 12: 2 3 PenG 2014-01-01 2014-01-02 # 13: 3 3 Cipro 2014-01-01 2014-01-05 # 14: 4 3 Cipro 2014-01-02 2014-01-03 # 15: 5 3 PenG 2014-01-01 2014-01-02 # 16: 1 4 Moxi 2014-01-01 2014-01-07 # 17: 2 4 Vanco 2014-01-01 2014-01-02 # 18: 3 4 Vanco 2014-01-01 2014-01-05 # 19: 4 4 PenG 2014-01-02 2014-01-03 # 20: 5 4 Cipro 2014-01-01 2014-01-02 

He usado los números de columna aquí, pero también puedes proporcionar los nombres de las columnas.