Как сделать срединное расщепление в пределах уровней факторов в R? - PullRequest
8 голосов
/ 11 августа 2009

Здесь я создаю новый столбец, чтобы указать, выше или ниже myData его медиана

### 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» в полезный столбец фрейма данных?

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

Обновление

На примере Тьерри о том, как грамотно использовать factor (), и после обнаружения функции «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"))

Ответы [ 2 ]

3 голосов
/ 11 августа 2009

Вот решение с использованием пакета 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
})
1 голос
/ 11 августа 2009

Вот способ взлома. Хэдли может прийти с чем-то более элегантным:

Для начала просто объединяем вывод 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, а также добавить новый столбец. Оставлено как упражнение ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...