2015-07-29 9 views
7

Ho condotto uno studio che, in retrospettiva (una vita, una impara :-)) sembra generare dati multilivello. Ora sto cercando di ristrutturare il set di dati da ampio a lungo in modo da poterlo analizzare utilizzando, ad es. lme4.Come posso convertire un ampio dataframe in un dataframe lungo per una struttura multilivello con 'quadruplo nesting'?

In tal modo, incontro una, ehm, sfida, che ho incontrato alcune volte prima, ma per la quale non ho mai trovato una buona soluzione. Ho cercato di nuovo questa volta, ma probabilmente uso le parole chiave sbagliate - o questo problema è molto più raro di quanto pensassi.

Fondamentalmente, in questo set di dati, i nomi variabili indicano per quali dati di misura vengono raccolti. Ho chiesto ai partecipanti di valutare (valutare) gli interventi (potrebbe essere qualsiasi cosa realmente). Ogni intervento è in uno dei 6 domini comportamentali. Inoltre, i partecipanti hanno valutato ciascun intervento sia quando è stato presentato da solo, sia contemporaneamente ad un altro intervento, o con altri due interventi. C'erano tre tipi di interventi, tutti valutati prima (t0) e dopo (t1) li ho presentati con alcune informazioni.

Così, in effetti, ho un dataframe che può essere rigenerata in questo modo:

### Elements of the variable names 
measurementMomentsVector <- c("t0", "t1"); 
interventionTypesVector <- c("fear", "know", "scd"); 
nrOfInterventionsSimultaneouslyVector <- c(1, 2, 3); 
behaviorDomainsVector <- c("diet", "pox", "alc", "smoking", "traff", "adh"); 

### Generate a vector with all variable names 
variableNames <- 
    apply(expand.grid(measurementMomentsVector, 
        interventionTypesVector, 
        nrOfInterventionsSimultaneouslyVector, 
        behaviorDomainsVector), 
     1, paste0, collapse="_"); 

### Generate 5 'participants' worth of data 
wideData <- data.frame(matrix(rnorm(5*length(variableNames)), nrow=5)); 

### Assign names 
names(wideData) <- variableNames; 

### Add unique id variable for every participants 
wideData$id <- 1:5; 

Quindi, utilizzando head(wideData)[, 1:5] si può vedere o meno quello che sembra il dataframe come:

t0_fear_1_diet t1_fear_1_diet t0_know_1_diet t1_know_1_diet t0_scd_1_diet 
1  -0.9338191  0.9747453  1.0069036  0.3500103 -0.844699708 
2  0.8921867  1.3687834  -1.2005791  0.2747955 1.316768219 
3  1.6200200  0.5245470  -1.2910586  1.3211912 -0.174795144 
4  0.1543738  0.7535642  0.4726131  -0.3464789 -0.009190702 
5  -1.3676692  -0.4491574  -2.0902003  -0.3484678 -2.537501824 

Ora, vuoi convertire questi dati in un lungo dataframe, con 6 variabili, ad esempio 'id', 'measurementMoment', 'interventionType', 'nrOfInterventionsSimultaneously', 'behaviorDomain' e 'evaluation', dove la prima variabile indica i partecipanti a cui un record appartiene, il las t variabile è il punteggio (valutazione, grado, valutazione) i partecipanti hanno dato un intervento specifico, e le quattro variabili in mezzo indicano quale intervento viene valutato esattamente.

Probabilmente potrei scrivere un codice 'personalizzato' solo per questo problema, ma mi aspetto che R 'abbia qualcosa per questo'. Ho giocato in giro con reshape2, ad esempio:

longData <- reshape(wideData, varying=1:(ncol(wideData)-1), 
        idvar="id", 
        sep="_", direction="long") 

Ma non riesce a indovinare le variabili nel tempo variabili:

Error in guess(varying) : 
    failed to guess time-varying variables from their names 

ho lottato con questo un paio di volte, e non riesco a trovare alcuna risposta online. E ora ho davvero bisogno di andare avanti, quindi ho pensato di provare questo come ultimo sforzo prima di ricorrere a scrivere qualcosa di personalizzato :-)

Apprezzerei molto ogni suggerimento che qualcuno può dare !!!

+0

Qual è il valore di 'firstSecondOccurrenceVector'? – krlmlr

+0

Scusate, era un rimpasto da prima che lo chiarissi un po '! Non è più importante :-) Scusa per la confusione! – Matherion

+0

Non chiedere scusa. Invece modifica il codice in modo che venga eseguito. –

risposta

8

Credo che il problema può essere risolto con un approccio in due fasi:

  1. sciogliere i dati in un lungo data.frame (o come ho fatto io, in una lunga data.table)
  2. dividere la colonna variable con tutta le etichette in colonne separate per ogni variabile di raggruppamento richiesta.

Dato che le informazioni di questo è nelle etichette, questo può essere facilmente realizzato con la funzione tstrsplit dal pacchetto data.table.

Questo è quello che si potrebbe essere alla ricerca di:

library(data.table) 
longData <- melt(setDT(wideData), id.vars="id") 
longData[, c("moment", "intervention", "number", "behavior") := 
       tstrsplit(variable, "_", type.convert = TRUE) 
     ][, variable:=NULL] 

il risultato:

> head(longData,15) 
    id  value moment intervention number behavior 
1: 1 -0.07747254  t0   fear  1  diet 
2: 2 -0.76207379  t0   fear  1  diet 
3: 3 1.15501244  t0   fear  1  diet 
4: 4 1.24792369  t0   fear  1  diet 
5: 5 -0.28226121  t0   fear  1  diet 
6: 1 -1.04875354  t1   fear  1  diet 
7: 2 -0.91436882  t1   fear  1  diet 
8: 3 0.72863487  t1   fear  1  diet 
9: 4 0.10934261  t1   fear  1  diet 
10: 5 -0.06093002  t1   fear  1  diet 
11: 1 -0.70725760  t0   know  1  diet 
12: 2 1.06309003  t0   know  1  diet 
13: 3 0.89501164  t0   know  1  diet 
14: 4 1.48148316  t0   know  1  diet 
15: 5 0.22086835  t0   know  1  diet 

In alternativa al data.table, si può anche dividere la colonna variable con la funzione cSplit del pacchetto splitstackshape (sarà necessario rinominare successivamente le colonne delle variabili risultanti):

library(splitstackshape) 
longData <- cSplit(longData, sep="_", "variable", "wide", type.convert=TRUE) 
names(longData) <- c("id","value","moment","intervention","number","behavior") 

o con tidyr:

library(tidyr) 
separate(longData, variable, c("moment", "intervention", "number", "behavior"), sep="_", remove=TRUE) 
+0

Questo è grandioso, grazie! Esattamente quello di cui ho bisogno. Grazie anche per avermi indicato verso data.table, sembra fantastico! Grazie mille!!! – Matherion

Problemi correlati