在 R data.table 中具有外部指定四分位数断点的四分位数排序器

Quartile sorter with externally specified quartile breakpoints in R data.table

我想根据变量 "varbl" 将观察结果分类为四分位数。由于我的数据非常大 (2Gb),我正在尝试通过 data.table 来实现它。问题是我需要使用特定于组的外部四分位数。组变量为 "prd" 或 "prd1".

我的数据和断点如下:

data <- data.table(id = c(1,2,3,4,5,1,2,3,4,5), prd1 = c(1,1,1,1,1,2,2,2,2,2), varbl = c(-1.6, -0.7, 0.1, 1.2, -0.5, -0.8, 0.4, 1.2, 1.9, 4))
bks <- data.table(prd=c(1,2), br0 = c(-5,-5), br1=c(-1,0), br2=c(0, 0.5), br3=c(1, 3), br4=c(5,5))
 > data
    id prd1 varbl
 1:  1    1  -1.6
 2:  2    1  -0.7
 3:  3    1   0.1
 4:  4    1   1.2
 5:  5    1  -0.5
 6:  1    2  -0.8
 7:  2    2   0.4
 8:  3    2   1.2
 9:  4    2   1.9
10:  5    2   4.0
> bks
   prd br0 br1 br2 br3 br4
1:   1  -5  -1 0.0   1   5
2:   2  -5   0 0.5   3   5

期望的输出是:

> output
    id prd1 varbl ntile
 1:  1    1  -1.6     1
 2:  2    1  -0.7     2
 3:  3    1   0.1     3
 4:  4    1   1.2     4
 5:  5    1  -0.5     2
 6:  1    2  -0.8     1
 7:  2    2   0.4     2
 8:  3    2   1.2     3
 9:  4    2   1.9     3
10:  5    2   4.0     4

我尝试了以下代码,但它失败了,因为我无法在与来自数据的当前 prd1 相同的 prd 上对 bks 进行子集化:

data[, ntile := cut(varbl, breaks = bks[prd==prd1], include.lowest=TRUE, labels = 1:4)]

作为另一种尝试,我尝试先加入数据和 bks(我不想这样做,因为它会将数据的大小从 2Gb 增加到 4Gb) 然后将观察结果分类为分位数。它失败了,因为我不明白如何使用列名为每一行构造一个断点向量。 None 次尝试成功。

setnames(data, "prd1", "prd")
data <- data[bks, on="prd", nomatch=0]
data[, ntile := cut(varbl, breaks = .(br0, br1, br2, br3, br4), include.lowest=TRUE, labels=1:4)]
data[, ntile := cut(varbl, breaks = colnames(bks)[-1], include.lowest=TRUE, labels=1:4)]
data[, ntile := cut(varbl, breaks = c("br0", "br1", "br2", "br3", "br4"), include.lowest=TRUE, labels=1:4)]

稍微重新排列 bks 意味着您可以将其作为一个连接来执行此操作:

bks <- bks[, data.frame(embed(unlist(.SD),2)[,2:1]), by=prd]
bks[, grp := seq_len(.N), by=prd]

#   prd   X1   X2 grp
#1:   1 -5.0 -1.0   1
#2:   1 -1.0  0.0   2
#3:   1  0.0  1.0   3
#4:   1  1.0  5.0   4
#5:   2 -5.0  0.0   1
#6:   2  0.0  0.5   2
#7:   2  0.5  3.0   3
#8:   2  3.0  5.0   4

data[bks, on=c("prd1"="prd","varbl>=X1","varbl<X2"), grp := i.grp]

#    id prd1 varbl  grp
# 1:  1    1  -1.6    1
# 2:  2    1  -0.7    2
# 3:  3    1   0.1    3
# 4:  4    1   1.2    4
# 5:  5    1  -0.5    2
# 6:  1    2  -0.8    1
# 7:  2    2   0.4    2
# 8:  3    2   1.2    3
# 9:  4    2   1.9    3
#10:  5    2   4.0    4