R 在应用于向量的函数中使用ifelse和随机变量生成

R 在应用于向量的函数中使用ifelse和随机变量生成,r,random,R,Random,我想创建一个函数,根据输入生成一个随机数,并将其应用于布尔向量。该功能将用于生成约500M元素的测试数据 f <- function(x, p) ifelse(x, runif(1)^p, runif(1)^(1/p)) f(c(T,T,T,F,F,F), 2) 我希望输入向量的每个元素都有一个新的随机数,而不是两个重复的随机数。为什么我会得到这个结果,我如何才能得到与之相同的期望结果 c(runif(3)^2, runif(3)^(1/2)) 为每个元素生成一个新的随机数 0.

我想创建一个函数,根据输入生成一个随机数,并将其应用于布尔向量。该功能将用于生成约500M元素的测试数据

f <- function(x, p) ifelse(x, runif(1)^p, runif(1)^(1/p))
f(c(T,T,T,F,F,F), 2)   
我希望输入向量的每个元素都有一个新的随机数,而不是两个重复的随机数。为什么我会得到这个结果,我如何才能得到与之相同的期望结果

c(runif(3)^2, runif(3)^(1/2))
为每个元素生成一个新的随机数

0.0774 0.7071 0.2184 0.8719 0.9990 0.8819

您需要创建两个不同的随机数向量,其长度与
x
-向量相同

 f <- function(x, p) ifelse(x, runif(6)^p, runif(6)^(1/p))
 f(c(T,T,T,F,F,F), 2)   
 [1] 0.3040201 0.5543376 0.7291466 0.5205014 0.3563542 0.8697398

f@bondedust的答案是正确的(即,
ifelse()
并没有真正循环),但效率稍低——它会根据需要对随机均匀偏差进行两倍的采样(在实践中,除非使用一个巨大的向量或大量运行函数,否则这不会有多大关系)。这里有一个稍微高效的版本,它通过power(
^
)操作符进行矢量化:

set.seed(1001)
f <- function(x, p=2) {
    rvec <- runif(length(x))
    rvec^(ifelse(x, p, 1/p))
}
## best to avoid the T/F shortcut ...
test <-  c(TRUE,TRUE,TRUE,FALSE,FALSE,FALSE)
f(test, 2) 
。。。布莱恩·里普利:“太慢了”原文如此:在你保存的7米比赛中,你打算做什么


f_bb@Frank yours是目前为止最好的解决方案。太好了,谢谢您的详细介绍。@Frank函数的速度大约是前者的两倍。使用microbenchmark和2M矢量宏进行测试。(让您的问题陈述您用例的大致维度(例如,典型向量长度、重复次数)确实有助于您了解优化过程中的困难程度……对于500米,根据您需要运行它的次数,可能值得探索
Rcpp
解决方案。。。
f <- function(x, p) ifelse(x, runif( length(x) )^p, runif( length(x) )^(1/p))
set.seed(1001)
f <- function(x, p=2) {
    rvec <- runif(length(x))
    rvec^(ifelse(x, p, 1/p))
}
## best to avoid the T/F shortcut ...
test <-  c(TRUE,TRUE,TRUE,FALSE,FALSE,FALSE)
f(test, 2) 
fortunes::fortune("7ms")
f_bb <- f
f_bd <- function(x, p=2)
    ifelse(x, runif( length(x) )^p, runif( length(x) )^(1/p))
f_frank <- function(x,p=2) runif(length(x))^(p^(2*x-1))
library("rbenchmark")
benchmark(f_bb(test),f_bd(test),f_frank(test),replications=10000,
         columns=c("test","replications","elapsed","relative"))
##            test replications elapsed relative
## 1    f_bb(test)        10000   0.161    2.516
## 2    f_bd(test)        10000   0.199    3.109
## 3 f_frank(test)        10000   0.064    1.000