2012-01-25 18 views
5

Mam problemy z przekształceniem zestawu danych panelu z szerokiego na długi format. Zestaw danych wygląda następująco:Zmiana rozmiaru panelu danych na format długi do formatu

ID | KP1_430a | KP1_430b | KP1_430c | KP2_430a | KP2_430b | KP2_430c | KP1_1500a | ... 
1  .... 
2  .... 

KP1; KP2 do KP7 opisują fale. a, b do f opisują konkretną pozycję. (Np. Od lewej do prawej strony umieszczenie strony)

Chciałbym mieć te dane w długim formacie. W ten sposób:

ID | Party | Wave | 430 | 1500 
1  1  1  .. .. 
1  2  1  .. .. 
.  .  .   
1  1  2  .. .. 
.  .  .   
2  1  1  .. .. 

Próbowałem użyć funkcji zmiany kształtu. Ale miałem problemy z przekształceniem go w czasie i nad stronami jednocześnie.

Oto przykład małego pliku data.frame.

data <- data.frame(matrix(rnorm(10),2,10)) 
data[,1] <- 1:2 
names(data) <- c("ID","KP1_430a" , "KP1_430b" , "KP1_430c" , "KP2_430a" , "KP2_430b ", "KP2_430c ", "KP1_1500a" ,"KP1_1500b", "KP1_1500c") 

I to jest, jak daleko się dostałem.

data_long <- reshape(data,varying=list(names(data)[2:4],names(data)[5:7], names(data[8:10]), 
          v.names=c("KP1_430","KP2_430","KP1_1500"), 
          direction="long", timevar="Party") 

Pozostaje pytanie: w jaki sposób mogę uzyskać zmienne czasowe w długim formacie? Czy istnieje bardziej elegancki sposób na przekształcenie tych danych? W powyższym kodzie musiałbym wpisać nazwy (nazwy (dane) [2: 4]) dla każdej fali i zmiennej. W tym małym pliku data.frame jest OK, ale zbiór danych jest dużo większy.

EDYCJA: W jaki sposób można wykonać tę transformację ręcznie: faktycznie zrobiłem to, co pozostawiło mi plik długich stron.
Najpierw należy powiązać KP1_430a i KP1_1500a z identyfikatorami, czasem = 1 i stroną = 1 kolumną. Po drugie utwórz ten sam obiekt dla wszystkich stron [b-f], zmieniając odpowiednio indeks partyjny i dodaj go wierszowo. Wykonaj krok pierwszy i drugi dla pozostałych fal [2-7], odpowiednio zmieniając partię i czas var, i dołączaj je w rzędzie.

+0

Jeśli chcesz osobne kolumny dla 430 i 1500 w długim formacie, wtedy powinna być równa ilość danych z tych warunków w szerokim. W jaki sposób to zrobisz, będziesz miał dużo NA w 1500 kolumnie ... czy chciałeś tego w ten sposób? – John

+0

Och, to chyba wszystko trochę szkicowe. Występuje jednakowa liczba fal (1-7) i elementów partii (a-f) dla tych dwóch zmiennych. A więc: KP [1-7] _430 [a-f], KP [1-7] _1500 [a-f]. – lstoetze

+0

Jednak dla niektórych zmiennych w zestawie danych istnieje (a) tylko dane dla niektórych fal - np. KP [146] _1640 [a-f] lub (b) niezwiązane ze stroną - np. KP [1-7] _1490. – lstoetze

Odpowiedz

4

Zwykle łatwiej jest postępować w dwóch krokach: najpierw użyj melt, aby umieścić dane w "wysokim" formacie (chyba, że ​​już tak jest), a następnie użyj dcast, aby przekonwertować ti na szerszy format.

library(reshape2) 
library(stringr) 

# Tall format 
d <- melt(data, id.vars="ID") 

# Process the column containing wave and party 
d1 <- str_match_all( 
    as.character(d$variable), 
    "KP([0-9])_([0-9]+)([a-z])" 
) 
d1 <- do.call(rbind, d1) 
d1 <- d1[,-1] 
colnames(d1) <- c("wave", "number", "party") 
d1 <- as.data.frame(d1) 
d <- cbind(d, d1) 

# Convert to the desired format 
d <- dcast(d, ID + wave + party ~ number) 
+0

To działa! Wspaniały. Dziękuję Ci. – lstoetze

0

W tym momencie dane Wave znajdują się w nazwach zmiennych i należy je wyodrębnić za pomocą przetwarzania ciągów. Nie miałem problemów z wytopu

mdat <- melt(data, id.vars="ID") 
mdat$wave=sub("KP", "", sub("_.+$", "", mdat$variable)) # remove the other stuff 
mdat 

Twój opis jest zbyt pobieżne (jak dotąd) dla mnie, aby dowiedzieć się reguły wyprowadzania zmienną „Party”, więc chyba można edytować kwestionujesz, aby pokazać, w jaki sposób może być zrobione przez człowieka ... i wtedy możemy pokazać komputerowi, jak to zrobić.

EDIT: Jeśli ostatnia mała litera w oryginalnych nazw kolumn jest stroną, jak sądzi, Vincent, a następnie można przycinać spacje w tych nazwach i wyodrębnić:

mdat$var <- sub("\\s", "", (as.character(mdat$variable))) 
mdat$party=substr(mdat$var, nchar(mdat$var), nchar(mdat$var)) 
#-------------- 
> mdat 
    ID variable  value wave party  var 
1 1 KP1_430a 0.7220627 1  a KP1_430a 
2 2 KP1_430a 0.9585243 1  a KP1_430a 
3 1 KP1_430b -1.2954671 1  b KP1_430b 
4 2 KP1_430b 0.3393617 1  b KP1_430b 
5 1 KP1_430c -1.1477627 1  c KP1_430c 
6 2 KP1_430c -1.0909179 1  c KP1_430c 
<snipped output>