我有两个矢量“H”和“L”,它们有200个数值。我想创建一个名为“HL”的第三个向量,它包含来自H和L的200个随机样本。但是,我希望它们能够并行选择,就像pmin和pmax函数一样。
简化示例:
H <- 1:5
L <- 6:10
# rbind(H,L)
# [,1] [,2] [,3] [,4] [,5]
# H 1 2 3 4 5
# L 6 7 8 9 10
# intended result is then a random pick from each 'column' shown above, e.g:
HL <- c(6,2,8,4,10)
有没有办法在不使用循环的情况下执行此操作?
非常感谢任何建议 感谢
答案 0 :(得分:7)
您需要来自bernouli(即0或1)分布的N个样本,其中N
是H / L中的值的数量。然后使用采样分别从H或L中选取。使用ifelse
可确保您需要的“并行选择”。
set.seed(1)
N <- length(H)
HorL <- rbinom(N, 1, 0.5)
# the select
results <- ifelse(HorL, H, L)
results
# [1] 6 7 3 4 10
ifelse( rbinom(H, 1, 0.5), H, L)
:
(相对)更快的实现方法(不需要ifelse
)将是:
idx <- which(!as.logical(rbinom(H, 1, 0.5)))
vv <- H
vv[idx] <- L[idx]
@Gabriel,我们的想法是你从两个选项中选择一个。您可以有效地翻转硬币,如果是头部,则从H中选择,如果是尾部,则从L中选择。这是伯努利分布,更一般的形式是二项分布。 R有一个提供随机数量的时尚设施。
因此我们向R询问其中许多N
,然后相应地从H或L中选择。
“select from ..”部分是R
诡计。
请注意,我们可以将0, 1
视为TRUE, FALSE
或A, B
等。
使用ifelse
方法应该有点自我解释。如果为TRUE,则从一个源中选择,如果为FALSE,则从另一个源中选择。
Arun的方法更有创意。他的方法使用相同的“翻转硬币”机制来选择集合,但具有速度的好处。 (我们说纳秒,但仍然)。 他的方法基本上说:
答案 1 :(得分:-1)
library(data.table)
set.seed(1350)
# Create an example data table:
dt <- data.table(ID=1:200,H=sample(1:1000,200),L=sample(1001:2000,200),key="ID")
# (If you already have a data frame 'df', you can use):
# dt <- as.data.table(df)
set.seed(5655)
# Add a column that randomly samples between H and L:
dt[,HL:=sample(c(H,L),1),by=ID]
dt
# ID H L HL
# 1: 1 837 1391 1391
# 2: 2 999 1573 1573
# 3: 3 566 1275 566
# 4: 4 347 1709 1709
# 5: 5 129 1627 129
# ---
#196: 196 67 1879 1879
#197: 197 652 1811 1811
#198: 198 569 1160 1160
#199: 199 17 1026 17
#200: 200 221 1500 1500
编辑2:
如评论中所指出的,如果H有重复,我的初始答案将给出不正确的值。我添加的时间显示data.table
更快,但是当我更正答案时,它确实变得更慢,正如评论中所建议的那样。 (错误的答案更快,因为它是按重复值进行分组,因此需要考虑的行数要少得多......)
简而言之,我错了,你可能会对另一个答案感觉更好。
这是一个合适的基准:
set.seed(1350)
H <- sample(1:200, 200)
L <- sample(201:400, 200)
usingDataTable <- quote({
dt <- data.table(H, L)
dt[,HL:=sample(c(H,L),1),by=H]
})
dt2 <- data.table(H, L)
usingDataTable.NoInitialize <- quote({
dt2[,HL:=sample(c(H,L),1),by=H]
})
usingVectors <- quote ({
ifelse( rbinom(H, 1, 0.5), H, L)
})
microbenchmark(eval(usingVectors), eval(usingDataTable), eval(usingDataTable.NoInitialize), times=100L)
Unit: microseconds
expr min lq median uq max neval
eval(usingVectors) 55.021 61.148 66.760 69.4605 1682.163 100
eval(usingDataTable) 1635.676 1745.437 1795.245 1851.0950 3629.179 100
eval(usingDataTable.NoInitialize) 1458.573 1537.618 1596.237 1669.3750 3683.756 100