2012-03-13 11 views
14

Wiem, że od szerokiego do długiego pytano zbyt wiele razy, ale nie mogę wymyślić, jak zamienić poniższe w długi format. Strzelam Nawet poprosiłam jednego z szerokich na długie z 2 powtórzonymi pomiarami na SO. Jestem sfrustrowany moją niezdolnością do konwersji moich danych. Jak mogę włączyć tę zmienną (kolejność nie ma znaczenia):od szerokiej do długiej wielokrotnej miary za każdym razem

 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 

w tym:

 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 

zbiorze danych

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)) 

Z góry dziękuję!

EDYCJA: Podczas korzystania z set.seed wydarzyło się coś nieprzyjemnego (z pewnością popełniłem błąd). Rzeczywiste dane powyżej nie są danymi, które otrzymasz, jeśli użyjesz set.seed(10). Zostawiam błąd dla dokładności historycznej i to naprawdę nie ma wpływu na rozwiązania, które dali ludzie.

+0

Wyczyść pytanie, powtarzalny przykład. +1 –

Odpowiedz

8

Jest to dość blisko i zmiana nazwy kolumn powinny być w zasięgu skillset:

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

EDIT: Dodawanie wersji, która jest niemal dokładną rozwiązanie:

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

dziękuję bardzo! Byłem blisko tego, ale nie bardzo rozumiałem, co robię. Bardzo proste i dowiedziałem się trochę więcej o przekształceniu w bazie (potężna, ale czasami dezorientująca funkcja) –

+0

Całkowicie zgadzam się, że może to być mylące.Jako Ben Bolker, użyłem po prostu użyć polecenia przekształcenia :: melt. –

+0

właśnie wróciłem (I ŻE TAK POWIEDZIAŁEŚ WIĘCEJ, JEŚLI KTÓRZY SIĘ WPROWADZIĆ W TWOJĄ odpowiedź, po prostu sugestię, że dodasz komentarz, gdy to zrobisz, SO informuje o tym plakacie) i podobała mi się twoja odpowiedź już przedtem Bardzo mi się podoba teraz Adnotacje są wspaniałe Dziękuję –

3

dziwo ja don Wydaje się, że otrzymujesz te same liczby, co Ty (które powinienem, ponieważ obaj używaliśmy set.seed(10)?), ale w przeciwnym razie wydaje się, że to wystarczy:

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),]) 

Jest to bardziej skomplikowane niż odpowiedź @ DWina, ale może (?) Bardziej ogólne.

+0

ty Ben. Dodaję zarówno twoją odpowiedź, jak i Dwina do moich (teraz ponad 200 stron) notatek R. Obie odpowiedzi były bardzo wnikliwe w zależności od sytuacji +1 –

2

Jeśli naprawdę nie chcesz "T" w zmiennej "time" na wyjściu, czy nie możesz po prostu wykonać następujące czynności?

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

Albo, bez zmiany names(DF), można po prostu ustawić sep= argument to "T":

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

jestem nieco zdezorientowany, choć. Jak Ben Bolker zwrócił uwagę na numer a in his comment, "kod zbioru danych" nie zawiera tych samych numerów co dane. Również wyniki DWin i moich kopalni są perfekcyjne, ale nie pasują do tego w wyjściowym "do tego" w oryginalnym pytaniu.

Sprawdziłem to, tworząc jedną ramkę danych o nazwie "DWin" z jego wynikami i jedną ramkę danych o nazwie "moje" z moimi wynikami i porównano je za pomocą DWin == mine.

Czy możesz zweryfikować, że uzyskane dane są rzeczywiście potrzebne?

+0

Tak, wynik jaki otrzymałeś i DWin jest poprawny. set.seed Przepraszam, świetne rozwiązanie, bardzo mało kodu, –

0

Innym sposobem podejścia do problemu, który wymaga bardzo mało kodu, ale prawdopodobnie wolniej ,:

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

najbardziej zwięzły sposobem jest użycie tidyr połączeniu z dplyr bibliotece.

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 został zaprojektowany specjalnie do przechowywania danych.

+0

Nie nazwałbym tego zbyt zwięźle w porównaniu do innych rozwiązań –

+1

To jest lepsze od rozwiązań, które użyj 'reshape' - łatwiejsze do odczytania dzięki swojemu funkcjonalnemu stylowi (operator'%>% ') i bardziej wydajnemu też, jak sądzę, ze względu na kluczowe fragmenty napisane w C++. – GregT

+1

jaka część 'enter code here' powinna być? @ Yingsen Mao – vashts85

Powiązane problemy