2015-04-21 10 views
33

Próbuję wziąć kolumny, które są w długim formacie i rozłożyć je na szeroki format, jak pokazano poniżej. Chciałbym użyć tidyr do rozwiązania tego problemu za pomocą narzędzi do manipulacji danymi, w które inwestuję, ale aby udzielić tej odpowiedzi bardziej ogólnej, proszę podać inne rozwiązania.Jak rozproszyć powtarzające się pomiary wielu zmiennych w szerokim formacie?

Oto co mam:

library(dplyr); library(tidyr) 

set.seed(10) 
dat <- data_frame(
    Person = rep(c("greg", "sally", "sue"), each=2), 
    Time = rep(c("Pre", "Post"), 3), 
    Score1 = round(rnorm(6, mean = 80, sd=4), 0), 
    Score2 = round(jitter(Score1, 15), 0), 
    Score3 = 5 + (Score1 + Score2)/2 
) 

## Person Time Score1 Score2 Score3 
## 1 greg Pre  80  78 84.0 
## 2 greg Post  79  80 84.5 
## 3 sally Pre  75  74 79.5 
## 4 sally Post  78  78 83.0 
## 5 sue Pre  81  78 84.5 
## 6 sue Post  82  81 86.5 

Pożądany szeroki format:

Person Pre.Score1 Pre.Score2 Pre.Score3 Post.Score1 Post.Score2 Post.Score3 
1 greg   80   78  84.0   79   80  84.5 
2 sally   75   74  79.5   78   78  83.0 
3 sue   81   78  84.5   82   81  86.5 

mogę to zrobić wykonując coś takiego za każdy wynik:

spread(dat %>% select(Person, Time, Score1), Time, Score1) %>% 
    rename(Score1_Pre = Pre, Score1_Post = Post) 

A następnie za pomocą _join, ale wydaje się to pełne gadek i podoba mi się, że musi być lepszy sposób.

Podobne pytania:
tidyr wide to long with two repeated measures
Is it possible to use spread on multiple columns in tidyr similar to dcast?

+2

Jest to łatwiejsze w wersji woju 'data.table' tj. 'dcast (setDT (dat), Person ~ Time, value.var = c ('Score1', 'Score2', 'Score3'))' – akrun

+0

@TylerRinker, myślę, że odnosi się do drugiej kolumny twojego wyniku. – BrodieG

Odpowiedz

42

Jeśli chcesz trzymać tidyr/dplyr

dat %>% 
    gather(temp, score, starts_with("Score")) %>% 
    unite(temp1, Time, temp, sep = ".") %>% 
    spread(temp1, score) 
+0

To jest rozwiązanie * tidyr *, o którym mówiłem, że jest mniej satysfakcjonujące niż jedna z 2 innych odpowiedzi tutaj. Chciałbym zobaczyć funkcjonalność ** reshape2 ** w odniesieniu do tego rodzaju ruchu dodanego do ** tidyr **. –

+5

@TylerRinker Celem tidyr jest sprawić, by twoje dane były uporządkowane, więc nie powinieneś oczekiwać, że odwrotność będzie łatwiejsza. – hadley

+2

@hadely Tak, widzę, jak narzędzia powinny spełniać filozofię pakietu. Często myślę, że ** tidyr ** zastąpił ** przekształcić **, ale tak naprawdę mają różne podstawowe filozofie (nazwy pakietów mówią wszystko); ** tidyr ** to sub-filozofia ** reshape2 **. Wszelkie plany dotyczące pakietu ** untidyr ** :-) –

10

Korzystanie reshape2:

library(reshape2) 
dcast(melt(dat), Person ~ Time + variable) 

Produkuje:

Using Person, Time as id variables 
    Person Post_Score1 Post_Score2 Post_Score3 Pre_Score1 Pre_Score2 Pre_Score3 
1 greg   79   78  83.5   83   81  87.0 
2 sally   82   81  86.5   75   74  79.5 
3 sue   78   78  83.0   82   79  85.5 
+4

Prawdopodobnie wystarczy "przekształcenie (dat, Person ~ Time + variable)". –

+0

Dzięki @DavidArenburg, nie wiedziałem o tym jednym – BrodieG

13

Korzystanie dcast z pakietu data.table.

library(data.table)#v1.9.5+ 
dcast(setDT(dat), Person~Time, value.var=paste0("Score", 1:3)) 

Albo reshape od baseR

reshape(as.data.frame(dat), idvar='Person', timevar='Time',direction='wide') 
+3

'value.var = paste0 (" Score ", 1: 3)'? +1 dla bazy (nadal boję się 'przekształcenia') – BrodieG

+0

@BrodieG Dzięki, działa, a także' names (dat) [3: 5] 'lub może być' grep'. – akrun

Powiązane problemy