将连续变量拆分为具有相同数量元素的组 - 从bin值返回数值向量

时间:2016-09-19 15:12:24

标签: r

我有一个连续变量,我希望将其拆分为二进制数,返回一个数值向量(长度等于我的原始向量),其值与二进制值的值相关。每个bin应该具有大致相同数量的元素。

这个问题:splitting a continuous variable into equal sized groups描述了相关情况的一些技巧。例如,如果我从

开始
x = c(1,5,3,12,5,6,7)

我可以使用cut()来获取:

cut(x, 3, labels = FALSE)
[1] 1 2 1 3 2 2 2

这是不可取的,因为因子的值只是连续的整数,它们与我的向量中的基础原始值没有直接关系。

另一种可能性是cut2:例如:

library(Hmisc)
cut2(x, g = 3, levels.mean = TRUE)
[1] 3.5 3.5 3.5 9.5 3.5 6.0 9.5

这更好,因为现在返回值与箱的值有关。从那以后它仍然不太理想:

  • (a)它产生一个因子,然后需要将其转换为数字(参见e.g.),这既慢又笨拙。
  • (b)理想情况下,我希望能够选择是否使用间隔的顶端或底端,而不仅仅是手段。

我知道还有一些选项可以使用正则表达式从cutcut2返回因子来获取区间的顶点或底点。这些看起来过于繁琐。

这只是一种需要一些不那么优雅的黑客攻击的情况吗?或者,是否有一些更容易实现的功能?

我目前的最佳努力如下:

MyDiscretize = function(x, N_Bins){
    f = cut2(x, g = N_Bins, levels.mean = TRUE)
    return(as.numeric(levels(f))[f])
}

我的目标是找到更快,更优雅,更容易适应使用任何一个端点的东西,而不仅仅是手段。

修改:

澄清一下:我想要的输出是:

  • (a)与我在cut2示例中可以实现的内容相同,但不需要将因子转换为数字。

  • (b)如果可能,还可以轻松选择使用间隔的任何一个端点,而不是中点。

2 个答案:

答案 0 :(得分:1)

也许不是很优雅,但应该是高效的。试试这个功能:

myCut<-function(x,breaks,retValues=c("means","highs","lows")) {
    retValues<-match.arg(retValues)
    if (length(breaks)!=1) stop("breaks must be a single number")
    breaks<-as.integer(breaks)
    if (is.na(breaks)||breaks<2) stop("breaks must greater than or equal to 2") 
    intervals<-seq(min(x),max(x),length.out=breaks+1)
    bins<-findInterval(x,intervals,all.inside=TRUE)
    if (retValues=="means") return(rowMeans(cbind(intervals[-(breaks+1)],intervals[-1]))[bins])
    if (retValues=="highs") return(intervals[-1][bins]) 
    intervals[-(breaks+1)][bins]
}
x = c(1,5,3,12,5,6,7)
myCut(x,3)
#[1]  2.833333  6.500000  2.833333 10.166667  6.500000  6.500000  6.500000
myCut(x,3,"highs")
#[1]  4.666667  8.333333  4.666667 12.000000  8.333333  8.333333  8.333333
myCut(x,3,"lows")
#[1] 1.000000 4.666667 1.000000 8.333333 4.666667 4.666667 4.666667

答案 1 :(得分:1)

像这样使用x = c(1,5,3,12,5,6,7)

假设:

ave(x,cut2(x,g = 3), FUN = mean)
[1] 3.5 3.5 3.5 9.5 3.5 6.0 9.5

平均:

ave(x,cut2(x,g = 3), FUN = min)
[1] 1 1 1 7 1 6 7

敏:

ave(x,cut2(x,g = 3), FUN = max)
[1]  5  5  5 12  5  6 12

最大:

ave(x,cut2(x,g = 3), FUN = sd)
[1] 1.914854 1.914854 1.914854 3.535534 1.914854       NA 3.535534

或标准差:

cut2

请注意区间内只有一个数据点的NA结果。

希望这就是你所需要的。

注意:
cut中的参数g是分位数组的数量。组可能没有相同数量的数据点,并且间隔可能不具有相同的长度 另一方面,<option value="<?php echo $status['status'].' by '.$staff['name'].' '.$staff['surname']; ?>">Set to <?php echo ucwords($status['status']); ?> </option> 将间隔分成几个相等的长度。