2012-02-18 38 views
5

Funkcje topienia/odlewania w pakiecie przekształcania są świetne, ale nie jestem pewien, czy istnieje prosty sposób ich zastosowania, gdy mierzone zmienne są różnych typów. Na przykład, tutaj jest to fragment z gdzie każda MD zapewnia płeć i ciężar trzech pacjentów:Alternatywy dla statystyk :: zmiana kształtu

ID PT1 WT1 PT2 WT2 PT3 WT3 
1 "M" 170 "M" 175 "F" 145 
... 

której celem jest, aby przekształcić tak, każdy rząd jest pacjentem:

ID PTNUM GENDER WEIGHT 
1 1  "M" 170 
1 2  "M" 175 
1 3  "F" 145 
... 

Użycie funkcja zmiany kształtu w pakiecie statystyk jest jedną z opcji, o których wiem, ale zamieszczam tutaj w nadziei, że użytkownicy R bardziej doświadczeni niż ja opublikują inne, mam nadzieję, lepsze metody. Wielkie dzięki!

-

@Vincent Zoonekynd:

Lubiłem Twój przykład dużo, więc uogólnić go do wielu zmiennych.

# Sample data 
n <- 5 
d <- data.frame(
    id = 1:n, 
    p1 = sample(c("M","F"),n,replace=TRUE), 
    q1 = sample(c("Alpha","Beta"),n,replace=TRUE), 
    w1 = round(runif(n,100,200)), 
    y1 = round(runif(n,100,200)), 
    p2 = sample(c("M","F"),n,replace=TRUE), 
    q2 = sample(c("Alpha","Beta"),n,replace=TRUE), 
    w2 = round(runif(n,100,200)), 
    y2 = round(runif(n,100,200)), 
    p3 = sample(c("M","F"),n,replace=TRUE), 
    q3 = sample(c("Alpha","Beta"),n,replace=TRUE), 
    w3 = round(runif(n,100,200)), 
    y3 = round(runif(n,100,200)) 
) 
# Reshape the data.frame, one variable at a time 
library(reshape) 
d1 <- melt(d, id.vars="id", measure.vars=c("p1","p2","p3","q1","q2","q3")) 
d2 <- melt(d, id.vars="id", measure.vars=c("w1","w2","w3","y1","y2","y3")) 
d1 = cbind(d1,colsplit(d1$variable,names=c("var","ptnum"))) 
d2 = cbind(d2,colsplit(d2$variable,names=c("var","ptnum"))) 
d1$variable = NULL 
d2$variable = NULL 
d1c = cast(d1,...~var) 
d2c = cast(d2,...~var) 
# Join the two data.frames 
d3 = merge(d1c, d2c, by=c("id","ptnum"), all=TRUE) 

-

myśli końcowe: Moja motywacja na to pytanie było poznanie alternatyw dla pakietu przekształcenia innej niż statystykach :: funkcję zmienią. W tej chwili doszedłem do następujących wniosków:

  • Trzymaj się statystyk :: zmieniaj kształt, kiedy możesz. Tak długo, jak pamiętasz o używaniu listy zamiast prostego wektora dla argumentu "zmiennego", nie będziesz miał problemów. W przypadku mniejszych zbiorów danych - tym razem miałem do czynienia z kilkoma tysiącami przypadków pacjentów z mniej niż 200 zmiennymi - mniejsza prędkość tej funkcji warta jest prostoty kodu.

  • Aby zastosować metodę rzutowania/topienia w pakiecie przekształcenia Hadleya Wickhama (lub przekształcania2), należy podzielić zmienne na dwa zestawy, z których jeden składa się ze zmiennych numerycznych, a drugi ze zmiennych znakowych. Kiedy twój zbiór danych jest wystarczająco duży, aby znaleźć statystyki :: przekształcić się w nie do zniesienia, wyobrażam sobie, że dodatkowy krok dzielenia zmiennych na dwa zestawy nie będzie tak zły.

+3

Lepiej w jakim sensie? zmiana kształtu jest przeznaczona do takich zadań, więc dlaczego jej nie używać? – Fojtasek

+0

Zmiana kształtu działa tak długo, jak długo pamięta się użycie kanonicznej formy różnych argumentów (lista): [link] (http://www.mail-archive.com/[email protected]/msg160715 .html) Z R, jestem ciągle zaskoczony istnieniem alternatyw, których nie byłem świadomy, więc pomyślałem, że ktoś zamieści inne podejścia. Jednym z przykładów definiowania "lepszego" byłaby szybkość: w moim wprawdzie subiektywnym doświadczeniu, obsada/topnienie wydaje się szybsza niż wbudowana zmiana kształtu. –

+0

Nie zauważyłem tego, dzięki. Teraz zmieniłem bibliotekę z reshape2, aby zmienić kształt.Wciąż możesz użyć funkcji reshape2, jeśli chcesz: będziesz musiał dodać argument wzoru z wartością "" do wywołania colsplit(). –

Odpowiedz

3

można przetworzyć każdej zmiennej oddzielnie, i dołącz wynikające dwa data.frames.

# Sample data 
n <- 5 
d <- data.frame(
    id = 1:n, 
    pt1 = sample(c("M","F"),n,replace=TRUE), 
    wt1 = round(runif(n,100,200)), 
    pt2 = sample(c("M","F"),n,replace=TRUE), 
    wt2 = round(runif(n,100,200)), 
    pt3 = sample(c("M","F"),n,replace=TRUE), 
    wt3 = round(runif(n,100,200)) 
) 
# Reshape the data.frame, one variable at a time 
library(reshape2) 
d1 <- melt(d, 
    id.vars="id", measure.vars=c("pt1","pt2","pt3"), 
    variable.name="patient", value.name="gender" 
) 
d2 <- melt(d, 
    id.vars="id", measure.vars=c("wt1","wt2","wt3"), 
    variable.name="patient", value.name="weight" 
) 
d1$patient <- as.numeric(gsub("pt", "", d1$patient)) 
d2$patient <- as.numeric(gsub("wt", "", d1$patient)) 
# Join the two data.frames 
merge(d1, d2, by=c("id","patient"), all=TRUE) 
+0

Dziękuję, to ma sens. Kod jest dłuższy niż wymagany dla stats :: reshape, ale prawdopodobnie warty jest wydajności uzyskanej w przypadku dużej liczby zmiennych, co często ma miejsce w przypadku mnie. –

2

Myślę, że funkcja reshape w pakiecie statystyk jest najprostsza. Oto prosty przykład, czy robi to, co chcesz?

> tmp 
    id val val2 cat 
1 1 1 14 a 
2 1 2 13 b 
3 2 3 12 b 
4 2 4 11 a 
> tmp2 <- tmp 
> tmp2$t <- ave(tmp2$val, tmp2$id, FUN=seq_along) 
> tmp2 
    id val val2 cat t 
1 1 1 14 a 1 
2 1 2 13 b 2 
3 2 3 12 b 1 
4 2 4 11 a 2 
> reshape(tmp2, idvar='id', timevar='t', direction='wide') 
    id val.1 val2.1 cat.1 val.2 val2.2 cat.2 
1 1  1  14  a  2  13  b 
3 2  3  12  b  4  11  a 

Mam nadzieję, że Twoja płeć pacjentów nie zmienia każdą wizytę, ale nie może być inne zmienne kategoryczne, które zmieniają się pomiędzy wizytami

+0

Co miałem na myśli było wielu pacjentów na MD, nie ten sam pacjent mierzony przy wielu okazjach. Zgadzam się jednak, że kod z stats :: reshape jest zdecydowanie bardziej kompaktowy, o ile ktoś jest świadomy potencjalnych błędów: [patrz link] (http://www.mail-archive.com/[email protected]) .org/msg160715.html) –

+0

Tak więc w moim przykładzie użyj id jako identyfikatora lekarza, a wiele wartości reprezentuje pacjentów. –