用 NA 填充矩阵以满足所需的尺寸
Filling matrices with NA to meet desired dimensions
我有一个我创建的矩阵列表。列表中的矩阵具有不同的维度,我想用 NA
s.
填充没有 3x3 维度的矩阵
我在下面列出了我的预期结果。我想将其包含在 if
语句中,如果列表中的矩阵没有 3x3 维度,我想向这些矩阵添加空 columns/rows 并用 NA
。有没有一种在 base r 中执行此操作的有效方法?
# Created Matrices
m1 <- matrix(1:9, 3,3)
m2 <- matrix(1:4, 2,2)
m3 <- matrix(1:3, 3, 1)
# Matrices into a list
l1 <- list(m1, m2, m3)
l1
# Expected Matrices and outputs
m2_new <- matrix(c(1,2,NA,3, 4, rep(NA, 4)), 3,3)
m3_new <- matrix(c(1,2,3,rep(NA, 6)), 3,3)
expected <- list(m1, m2_new, m3_new)
一个选项是创建 NA
matrix
和 replace
具有 'x' 的值,基于 row/col
索引
dummy <- matrix(ncol = 3, nrow = 3)
l2 <- lapply(l1, function(x) replace(dummy, cbind(c(row(x)), c(col(x))), x))
-正在检查
> all.equal(l2, expected)
[1] TRUE
我认为有更好的解决方案,但我的解决方案也可以处理 1x1 矩阵,它实际上只是一个向量。
您可以根据需要在您的代码中使用我在此处 resize_matrix
创建的函数。它非常冗长,但我认为很容易准确地理解它在幕后做了什么。注意:该函数旨在用于 lapply() 调用。
输入:
m1 <- matrix(1:9, 3,3)
m2 <- matrix(1:4, 2,2)
m3 <- matrix(1:3, 3, 1)
m4 <- matrix(1:3, 1, 3)
m5 <- matrix(1, 1, 1)
# Matrices into a list
l1 <- list(m1, m2, m3, m4, m5)
l1
#> [[1]]
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
#>
#> [[2]]
#> [,1] [,2]
#> [1,] 1 3
#> [2,] 2 4
#>
#> [[3]]
#> [,1]
#> [1,] 1
#> [2,] 2
#> [3,] 3
#>
#> [[4]]
#> [,1] [,2] [,3]
#> [1,] 1 2 3
#>
#> [[5]]
#> [,1]
#> [1,] 1
函数:
resize_matrix <- function(mat, desired_rows = 3, desired_columns = 3){
needed_cols <- desired_columns - dim(mat)[2]; needed_cols
needed_rows <- desired_rows - dim(mat)[1]; needed_rows
if (dim(mat)[1] == 1 & dim(mat)[2] == 1){
# we're give a matrix with a single value, expand correctly
final_mat <- matrix(NA, nrow = desired_rows, ncol = desired_columns)
final_mat[1,1] <- mat
} else if (needed_cols > 0 & needed_rows > 0){
# we need to add both rows and columns
col_res <- rep(NA, needed_rows)
row_res <- rep(NA, needed_cols)
mat_temp1 <- rbind(mat, col_res)
final_mat <- unname(cbind(mat_temp1, row_res))
} else if (needed_cols > 0 & needed_rows == 0) {
# we need to add only columns
row_res <- matrix(rep(NA, needed_cols),
ncol = needed_cols, nrow = desired_rows)
final_mat <- unname(cbind(mat, row_res))
} else if (needed_cols == 0 & needed_rows > 0) {
# we need to add only rows
col_res <- matrix(rep(NA, needed_rows),
ncol = desired_columns, nrow = needed_rows)
final_mat <- unname(rbind(mat, col_res))
} else {
# we don't need to add anything, return the matrix
final_mat <- mat
}
return(final_mat)
}
输出:
lapply(l1, FUN = resize_matrix)
#> [[1]]
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
#>
#> [[2]]
#> [,1] [,2] [,3]
#> [1,] 1 3 NA
#> [2,] 2 4 NA
#> [3,] NA NA NA
#>
#> [[3]]
#> [,1] [,2] [,3]
#> [1,] 1 NA NA
#> [2,] 2 NA NA
#> [3,] 3 NA NA
#>
#> [[4]]
#> [,1] [,2] [,3]
#> [1,] 1 2 3
#> [2,] NA NA NA
#> [3,] NA NA NA
#>
#> [[5]]
#> [,1] [,2] [,3]
#> [1,] 1 NA NA
#> [2,] NA NA NA
#> [3,] NA NA NA
由 reprex package (v2.0.1)
于 2022-04-16 创建
您可以用矩阵索引替换矩阵的一部分。
mat <- array(dim = c(3, 3))
lapply(l1, function(x) `[<-`(mat, 1:nrow(x), 1:ncol(x), x))
# [[1]]
# [,1] [,2] [,3]
# [1,] 1 4 7
# [2,] 2 5 8
# [3,] 3 6 9
#
# [[2]]
# [,1] [,2] [,3]
# [1,] 1 3 NA
# [2,] 2 4 NA
# [3,] NA NA NA
#
# [[3]]
# [,1] [,2] [,3]
# [1,] 1 NA NA
# [2,] 2 NA NA
# [3,] 3 NA NA
更新见 Darren Tsai 的评论:
n <- 3
l2 <- lapply(l1, function(x) rbind(x, matrix(ncol = ncol(x), nrow = n - nrow(x))))
x <- sapply(l2, `length<-`, max(lengths(l2)))
list(m1 = matrix(x[,1],3), m2 = matrix(x[,2],3), m3 = matrix(x[,3],3))
$m1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$m2
[,1] [,2] [,3]
[1,] 1 3 NA
[2,] 2 4 NA
[3,] NA NA NA
$m3
[,1] [,2] [,3]
[1,] 1 NA NA
[2,] 2 NA NA
[3,] 3 NA NA
第一个答案:输出不正确:
这是另一种方法:
x <- t(sapply(l1, `length<-`, max(lengths(l1))))
l2 <- list(x[,1:3], x[,4:6], x[,7:9])
l2
[[1]]
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 1 2 3
[3,] 1 2 3
[[2]]
[,1] [,2] [,3]
[1,] 2 2 2
[2,] 4 NA NA
[3,] NA NA NA
[[3]]
[,1] [,2] [,3]
[1,] 3 3 3
[2,] NA NA NA
[3,] NA NA NA
我有一个我创建的矩阵列表。列表中的矩阵具有不同的维度,我想用 NA
s.
我在下面列出了我的预期结果。我想将其包含在 if
语句中,如果列表中的矩阵没有 3x3 维度,我想向这些矩阵添加空 columns/rows 并用 NA
。有没有一种在 base r 中执行此操作的有效方法?
# Created Matrices
m1 <- matrix(1:9, 3,3)
m2 <- matrix(1:4, 2,2)
m3 <- matrix(1:3, 3, 1)
# Matrices into a list
l1 <- list(m1, m2, m3)
l1
# Expected Matrices and outputs
m2_new <- matrix(c(1,2,NA,3, 4, rep(NA, 4)), 3,3)
m3_new <- matrix(c(1,2,3,rep(NA, 6)), 3,3)
expected <- list(m1, m2_new, m3_new)
一个选项是创建 NA
matrix
和 replace
具有 'x' 的值,基于 row/col
索引
dummy <- matrix(ncol = 3, nrow = 3)
l2 <- lapply(l1, function(x) replace(dummy, cbind(c(row(x)), c(col(x))), x))
-正在检查
> all.equal(l2, expected)
[1] TRUE
我认为有更好的解决方案,但我的解决方案也可以处理 1x1 矩阵,它实际上只是一个向量。
您可以根据需要在您的代码中使用我在此处 resize_matrix
创建的函数。它非常冗长,但我认为很容易准确地理解它在幕后做了什么。注意:该函数旨在用于 lapply() 调用。
输入:
m1 <- matrix(1:9, 3,3)
m2 <- matrix(1:4, 2,2)
m3 <- matrix(1:3, 3, 1)
m4 <- matrix(1:3, 1, 3)
m5 <- matrix(1, 1, 1)
# Matrices into a list
l1 <- list(m1, m2, m3, m4, m5)
l1
#> [[1]]
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
#>
#> [[2]]
#> [,1] [,2]
#> [1,] 1 3
#> [2,] 2 4
#>
#> [[3]]
#> [,1]
#> [1,] 1
#> [2,] 2
#> [3,] 3
#>
#> [[4]]
#> [,1] [,2] [,3]
#> [1,] 1 2 3
#>
#> [[5]]
#> [,1]
#> [1,] 1
函数:
resize_matrix <- function(mat, desired_rows = 3, desired_columns = 3){
needed_cols <- desired_columns - dim(mat)[2]; needed_cols
needed_rows <- desired_rows - dim(mat)[1]; needed_rows
if (dim(mat)[1] == 1 & dim(mat)[2] == 1){
# we're give a matrix with a single value, expand correctly
final_mat <- matrix(NA, nrow = desired_rows, ncol = desired_columns)
final_mat[1,1] <- mat
} else if (needed_cols > 0 & needed_rows > 0){
# we need to add both rows and columns
col_res <- rep(NA, needed_rows)
row_res <- rep(NA, needed_cols)
mat_temp1 <- rbind(mat, col_res)
final_mat <- unname(cbind(mat_temp1, row_res))
} else if (needed_cols > 0 & needed_rows == 0) {
# we need to add only columns
row_res <- matrix(rep(NA, needed_cols),
ncol = needed_cols, nrow = desired_rows)
final_mat <- unname(cbind(mat, row_res))
} else if (needed_cols == 0 & needed_rows > 0) {
# we need to add only rows
col_res <- matrix(rep(NA, needed_rows),
ncol = desired_columns, nrow = needed_rows)
final_mat <- unname(rbind(mat, col_res))
} else {
# we don't need to add anything, return the matrix
final_mat <- mat
}
return(final_mat)
}
输出:
lapply(l1, FUN = resize_matrix)
#> [[1]]
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
#>
#> [[2]]
#> [,1] [,2] [,3]
#> [1,] 1 3 NA
#> [2,] 2 4 NA
#> [3,] NA NA NA
#>
#> [[3]]
#> [,1] [,2] [,3]
#> [1,] 1 NA NA
#> [2,] 2 NA NA
#> [3,] 3 NA NA
#>
#> [[4]]
#> [,1] [,2] [,3]
#> [1,] 1 2 3
#> [2,] NA NA NA
#> [3,] NA NA NA
#>
#> [[5]]
#> [,1] [,2] [,3]
#> [1,] 1 NA NA
#> [2,] NA NA NA
#> [3,] NA NA NA
由 reprex package (v2.0.1)
于 2022-04-16 创建您可以用矩阵索引替换矩阵的一部分。
mat <- array(dim = c(3, 3))
lapply(l1, function(x) `[<-`(mat, 1:nrow(x), 1:ncol(x), x))
# [[1]]
# [,1] [,2] [,3]
# [1,] 1 4 7
# [2,] 2 5 8
# [3,] 3 6 9
#
# [[2]]
# [,1] [,2] [,3]
# [1,] 1 3 NA
# [2,] 2 4 NA
# [3,] NA NA NA
#
# [[3]]
# [,1] [,2] [,3]
# [1,] 1 NA NA
# [2,] 2 NA NA
# [3,] 3 NA NA
更新见 Darren Tsai 的评论:
n <- 3
l2 <- lapply(l1, function(x) rbind(x, matrix(ncol = ncol(x), nrow = n - nrow(x))))
x <- sapply(l2, `length<-`, max(lengths(l2)))
list(m1 = matrix(x[,1],3), m2 = matrix(x[,2],3), m3 = matrix(x[,3],3))
$m1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$m2
[,1] [,2] [,3]
[1,] 1 3 NA
[2,] 2 4 NA
[3,] NA NA NA
$m3
[,1] [,2] [,3]
[1,] 1 NA NA
[2,] 2 NA NA
[3,] 3 NA NA
第一个答案:输出不正确: 这是另一种方法:
x <- t(sapply(l1, `length<-`, max(lengths(l1))))
l2 <- list(x[,1:3], x[,4:6], x[,7:9])
l2
[[1]]
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 1 2 3
[3,] 1 2 3
[[2]]
[,1] [,2] [,3]
[1,] 2 2 2
[2,] 4 NA NA
[3,] NA NA NA
[[3]]
[,1] [,2] [,3]
[1,] 3 3 3
[2,] NA NA NA
[3,] NA NA NA