【问题标题】:How to assign a set of numbers randomly to a matrix in R with no row with all the same elements如何将一组数字随机分配给R中的矩阵,其中没有包含所有相同元素的行
【发布时间】:2018-06-10 23:41:50
【问题描述】:

我想创建一个 n 行 m 列的随机矩阵。我希望从一组数字中随机选择矩阵每一行的元素。我想在每一行中至少有一个不同的数字。我不希望一行的所有元素都相同。我曾经问过我的问题here,但我不知道为什么我提供的功能仍然给我一些包含所有相同元素的行。如何调整此功能?

f2 <- function(x, n, m) {
if ( length(unique(x)) == 1 ) {
    stop('x has only one unique element.', call. = FALSE)
}
result <- t(replicate(n, sample(x, m, replace = TRUE)))
while ( any(apply(result, 1, function(x) length(unique(result)) == 1)) ) {
    result <- t(replicate(n, sample(x, m, replace = TRUE)))
}
return(result)}

这是一个例子:

x <- c(1, 1.5, 2, 3,4)
set.seed(123456)
matall=f2(x, 1200, 4)
View(matall)

      [,1] [,2] [,3] [,4]
   [1,]  3.0  3.0  1.5  1.5
   [2,]  1.5  1.0  2.0  1.0
   [3,]  4.0  1.0  3.0  2.0
   [4,]  4.0  4.0  4.0  4.0

【问题讨论】:

  • 请看示例中的第 4 行。所有元素都是 4。我不希望这种情况发生。我希望至少有一个元素连续不同。

标签: r matrix


【解决方案1】:

函数定义中有错字。 while 子句应为

while ( any(apply(result, 1, function(x) length(unique(x)) == 1)) ) {

而不是

while ( any(apply(result, 1, function(x) length(unique(result)) == 1)) ) {

但是,该函数不会很快终止,因为它会在每次找到具有相同值的行时尝试重新创建整个矩阵。

改进后的版本只替换具有相同值的行

f3 <- function(x, n, m) {
  if ( length(unique(x)) == 1 ) {
    stop('x has only one unique element.', call. = FALSE)
  }
  result <- replicate(m, sample(x, n, replace = TRUE))
  uni_rows <- apply(result, 1, function(x) length(unique(x)) == 1)
  while ( any(uni_rows) ) {
    result[which(uni_rows), ] <- replicate(m, sample(x, sum(uni_rows), replace = TRUE))
    uni_rows <- apply(result, 1, function(x) length(unique(x)) == 1)
  }
  return(result)
}

现在,

x <- c(1, 1.5, 2, 3, 4)
set.seed(123456)
matall <- f3(x, 1200, 4)
any(apply(matall, 1, function(x) length(unique(x)) == 1))
[1] FALSE

返回

head(matall, 11)
      [,1] [,2] [,3] [,4]
 [1,]  3.0    3  1.5  1.5
 [2,]  1.5    1  2.0  1.0
 [3,]  4.0    1  3.0  2.0
 [4,]  2.0    4  3.0  1.0
 [5,]  4.0    1  1.5  3.0
 [6,]  4.0    3  2.0  3.0
 [7,]  2.0    3  4.0  4.0
 [8,]  4.0    1  2.0  4.0
 [9,]  1.5    1  4.0  1.0
[10,]  4.0    4  3.0  3.0
[11,]  1.5    3  4.0  1.5

【讨论】:

  • 非常感谢。有用。由于本网站的政策,我不喜欢您的回答。
  • @Fate 你需要至少 15 的声望才能投票。但是您可以通过单击所选答案的复选标记符号来接受您认为对解决您的问题最有用的答案之一。接受将为您带来额外的 +2 声望点。
【解决方案2】:

我想创建一个 n 行 m 列的随机矩阵。

cols <- 3; rows <- 3
m <- matrix(ncol = cols, nrow = rows)

我希望随机选择矩阵每一行的元素 来自一组数字。

set.seed(2)
set <- seq(ncol(m)-1L)
m[] <- sample(set, length(m), replace = T)
m
#      [,1] [,2] [,3]
# [1,]    1    1    1
# [2,]    2    2    2
# [3,]    2    2    1

我希望每行至少有一个不同的数字。

rowRanges <- matrixStats::rowRanges(m)
(isSingle <- rowRanges[,2]-rowRanges[,1]==0)
# [1]  TRUE  TRUE FALSE

m[isSingle,1] <- vapply(rowRanges[isSingle, 1], function(x) set[set!=x][1], 0L)
m
#      [,1] [,2] [,3]
# [1,]    2    1    1
# [2,]    1    2    2
# [3,]    2    2    1

或者,如果您想根据要选择的设置值和列来随机分配:

vsample <- Vectorize(function(x) sample(set[set!=x], size = 1L), "x")
idx <- cbind(row=which(isSingle), col=sample(ncol(m), sum(isSingle), replace = TRUE))
mvals <- vsample(rowRanges[isSingle, 1])
m[idx] <- mvals

【讨论】:

  • 我将 set 更改为 set=c(1,2,3,4),后来出现此错误:“vapply(rowRanges[isSingle, 1], function(x) set[set ! = x], 0L) :值的长度必须为 1,但 FUN(X[[1]]) 结果的长度为 3"
  • @Fate 我的错,例如set[set!=x][1] 确保 vapply 只取 1 个值(在这种情况下,第一个不是行中的值)。
  • 非常感谢。有用。由于本网站的政策,我不喜欢您的回答
猜你喜欢
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 2022-08-17
  • 1970-01-01
  • 2018-08-01
相关资源
最近更新 更多