10

在这里,我创建一个新列来指示 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 的方式来做到这一点......

更新

通过 Thierry 关于如何巧妙使用 factor() 的示例,以及在 Spector 的书中发现“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"))
4

3 回答 3

4

这是使用 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
})
于 2009-08-11T14:22:44.977 回答
1

这是一种hack-ish方式。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 以排序 AA ... AB ... BC ... C 。作为练习离开...

于 2009-08-11T12:37:03.577 回答
0

你不是在寻找这样的东西,是吗?

Course$grade2 <- ifelse(Course$grade >= median(Course$grade), 1, 0)
于 2020-02-12T03:35:55.693 回答