R:从矩阵每一行中随机抽取元素

ryoqjall  于 2023-03-10  发布在  其他
关注(0)|答案(3)|浏览(113)

有人能帮我优化我对矩阵每一行的随机值进行采样的方法吗?
到目前为止,我有两种方法:

volume <- matrix(rnorm(10000), 100, 100)
microbenchmark(
  
  test <- apply(volume, 1, function(x) {sample(x, 1)}),
  # make matrix into a vector, sample one time for all rows at the same time,
  # and then add 0, 100, 200 ...  to each sample
  test2 <- c(t(volume))[sample(x=1:ncol(volume), size=nrow(volume), replace=T) + seq(from=0, by=ncol(volume), length.out=nrow(volume))] 
)
5jvtdoz2

5jvtdoz21#

您可以使用2列矩阵为矩阵编制索引,以便第一列是行的选择器,第二列是列的选择器。
例如:

index <- matrix(c(1, 4, 1, 3), ncol = 2)
index
     [,1] [,2]
[1,]    1    1
[2,]    4    3
matrix(c(1:15), ncol = 3)
     [,1] [,2] [,3]
[1,]    1    6   11
[2,]    2    7   12
[3,]    3    8   13
[4,]    4    9   14
[5,]    5   10   15
matrix(c(1:15), ncol = 3)[index]
[1]  1 14

应用相同的原理,我们可以创建一个索引矩阵,其中第一列为每行(1:100),第二列为从1到100的随机整数,以选择随机列。

test3 <- volume[matrix(c(1:100, sample.int(100, 100, replace = TRUE)), nrow = 100)]

它看起来快了一点,可能是因为R中的矢量化,但我还没有足够的力量告诉。我希望这对你有帮助或给你其他的想法!

yvgpqqbh

yvgpqqbh2#

另一种方法:

n <- 100
v <- as.vector(t(volume))
s <- (1:n) * n - sample(1:n, n, replace = T) + 1
v[s]

测试用例

使用更小的矩阵和易于理解的数字

n <- 10

volume <- matrix(1:(n*n), n, n)

v <- as.vector(t(volume))
s <- (1:n) * n -  sample(1:n, n, replace = T) + 1
v[s]

[1] 41 12 53  4 15 26 47 88 89 80

我们可以很容易地逐行交叉检查,我们有一个来自随机列的值。
我使用了rbenchmark here

test replications elapsed relative user.self sys.self user.child sys.child
1 test1        10000   10.39    8.731      9.80     0.50         NA        NA
2 test2        10000    1.53    1.286      0.98     0.53         NA        NA
3 v[s]         10000    1.19    1.000      0.84     0.34         NA        NA
fwzugrvs

fwzugrvs3#

您可以尝试将sample.intcbind结合使用,如下所示

> volume[cbind(sample.int(nrow(volume)), seq(ncol(volume)))] + 100 * (seq(nrow(volume)) - 1)
  [1]   -1.224613   98.512540  200.945185  301.154825  398.633888  500.537326
  [7]  599.296667  699.875739  801.979633  901.943536 1000.485389 1101.245489
 [13] 1199.927407 1300.614396 1401.376295 1499.845985 1600.325472 1700.827938
 [19] 1800.848768 1898.982145 1999.513529 2099.892262 2200.420631 2300.353487
 [25] 2400.006175 2499.805057 2601.976288 2698.841332 2801.744629 2900.781041
 [31] 3001.973210 3100.717182 3202.547228 3299.413149 3400.251934 3500.411278
 [37] 3600.147031 3700.617010 3799.195733 3899.599753 3999.305972 4100.592828
 [43] 4199.306696 4298.941681 4400.608532 4500.866239 4601.324509 4698.683332
 [49] 4800.558514 4898.423218 4998.912282 5099.734288 5200.426110 5299.556283
 [55] 5398.069062 5499.971494 5599.574838 5701.268051 5799.335310 5899.293448
 [61] 5999.440561 6100.137712 6200.173128 6300.441285 6399.531312 6499.438840
 [67] 6600.213682 6700.742909 6801.688150 6900.652646 7001.198283 7099.355430
 [73] 7198.598821 7297.607903 7400.581176 7501.050185 7601.602181 7698.798794
 [79] 7796.995970 7898.064790 7999.908998 8102.625282 8198.114373 8300.538023
 [85] 8398.521912 8500.918616 8599.469763 8699.102379 8798.473842 8899.133405
 [91] 9000.673422 9100.615656 9199.422079 9300.055959 9400.128205 9499.914517
 [97] 9600.943887 9698.741291 9799.654779 9900.996018

相关问题