如何从每个因素的 data.table 行中抽取随机子样本?
How to take a random subsample from rows of a data.table per factor?
我正在尝试创建一个大数据集的子样本,其中每个因素都有不同的 n。我希望能够非常快地执行此操作,因为我已经执行了数十万次。你能帮我用 data.tables 优化这个过程吗?
我现在做的是将 "rownumber" rn
添加到 data.table,使用各种 n 对其进行采样,然后基于它进行子集。我认为一定有更聪明的方法来做到这一点,但我似乎无法弄清楚。
# generate data.table
DT <- data.table(rn = 1:100, factor = letters[1:3],
value = rnorm(100, c(1, 5, 10)))
# subset based on "row number" with various numbers per category
subsetrn <- DT[, .(rn = sample(rn,
if (factor == "a") 12
else if (factor == "b") 20
else if (factor == "c") 5
else NULL, replace = TRUE)),
by = factor]
# subset
ss <- DT[rn %in% subsetrn[, rn]]
编辑:我见过这种从 data.table 中快速采样的方法,但它不是按因子进行的:
我还看到了如何对每个因素进行等量处理的技巧,但不是对每个因素进行不同量处理的技巧。
EDIT2:我一直在研究@akron 的解决方案,但仍然遇到问题:
如果我有一个因子为 0,则有问题:
# generate data.table
DT <- data.table(factor = letters[1:4],
value = rnorm(300, c(1, 5, 10)))
# subset based on "row number" with various numbers per category subsetrn
# index data table with numbers
id <- data.table(factor = letters[1:4], val = c(12, 20, 5, 0))
# map our DT onto it, then subsample by the new val
ssid <- DT[id, on = .(factor)][, sample(.I, val[1], replace = TRUE), factor]
# subset
ss <- DT[ssid[, V1]]
count(ss[, factor])
## x freq
## 1 a 10
## 2 b 12
## 3 c 5
## 4 d 10
# this is wrong! It only works if I do it like this
ss <- DT[id, on = .(factor)][ssid[, V1]]
我希望能够获得 ssid,这样我就可以 DT[ssid[, V1]]
(或 DT[ssid]
),这样我就可以通过引用来做所有事情,而不是制作 DT 的本地副本.在我的应用程序中,这一切都包含在一个函数中,该函数当前复制 DT 的一小部分 50k 次,耗时约 25 分钟。该函数对子集执行一些计算,然后返回输出。这很慢,我想弄清楚是否可以通过某种方式引用它。
这个问题现在可能变得有点太具体了 ;-)。
我们可以加入 key/value 数据集并使用 .I
到 sample
DT[DT[data.table(factor = letters[1:3], val = c(12, 20, 5)),
on = .(factor)][, sample(.I, val[1], replace = TRUE), factor]$V1]
如果我们把它分成几部分-
data.table(factor = letters[1:3], val = c(12, 20, 5))
是一个 key/value data.table
,通过加入 on
'factor` 将 'val' 作为原始数据集的列。
第二步,我们做joining
DT[data.table(factor = letters[1:3], val = c(12, 20, 5)),
on = .(factor)]
现在,我们 sample
行索引,按 'factor' 分组,指定 size
作为 'val' 的第一个元素,提取行索引列 $V1
并使用它来对原始数据集进行子集化。即
DT[....$V1]
我正在尝试创建一个大数据集的子样本,其中每个因素都有不同的 n。我希望能够非常快地执行此操作,因为我已经执行了数十万次。你能帮我用 data.tables 优化这个过程吗?
我现在做的是将 "rownumber" rn
添加到 data.table,使用各种 n 对其进行采样,然后基于它进行子集。我认为一定有更聪明的方法来做到这一点,但我似乎无法弄清楚。
# generate data.table
DT <- data.table(rn = 1:100, factor = letters[1:3],
value = rnorm(100, c(1, 5, 10)))
# subset based on "row number" with various numbers per category
subsetrn <- DT[, .(rn = sample(rn,
if (factor == "a") 12
else if (factor == "b") 20
else if (factor == "c") 5
else NULL, replace = TRUE)),
by = factor]
# subset
ss <- DT[rn %in% subsetrn[, rn]]
编辑:我见过这种从 data.table 中快速采样的方法,但它不是按因子进行的: 我还看到了如何对每个因素进行等量处理的技巧,但不是对每个因素进行不同量处理的技巧。
EDIT2:我一直在研究@akron 的解决方案,但仍然遇到问题:
如果我有一个因子为 0,则有问题:
# generate data.table
DT <- data.table(factor = letters[1:4],
value = rnorm(300, c(1, 5, 10)))
# subset based on "row number" with various numbers per category subsetrn
# index data table with numbers
id <- data.table(factor = letters[1:4], val = c(12, 20, 5, 0))
# map our DT onto it, then subsample by the new val
ssid <- DT[id, on = .(factor)][, sample(.I, val[1], replace = TRUE), factor]
# subset
ss <- DT[ssid[, V1]]
count(ss[, factor])
## x freq
## 1 a 10
## 2 b 12
## 3 c 5
## 4 d 10
# this is wrong! It only works if I do it like this
ss <- DT[id, on = .(factor)][ssid[, V1]]
我希望能够获得 ssid,这样我就可以 DT[ssid[, V1]]
(或 DT[ssid]
),这样我就可以通过引用来做所有事情,而不是制作 DT 的本地副本.在我的应用程序中,这一切都包含在一个函数中,该函数当前复制 DT 的一小部分 50k 次,耗时约 25 分钟。该函数对子集执行一些计算,然后返回输出。这很慢,我想弄清楚是否可以通过某种方式引用它。
这个问题现在可能变得有点太具体了 ;-)。
我们可以加入 key/value 数据集并使用 .I
到 sample
DT[DT[data.table(factor = letters[1:3], val = c(12, 20, 5)),
on = .(factor)][, sample(.I, val[1], replace = TRUE), factor]$V1]
如果我们把它分成几部分-
data.table(factor = letters[1:3], val = c(12, 20, 5))
是一个 key/value data.table
,通过加入 on
'factor` 将 'val' 作为原始数据集的列。
第二步,我们做joining
DT[data.table(factor = letters[1:3], val = c(12, 20, 5)),
on = .(factor)]
现在,我们 sample
行索引,按 'factor' 分组,指定 size
作为 'val' 的第一个元素,提取行索引列 $V1
并使用它来对原始数据集进行子集化。即
DT[....$V1]