2009-08-11 7 views
8

Здесь я делаю новый столбец, чтобы указать, является ли MyData выше или ниже среднего штрафаКак сделать срединные расщепления в пределах уровней факторов в 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 

работ. Теперь я хочу сделать то же самое, но вычислить медианные расщепления в каждом уровне myFactor.

Я придумал это:

#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 содержит то, что я хочу. Он правильно классифицирует каждый элемент факторов A, B и C. Однако я бы хотел создать новый столбец myDataFrame $ FactorLevelMedianSplit, который отображает недавно вычисленный срединный раскол.

Как вы преобразовываете вывод команды «by» в полезный столбец данных?

Я думаю, что, возможно, «по» команда не R-подобный способ сделать это ...

Update:

С примера Тьерри о том, как использовать фактор() умно, и на открывая функцию «ave» в книге Спектора, я нашел это решение, которое не требует дополнительных пакетов.

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

Непакетное решение для этого красиво - спасибо! – Amyunimus

ответ

3

Вот решение, использующее пакет 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

Это отлично работало. См. Также обновление для сообщения для без упаковки. –

1

Это хак-иш-путь. Hadley может прийти с чем-то более элегантным:

Чтобы начать, мы просто сцепить 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 

и, что важно, что мы получаем уровни фактора 1 и 2 здесь, которые мы можем использовать для повторного индексирования новый фактор с этими уровнями:

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 

, который мы можем назначить в data.frame вы хотите изменить:

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

Обновление: Не важно, нам нужно переиндексировать myDataFrame для сортировки A A ... A B ... B C ... C, а также добавить новый столбец. Оставленный как упражнение ...

Смежные вопросы