按宽度对向量进行分类

Bin a vector by width

我有一个连续变量向量。例如:

x <- c(0.9000000,  1.2666667,  4.0000000,  5.7333333, 19.7333333, 35.7666667, 44.0000000,  4.4333333,  0.4666667,  0.7000000,  0.9333333,  1.0000000,  1.0000000,  1.0000000,  1.2000000,  1.2333333, 1.2666667,  1.4333333,  1.7000000,  4.0666667,  1.9000000,  2.1000000,  0.9333333,  1.2666667,  3.7333333,  0.9333333,  2.7666667,  3.1333333,  3.9333333,  5.0333333,  6.0666667,  8.2333333)

我想按宽度(相等数量的值)将此向量分成三组(低值、中值和高值)。 因此,low 组的值将在所有总值中排名倒数第三。

然后我想对低和中容器进行分组,这样我就会有一个分类向量,其中包含 Not high 个主题,最低 66%,最高 33%。

我已经检查过,但找不到任何预定义函数来执行此操作。

您可以使用 cut 拆分和标记数值向量。本质上,您正在寻找一个等于 x 有序值的 2/3 的值的单个断点,因此您可以执行以下操作:

break_point <- sort(x)[round(2 * length(x)/3)]

break_point
#> [1] 3.733333

任何高于 3.733333 的值都将是 'high'。所以我们可以这样做:

y <- cut(x, breaks = c(-Inf, break_point, Inf), labels = c('not high', 'high'))

如果我们将其放入具有 x 的数据框中,您可以看到 y 适当地标记了最高值:

data.frame(x, y)
#>             x        y
#> 1   0.9000000 not high
#> 2   1.2666667 not high
#> 3   4.0000000     high
#> 4   5.7333333     high
#> 5  19.7333333     high
#> 6  35.7666667     high
#> 7  44.0000000     high
#> 8   4.4333333     high
#> 9   0.4666667 not high
#> 10  0.7000000 not high
#> 11  0.9333333 not high
#> 12  1.0000000 not high
#> 13  1.0000000 not high
#> 14  1.0000000 not high
#> 15  1.2000000 not high
#> 16  1.2333333 not high
#> 17  1.2666667 not high
#> 18  1.4333333 not high
#> 19  1.7000000 not high
#> 20  4.0666667     high
#> 21  1.9000000 not high
#> 22  2.1000000 not high
#> 23  0.9333333 not high
#> 24  1.2666667 not high
#> 25  3.7333333 not high
#> 26  0.9333333 not high
#> 27  2.7666667 not high
#> 28  3.1333333 not high
#> 29  3.9333333     high
#> 30  5.0333333     high
#> 31  6.0666667     high
#> 32  8.2333333     high

你可以看到大约 2/3 的案例是 'not high' 和 1/3 是 'high':

table(y) / length(x)
#> y
#> not high     high 
#>  0.65625  0.34375 

你不能在 'not high' 组中恰好有 2/3,因为你的矢量长度为 32,不能被 3 整除。

您可以使用 quantile():

y <- ifelse(x < quantile(x, 2/3), "not high", "high")

proportions(table(y))

#     high not high 
#  0.34375  0.65625 

您可以使用 santoku::chop_equally():

library(santoku)
chopped <- santoku::chop_equally(x, 3, labels = c("low", "medium", "high"))
data.frame(x, chopped)
            x chopped
1   0.9000000     low
2   1.2666667  medium
3   4.0000000    high
4   5.7333333    high
5  19.7333333    high
6  35.7666667    high
7  44.0000000    high
8   4.4333333    high
9   0.4666667     low
10  0.7000000     low
...

然后您可以重新组合因子(如果您想保留 low/medium/high 版本):

library(forcats)
chopped2 <- forcats::fct_collapse(chopped, 
                                    "High" = "high", 
                                     other_level = "Not high"
                                  )
data.frame(x, chopped2)
            x chopped2
1   0.9000000 Not high
2   1.2666667 Not high
3   4.0000000     High
4   5.7333333     High
5  19.7333333     High
6  35.7666667     High
7  44.0000000     High
8   4.4333333     High
9   0.4666667 Not high
10  0.7000000 Not high
...

或者,如果您只想要“高”/“不高”版本,请使用 chop_quantiles():

chopped2 <- santoku::chop_quantiles(x, .66, 
                                    labels = c("Not high", "High"))
data.frame(x, chopped2)
            x chopped2
1   0.9000000 Not high
2   1.2666667 Not high
3   4.0000000     High
4   5.7333333     High
5  19.7333333     High
6  35.7666667     High
7  44.0000000     High
8   4.4333333     High
9   0.4666667 Not high
10  0.7000000 Not high
...

你说你想按“宽度(相等数量的值)”进行分箱。上述 bins 的值数量相等,即 3 个类别中每个类别的 1/3。如果你想按宽度分箱,即进入 equal-width 间隔,请使用 santoku::chop_evenly():

chopped3 <- santoku::chop_evenly(x, 3, labels = c("low", "medium", "high"))
data.frame(x, chopped3)
            x chopped3
1   0.9000000      low
2   1.2666667      low
3   4.0000000      low
4   5.7333333      low
5  19.7333333   medium
6  35.7666667     high
7  44.0000000     high
8   4.4333333      low
9   0.4666667      low
10  0.7000000      low
...

注意:我是 santoku 包的维护者。