2009-08-11 22 views
8

Tutaj robię nową kolumnę, aby wskazać, czy Mydata jest powyżej lub poniżej medianyJak wykonać medianę podziału na poziomy czynników w R?

### MedianSplits based on Whole Data 
#create some test data 
myDataFrame=data.frame(myData=runif(15),myFactor=rep(c("A","B","C"),5)) 

#create column showing median split 
myBreaks= quantile(myDataFrame$myData,c(0,.5,1)) 
myDataFrame$MedianSplitWholeData = cut(
    myDataFrame$myData, 
    breaks=myBreaks, 
    include.lowest=TRUE, 
    labels=c("Below","Above")) 

#Check if it's correct 
myDataFrame$AboveWholeMedian = myDataFrame$myData > median(myDataFrame$myData) 
myDataFrame 

działa dobrze. Teraz chcę zrobić to samo, ale oblicz medianę podziału na każdym poziomie myFactor.

mam wymyślić to:

#Median splits within factor levels 
byOutput=by(myDataFrame$myData,myDataFrame$myFactor, function (x) { 
    myBreaks= quantile(x,c(0,.5,1)) 
    MedianSplitByGroup=cut(x, 
     breaks=myBreaks, 
     include.lowest=TRUE, 
     labels=c("Below","Above")) 
    MedianSplitByGroup 
    }) 

byOutput zawiera to, co chcę. Kategoryzuje on prawidłowo każdy element czynników A, B i C. Jednak chciałbym utworzyć nową kolumnę, myDataFrame $ FactorLevelMedianSplit, która pokazuje nowo obliczony medianowy podział.

Jak przekonwertować dane wyjściowe polecenia "by" do użytecznej kolumny danych?

myślę, być może "na" polecenie nie jest R-podobny sposób to zrobić ...

Aktualizacja:

Z przykład Thierry jak używać współczynnika() sprytnie i po odkrywając funkcję "ave" w książce Spectora, znalazłem to rozwiązanie, które nie wymaga żadnych dodatkowych pakietów.

myDataFrame$MediansByFactor=ave(
    myDataFrame$myData, 
    myDataFrame$myFactor, 
    FUN=median) 

myDataFrame$FactorLevelMedianSplit = factor(
    myDataFrame$myData>myDataFrame$MediansByFactor, 
    levels = c(TRUE, FALSE), 
    labels = c("Above", "Below")) 
+0

Opakowanie bez opakowania jest piękne - dzięki! – Amyunimus

Odpowiedz

3

Oto rozwiązanie z wykorzystaniem pakietu plyr.

myDataFrame <- data.frame(myData=runif(15),myFactor=rep(c("A","B","C"),5)) 
library(plyr) 
ddply(myDataFrame, "myFactor", function(x){ 
    x$Median <- median(x$myData) 
    x$FactorLevelMedianSplit <- factor(x$myData <= x$Median, levels = c(TRUE, FALSE), labels = c("Below", "Above")) 
    x 
}) 
+0

To działało świetnie. Zobacz także aktualizację postu, aby uzyskać sposób bez opakowania. –

1

Oto sposób hack-owski. Hadley mogą pochodzić z czegoś bardziej eleganckiego:

zacząć, prosty złączyć wyjście by:

R> do.call(c,byOutput) 
A1 A2 A3 A4 A5 B1 B2 B3 B4 B5 C1 C2 C3 C4 C5 
1 2 2 1 1 1 1 2 1 2 1 2 1 1 2 

i liczy, że mamy poziomy współczynnik 1 i 2 tutaj, które możemy wykorzystać do re-index nowy czynnik z tych poziomów:

R> c("Below","Above")[do.call(c,byOutput)] 
[1] "Below" "Above" "Above" "Below" "Below" "Below" "Below" "Above" 
[8] "Below" "Above" "Below" "Above" "Below" "Below" "Above" 
R> as.factor(c("Below","Above")[do.call(c,byOutput)]) 
[1] Below Above Above Below Below Below Below Above Below Above 
[11] Below Above Below Below Above 
Levels: Above Below 

które możemy następnie przypisać do data.frame chcesz zmodyfikować:

R> myDataFrame$FactorLevelMedianSplit <- 
     as.factor(c("Below","Above")[do.call(c,byOutput)]) 

Aktualizacja : Nieważne, musielibyśmy ponownie zindeksować myDataFrame, aby je posortować A A ... A B ... B C ... C, zanim dodamy nową kolumnę. Pozostawione jako ćwiczenie ...

Powiązane problemy