2015-07-29 20 views
7

Przeprowadziłem badanie, które z perspektywy czasu (jeden żyje, jeden się uczy :-)) wydaje się generować wielopoziomowe dane. Teraz próbuję zmienić zestaw danych z szerokiego na długi, aby móc go analizować za pomocą np. lme4.Jak przekonwertować szeroką ramkę danych na długą ramkę danych dla struktury wielopoziomowej z "poczwórnym zagnieżdżeniem"?

W ten sposób napotykam na ... wyzwanie, z którym już kilka razy się spotkałem, ale do którego nigdy nie znalazłem dobrego rozwiązania. Tym razem szukałem ponownie, ale prawdopodobnie używam złych słów kluczowych - lub ten problem jest znacznie rzadszy, niż myślałem.

Zasadniczo w tym zestawie danych zmienne_różne wskazują, dla których danych pomiarowych są zbierane. Poprosiłem uczestników o ocenę (ocenę) interwencji (może być cokolwiek naprawdę). Każda interwencja znajduje się w jednej z 6 domen behawioralnych. Ponadto uczestnicy oceniali każdą interwencję, gdy była ona prezentowana samodzielnie lub jednocześnie z inną interwencją lub dwiema innymi interwencjami. Były trzy rodzaje interwencji, wszystkie zostały ocenione wcześniej (t0), a po (t1) przedstawiłem im pewne informacje.

Tak, w istocie, mam dataframe że można regenerować tak:

### 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; 

więc korzystanie head(wideData)[, 1:5] widać mniej więcej co dataframe wygląda następująco:

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 

Teraz chcesz przekonwertować te dane na długą ramkę danych, z 6 zmiennymi, na przykład "id", "pomiarMoment", "typ interwencji", "nrOfInterventionsSimultaneously", "behaviorDomain" i "evaluation", gdzie pierwsza zmienna oznacza uczestników, do których rekord należy, las t zmienną jest wynik (ocena, ocena, ocena), uczestnicy podali konkretną interwencję, a cztery zmienne pośrednie wskazują, która interwencja jest dokładnie oceniana.

Mogę prawdopodobnie napisać jakiś "niestandardowy" kod tylko dla tego problemu, ale spodziewam się, że R "ma coś do tego". I już zostały gry z reshape2, np:

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

Ale nie udało się odgadnąć zmienne w czasie zmienne:

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

mam zmaga się z tym już kilka razy, i nie uda mi się znaleźć żadnych odpowiedzi w Internecie. A teraz naprawdę muszę iść dalej, więc pomyślałem, że spróbuję tego jako ostatni wysiłek zanim ucieknę się do napisania czegoś na zamówienie :-)

Byłbym bardzo wdzięczny za wszelkie wskazówki, które każdy może dać !!!

+0

Jaka jest wartość 'firstSecondOccurrenceVector'? – krlmlr

+0

Przepraszam, to było resztki sprzed wyjaśnienia! To już nie ważne :-) Przepraszamy za zamieszanie! – Matherion

+0

Nie przepraszaj. Zamiast tego edytuj kod, aby działał. –

Odpowiedz

8

Myślę, że problem może być rozwiązany z podejściem dwuetapowym:

  1. topić swoje dane na długi data.frame (lub tak jak ja, w długi data.table)
  2. podzielić kolumnę variable ze wszystkim etykiety w oddzielnych kolumnach dla każdej wymaganej zmiennej grupującej.

Ponieważ informacja o tym znajduje się na etykietach, można to łatwo osiągnąć za pomocą funkcji tstrsplit z pakietu data.table.

To, co może być szukasz:

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

Rezultat:

> 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 

Jako alternatywę dla data.table, można również podzielić kolumnę variable z funkcją cSplit pakietu splitstackshape (będziesz musiał następnie zmienić nazwy kolumn wynikowych):

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

lub tidyr:

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

To świetnie, dziękuję! Dokładnie to, czego potrzebuję. Dziękuję również za skierowanie mnie na stronę data.table, wygląda świetnie! Dziękuję Ci bardzo!!! – Matherion

Powiązane problemy