在0/1矩阵内进行采样

时间:2017-10-24 17:23:33

标签: r matrix sampling

我有$ N $ x $ N $矩阵$ G $由零和1组成。我想重新采样来自伯努利分布的$ G $中的那些,其中概率$ p $沿原点变化。我们的想法是用独立的伯努利变量实现替换$ G $中的所有。我在 R 中试过这个:

for(i in 1:N){ 
for(j in 1:N){ 
G[i,j] <- ifelse(G[i,j] == 1,rbinom(1,1,p[i]),0)}} 

但是,对于计算时间,最好避免使用for循环。有人会知道如何以矩阵形式写这个吗?非常感谢你!

2 个答案:

答案 0 :(得分:1)

利用R回收向量及其面向列的存储。我会在展示一个解决方案后解释。

#
# Generate a 0/1 matrix `G` for testing.
#
N <- 1e3
G <- matrix(rbinom(N^2, 1, 1/2), N)
#
# Generate the vector of probabilities for testing.
#
p <- runif(N)
#
# Here is a solution.
#
U <- runif(N*N) <= p # Random 0/1 values
G.0 <- G * U         # Conditionally replace elements of G

runif函数为G中的每个条目生成一个统一变量。将它与向量p进行比较会产生0个值为0/1的N个向量(1表示为真,0表示为假),所有这些值都串在一起,其中位置i,i + N,i + 2N的预期频率为1, ...,i +(N-1)N由p[i]的值给出i = 1,2,...,N。当在最后一行乘以G时,当旧值为零或新值为0时,新值为零,这是期望的结果,因为内部G的值也是逐列布局的。

此解决方案比原来的双循环快约20倍。它避免了条件执行的缓慢(ifelse),并利用任何内部并行性和R基本操作的优化(runif<=和{{ 1}})。你支付一个(相对较小的)价格:需要RAM存储这些随机结果(这里显式放入数组*)。

答案 1 :(得分:0)

如果不使用Python,请使用Numpy:

import numpy as np
G = np.array([[0,1,0,0], [0,0,0,1], [0,1,1,0], [1,1,1,1]])  
# This constructs G row-by-row 
probs = np.array([0.1, 0.2, 0.3, 0.4])  # Replace with your row-wise probabilities
samples = np.random.binomial(n=1, p=probs, size=(4,4))  # Binomial with n=1 is Bernoulli
desired_matrix = np.multiply(G, samples)

np.multiply函数以元素方式乘以数组,因此零条目保持为零,1个条目乘以0或1,具体取决于np.random.binomial返回的实现。一个棘手的问题是,我相信 Numpy足够聪明,可以在指定probs时将size中的每个概率广播到右行,但我不确定因为docs没有提到它。