这是一个由两部分组成的问题:第一个是创建一个NXN方阵,每行中只有一个随机元素为1,其他项必须为零。 (即每行中元素的总和为1)。
第二种是创建一个NXN方阵,每行的项目总和为1,但每个元素都遵循一个分布,例如:正态分布。
相关问题包括(Create a matrix with conditional sum in each row -R) Matlab似乎自动完成了我想做的事情(Why this thing happens with random matrix such that all rows sum up to 1?),但我正在寻找r中的解决方案。
以下是我的尝试:
# PART 1
N <- 50
x <- matrix(0,N,N)
lapply(1:N, function(y){
x[y,sample(N,1)]<- 1
})
(我还是零)
# PART 2
N <- 50
x <- matrix(0,N,N)
lapply(1:N, function(y){
x[y,]<- rnorm(N)
})
(需要扩展)
答案 0 :(得分:2)
这是另一个使用"[<-"
函数的两列寻址工具的无环解决方案。这将创建一个双列索引矩阵,其第一列只是一个升序系列,用于指定行位置,第二列(负责选择列位置的列)是一个随机整数值。 (这是马修“最简单的方法”的矢量化版本,我怀疑会更快,因为只有一次调用sample
。):
M <- matrix(0,N,N)
M[ cbind(1:N, sample(1:N, N, rep=TRUE))] <- 1
> rowSums(M)
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
如果你没有指定rep=TRUE
,那么colSums(M)也会一直都是,但那不是你要求的。它确实意味着你得到的矩阵的秩可能小于N.如果你遗漏了rep=TRUE
矩阵将是满级。
答案 1 :(得分:1)
在这里,您了解为什么lapply
并不总是替换循环。您正在尝试遍历x
行并修改矩阵,但您要修改的是来自全局环境的x
的副本。
最简单的解决方法是使用for
循环:
for (y in 1:N) {
x[y,sample(N,1)]<- 1
}
apply
系列应该用于返回值,而不是带有副作用的编程函数。
执行此操作的方法是返回行,然后将rbind
它们返回到矩阵中。这里显示了第二个示例,因为它更像apply
:
do.call(rbind, lapply((1:N), function(i) rnorm(N)))
然而,这更具可读性:
matrix(rnorm(N*N), N, N)
现在缩放它以使行总和等于1.您使用矩阵是面向列的并且向量被回收的事实,这意味着您可以将矩阵M
除以rowSums(M)
。使用更合理的N=5
:
m <- matrix(rnorm(N*N), N, N)
m/rowSums(m)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.1788692 0.5398464 0.24980924 -0.01282655 0.04430168
## [2,] 0.4176512 0.2564463 0.11553143 0.35432975 -0.14395871
## [3,] 0.3480568 0.7634421 -0.38433940 0.34175983 -0.06891932
## [4,] 1.1807180 -0.0192272 0.16500179 -0.31201400 -0.01447859
## [5,] 1.1601173 -0.1279919 -0.07447043 0.20865963 -0.16631458
答案 2 :(得分:0)
无循环解决方案:)
n <- 5
# on which column in each row insert 1s
s <- sample(n,n,TRUE)
# indexes for each row
w <- seq(1,n*n,by=n)-1
index <- s+w
# vector of 0s
vec <- integer(n*n)
# put 1s
vec[index] <- 1
# voila :)
matrix(vec,n,byrow = T)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 0 0 0
[2,] 0 0 0 1 0
[3,] 0 0 0 0 1
[4,] 1 0 0 0 0
[5,] 1 0 0 0 0