我想生成一个介于0和1之间但不在.4和.6之间的随机数。在R中有没有比以下更好的方法了?
sample(c(runif(1,0,.4), runif(1,.6,1)), 1, prob=c(.5,.5))
答案 0 :(得分:3)
类似于TC Zhang,但快了大约3倍(因为ifelse
慢):
mysample_axe <- function(n = 1){
tmp <- runif(n, max = 0.8)
tmp + (tmp > 0.4) * 0.2
}
与TC Zhang(mysample
)和Cath(samp_runif
)的比较:
microbenchmark::microbenchmark(mysample(1e5), mysample_axe(1e5), samp_runif(1e5))
Unit: milliseconds expr min lq mean median uq max neval cld mysample(1e+05) 12.684764 13.193528 17.313560 13.420470 19.692859 130.23693 100 c mysample_axe(1e+05) 4.897770 5.159778 5.751177 5.187718 5.218367 14.60607 100 a samp_runif(1e+05) 7.615363 8.101890 9.266797 8.139951 8.194121 25.44451 100 b
ggplot2::qplot(mysample_axe(1e5), breaks = I(seq(0, 1, 0.02)))
答案 1 :(得分:2)
从任何分布中抽样随机数的基本思想是inverse transform sampling。
mysample <- function(n = 1){
tmp <- runif(n)
ifelse (tmp > 0.5, 0.8 * tmp + 0.2, 0.8 * tmp)
}
library(ggplot2)
## A density plot for confirmation
df <- data.frame(x= mysample(1000000))
gg <- ggplot(df, aes(x=x)) +
geom_density()
gg
由reprex package(v0.2.0.9000)于2018-07-10创建。
答案 2 :(得分:2)
您可以对[0,1]上的均匀分布进行采样,直到使用递归函数得到一个遵循约束的数字(比@Axeman解慢约两倍):
samp_runif <- function(n){
x <- runif(n, 0, 1)
wh_pb <- which(x>0.4 & x<0.6)
if(length(wh_pb)){x[wh_pb] <- samp_runif(length(wh_pb)) ; return(x)} else return(x)
}
samp_runif(5)
# [1] 0.3633319 0.9586853 0.6766313 0.6903275 0.8090996
可视化:
test <- samp_runif(1e6)
plot(density(test))
概括:
您可以调整上述功能以将阈值(在示例中为0.4和0.6)作为参数,上下限相同(在示例中分别为0和1):
samp_runif <- function(n, a=0.4, b=0.6){
x <- runif(n, 0, 1)
wh_pb <- which(x>a & x<b)
if(length(wh_pb)){x[wh_pb] <- samp_runif(length(wh_pb), a=a, b=b) ; return(x)} else return(x)
}
samp_runif(5, 0.2, 0.8)
#[1] 0.80316178 0.99624724 0.89554995 0.05928052 0.17771131
答案 3 :(得分:0)
是的,这个想法是完全荒谬的,所以我删除了它。感谢Axeman的有用反馈。
这是另一个想法(这次经过了更好的测试):
fx <- function() {y <- runif(1); if (y > 0.4 & y < 0.6) fx() else y}
除了校正0.4和0.6之间的值外,只需获取另一个即可。