我知道如何为一个变量做到这一点。我们可以使用 equal.count() 或 quantile() 和 cut() 的组合。有人知道一个聚合函数可以同时为 100 列执行此操作吗?
我知道我可以写一个循环,但它很慢。有更快的方法吗?因为我正在研究一个大数据问题,所以也欢迎使用革命 R 的可能解决方案。提前谢谢!
澄清一下:我试图将每一列分成 20 个范围,而不仅仅是第一列。我不是试图拆分数据集,而是试图将变量转换为不同的范围。希望它澄清。十分感谢
我知道如何为一个变量做到这一点。我们可以使用 equal.count() 或 quantile() 和 cut() 的组合。有人知道一个聚合函数可以同时为 100 列执行此操作吗?
我知道我可以写一个循环,但它很慢。有更快的方法吗?因为我正在研究一个大数据问题,所以也欢迎使用革命 R 的可能解决方案。提前谢谢!
澄清一下:我试图将每一列分成 20 个范围,而不仅仅是第一列。我不是试图拆分数据集,而是试图将变量转换为不同的范围。希望它澄清。十分感谢
使用 cut2() 中的 g 参数来选择将变量切割成的中断。
require(data.table)
require(Hmisc)
set.seed(123)
DT <- data.table(x1 = rnorm(10e5, 50, 50),
x2 = rnorm(10e5, 30, 50),
x3 = rnorm(10e5, 20, 50),
x4 = rnorm(10e5, 10, 50),
x5 = rnorm(10e5, 10, 50)
)
cut_qt <- DT[,sapply(.SD, function(x) if(is.numeric(x)) cut2(x, g = 4)), ]
print(cut_qt)
head(cut_qt)
x1 x2 x3 x4 x5
[1,] "[ 16.3, 50.0)" "[-199.6, -3.8)" "[ -13.7, 20.0)" "[ -23.8, 10.0)" "[ -23.74, 9.97)"
[2,] "[ 16.3, 50.0)" "[ 63.6,257.4]" "[ 20.0, 53.7)" "[-218.7,-23.8)" "[-222.34,-23.74)"
[3,] "[ 83.7,292.5]" "[ -3.8, 29.9)" "[ -13.7, 20.0)" "[ 43.7,247.6]" "[ -23.74, 9.97)"
[4,] "[ 50.0, 83.7)" "[ 63.6,257.4]" "[ -13.7, 20.0)" "[ 10.0, 43.7)" "[-222.34,-23.74)"
[5,] "[ 50.0, 83.7)" "[ 29.9, 63.6)" "[-232.5,-13.7)" "[ 10.0, 43.7)" "[-222.34,-23.74)"
[6,] "[ 83.7,292.5]" "[ 29.9, 63.6)" "[-232.5,-13.7)" "[ 43.7,247.6]" "[ -23.74, 9.97)"
由于考虑到 OP 正在处理大型数据集,这很慢:
> system.time(DT[,lapply(.SD, function(x) if(is.numeric(x)) cut2(x, g = 4)), ])
user system elapsed
37.66 0.00 38.70
使用 set() 的替代方法
# 1) Calculate Quantiles
q <- DT[,sapply(.SD, function(x) if(is.numeric(x)) quantile(x)), ]
q
x1 x2 x3 x4 x5
0% -189.95953 -199.574605 -232.54139 -218.74362 -222.343247
25% 16.28067 -3.797748 -13.72424 -23.76578 -23.736187
50% 49.98701 29.938932 20.01473 10.03740 9.967671
75% 83.66663 63.614604 53.74529 43.73047 43.676887
100% 292.53835 257.368361 280.64704 247.64500 277.418083
# 2) Modify the existing DT with the categorical variables using set
cols_to_fix <- names(DT)
for (j in 1:length(cols_to_fix)){
column <- cols_to_fix[j]
brk = q[,j]
val = cut2(DT[[column]], cuts = brk)
set(DT, i=NULL, j=j, value = val)
}
system.time(for (j in 1:length(cols_to_fix)){
column <- cols_to_fix[j]
brk = q[,j]
val = cut2(DT[[column]], cuts = brk)
set(DT, i=NULL, j=j, value = val)
}
)
user system elapsed
4.71 0.00 4.83
新版本:
制作一个 20 列 100 行的数据框:
df <- as.data.frame(replicate(20, sample(1:100)))
按该列的十分位数分割每一列;这会产生一个 10 x 20 尺寸的二维列表:
pieces <- vapply(df, function(x) split(x, cut(x, quantile(x, (0:10)/10))), vector("list", 10))
您可以使用矩阵符号来访问内容
pieces[[2, 1]]
# [1] 20 12 14 16 11 19 17 13 18 15
您使用revolution-r
了标签,所以我假设您正在运行 Revolution R。如果您的数据是 Revolution XDF 格式,您可以使用 RevoEnhancements包中的 rxDiscretize 。它一次为数据集中的所有变量创建分箱,并生成一个对象,您可以将其用作 rxDataStep 函数中的转换。从帮助页面:
library(RevoEnhancements)
# Equal Freq
discTransforms <- rxDiscretize(~ cost,
data = claimsXdf,
type = "freq",
nBins = 1000,
subscript = "disc",
sep = "_")
x <- rxDataStep(inData = claimsXdf, transforms = discTransforms)