从矩阵的每一行随机采样

时间:2019-02-19 01:23:58

标签: r

给出一个5x5矩阵:

dataset=matrix(cbind(c(1,1,2,2,0),
                     c(1,1,2,0,0),
                     c(0,0,0,1,0),
                     c(0,0,1,1,1),
                     c(1,2,3,4,0))
dataset
      [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    0    0    1
[2,]    1    1    0    0    2
[3,]    2    2    0    1    3
[4,]    2    0    1    1    4
[5,]    0    0    0    1    0

我想从矩阵的每一行采样1个观察值,其中该行要采样的值等于1,并且我想创建一个新矩阵,在其中将随机采样的值设置为True新矩阵和所有其他值均设置为false。预期输出示例如下:

       1     2     3     4     5  
1   FALSE  TRUE FALSE FALSE FALSE 
2    TRUE FALSE FALSE FALSE FALSE
3   FALSE FALSE FALSE  TRUE FALSE 
4   FALSE FALSE  TRUE FALSE FALSE 
5   FALSE FALSE FALSE  TRUE FALSE 

有人可以帮助我弄清楚如何实现这一目标。

3 个答案:

答案 0 :(得分:2)

这是一个选择

# Courtesy of Hadley (avoids the "surprise" sample result when we have only one element)
# [http://r.789695.n4.nabble.com/using-quot-sample-quot-for-a-vector-of-length-1-td2299330.html]
resample <- function(x, ...) x[sample.int(length(x), ...)]

set.seed(2019)
t(apply(dataset, 1, function(x) 
    replace(rep(FALSE, length(x)), resample(which(x == 1), 1), TRUE)))
#      [,1]  [,2]  [,3]  [,4]  [,5]
#[1,] FALSE FALSE FALSE FALSE  TRUE
#[2,] FALSE  TRUE FALSE FALSE FALSE
#[3,] FALSE FALSE FALSE  TRUE FALSE
#[4,] FALSE FALSE FALSE  TRUE FALSE
#[5,] FALSE FALSE FALSE  TRUE FALSE

我添加了一个固定的随机种子以提高可重复性;删除以从1的每一行中随机采样dataset


样本数据

dataset=matrix(
    c(1,1,2,2,0,1,1,2,0,0,0,0,0,1,0,0,0,1,1,1,1,2,3,4,0),
    nrow = 5, ncol = 5)
dataset
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    1    0    0    1
#[2,]    1    1    0    0    2
#[3,]    2    2    0    1    3
#[4,]    2    0    1    1    4
#[5,]    0    0    0    1    0

答案 1 :(得分:1)

如果我理解了请求,那么这应该是一个有效的答案:

(dataset==1) * rbinom(length(dataset), 1, 0.5)

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    1
[2,]    0    1    0    0    0
[3,]    0    0    0    1    0
[4,]    0    0    0    1    0
[5,]    0    0    0    1    0

我的理解是,您只想在与原始矩阵中的1相同的位置上找到TRUE(或等价于1),但是只有其中一些随机样本才是TRUE(或1)

答案 2 :(得分:1)

我可以通过列出所有等于1的单元格的大方法,然后为每一行采样一个并更新矩阵的副本来解决这个问题。像这样:

idx <- which(dataset==1, arr.ind=TRUE)
idx <- idx[sample(nrow(idx)),]
idx <- idx[!duplicated(idx[,"row"]),]
mat <- matrix(FALSE, nrow=nrow(dataset), ncol=ncol(dataset))
mat[idx] <- TRUE

mat
#      [,1]  [,2]  [,3]  [,4]  [,5]
#[1,] FALSE  TRUE FALSE FALSE FALSE
#[2,]  TRUE FALSE FALSE FALSE FALSE
#[3,] FALSE FALSE FALSE  TRUE FALSE
#[4,] FALSE FALSE  TRUE FALSE FALSE
#[5,] FALSE FALSE FALSE  TRUE FALSE

这也将很好地扩展。在大约2.5秒内处理了500万行:

dataset <- dataset[rep(1:5,1e6),]
system.time({
idx <- which(dataset==1, arr.ind=TRUE)
idx <- idx[sample(nrow(idx)),]
idx <- idx[!duplicated(idx[,"row"]),]
mat <- matrix(FALSE, nrow=nrow(dataset), ncol=ncol(dataset))
mat[idx] <- TRUE
})
#   user  system elapsed 
#   2.32    0.22    2.58