有没有办法在R中生成0和1的矩阵以满足特定的行和列总数?

时间:2017-06-14 18:16:15

标签: r matrix

我想生成一个7列×10行矩阵,总共有20个随机生成的1,但每行至少有两个1和每列两个1。我怎么能这样做?

另外,如果我想设置一系列可接受的行和列总数而不是最小值,代码会有什么不同?

谢谢!

2 个答案:

答案 0 :(得分:3)

我觉得应该有一个更优雅的解决方案,但这是一个胶带球:

matbuilder <- function(n,nrow,ncol) {
  finished <- F
  while(!finished) {
    trial <- matrix(sample(c(rep(1,n),rep(0,nrow*ncol-n))),nrow=nrow,ncol=ncol)
    if(all(rowSums(trial)>=2 & all(colSums(trial)>=2))) finished <- T
  }
  return(trial)
}

x <- matbuilder(20, 10, 7)

x
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7]
##  [1,]    1    1    0    0    0    0    0
##  [2,]    0    0    0    0    1    0    1
##  [3,]    0    1    0    0    0    1    0
##  [4,]    1    0    0    0    1    0    0
##  [5,]    0    1    0    0    0    1    0
##  [6,]    0    0    1    1    0    0    0
##  [7,]    0    0    1    1    0    0    0
##  [8,]    0    0    0    0    1    0    1
##  [9,]    0    0    0    0    0    1    1
## [10,]    0    1    1    0    0    0    0

sum(x)
## [1] 20

rowSums(x)
##  [1] 2 2 2 2 2 2 2 2 2 2

colSums(x)
## [1] 2 4 3 2 3 3 3

或者,给出一系列可接受的行/列总数......

matbuilder <- function(n,nrow,ncol,rowmin,rowmax,colmin,colmax,ntimeout=100000) {
  finished <- F
  i <- 1
  trial <- NA
  while(!finished) {
    trial <- matrix(sample(c(rep(1,n),rep(0,nrow*ncol-n))),nrow=nrow,ncol=ncol)
    if(all(rowSums(trial)>=rowmin) & all(rowSums(trial)<=rowmax) & all(colSums(trial)>=colmin) & all(colSums(trial)<=colmax)) finished <- T
    i <- i+1
    if(i>ntimeout) {
      finished <- T
      cat("sorry boss, timeout.")
    }
  }
  return(trial)
}

x <- matbuilder(25,10,7,rowmin=2,rowmax=3,colmin=2,colmax=4)

x
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7]
##  [1,]    1    0    0    0    0    1    1
##  [2,]    0    1    1    0    0    0    1
##  [3,]    1    0    0    0    1    0    0
##  [4,]    1    0    1    1    0    0    0
##  [5,]    1    0    0    0    0    1    1
##  [6,]    0    1    1    1    0    0    0
##  [7,]    0    0    0    1    0    0    1
##  [8,]    0    0    1    0    1    0    0
##  [9,]    0    0    0    1    1    0    0
## [10,]    0    0    0    0    1    1    0

sum(x)
## [1] 25

rowSums(x)
##  [1] 3 3 2 3 3 3 2 2 2 2

colSums(x)
## [1] 4 2 4 4 4 3 4

答案 1 :(得分:2)

这个涉及对索引矩阵进行采样,使得每行重复两次并且列重复至少2次。

set.seed(42)
m = matrix(rep(0, 70), nrow = 10)

#Sample rows 1-10 twice
rows = sample(c(1:10, 1:10))

#Sample columns 1-7 twice and additional 6 to make 20
columns = sample(c(sample(1:7, 6, replace = TRUE), 1:7, 1:7))

#Create a matrix of indices that should be 1
inds = cbind(rows, columns)

#Remove duplicates in inds if any (Refer: https://stackoverflow.com/q/44555420/7128934)
inds[,2] = replace(x = inds[,2],
        list = duplicated(inds),
        values = sample(x = columns[!(columns %in% inds[,2][duplicated(inds)])],
                        size = 1))
m[inds] = 1

#Check
rowSums(m)
#[1] 2 2 2 2 2 2 2 2 2 2
colSums(m)
#[1] 4 2 2 3 2 2 5
sum(m)
#[1] 20