随机的矢量化并行选择?

时间:2013-07-22 00:28:49

标签: r vectorization random-sample

我有两个矢量“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)

有没有办法在不使用循环的情况下执行此操作?

非常感谢任何建议 感谢

2 个答案:

答案 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)

来自@Arun的

: (相对)更快的实现方法(不需要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, FALSEA, B等。

  • 使用ifelse方法应该有点自我解释。如果为TRUE,则从一个源中选择,如果为FALSE,则从另一个源中选择。

Arun的方法更有创意。他的方法使用相同的“翻转硬币”机制来选择集合,但具有速度的好处。 (我们说纳秒,但仍然)。 他的方法基本上说:

  • 从一个小组开始,比如H.
  • 翻转一枚硬币。
  • 每当硬币是Tails时,用L的相同索引元素替换H的元素。 (请注意,“相同索引”方面是您所称的“并行选择”)

答案 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
相关问题