Объединение матриц чередующимися столбцами
Я ищу общий подход для объединения двух матриц, так что столбцы из двух исходных матриц чередуются в новой матрице
col1m1... col1m2... col2m1... col2m2... col3m1... col3m2......
например:
matrix.odd <- matrix(c(rep(1,3),rep(3,3),rep(5,3)),nrow=3,ncol=3)
matrix.even <- matrix(c(rep(2,3),rep(4,3),rep(6,3)),nrow=3,ncol=3)
# would look like
matrix.combined <- matrix(c(rep(1,3),rep(2,3),rep(3,3),rep(4,3),rep(5,3),rep(6,3)),
nrow=3,ncol=6)
Я ищу общий подход, потому что у меня будут матричные комбинации с более чем тремя столбцами. Я пробовал некоторые из циклов и некоторых if-операторов, но для меня это не собиралось. Поиски сочетания матриц с тасованием и чередованием также не подтвердились. Есть предположения?
Ответы
Ответ 1
rows.combined <- nrow(matrix.odd)
cols.combined <- ncol(matrix.odd) + ncol(matrix.even)
matrix.combined <- matrix(NA, nrow=rows.combined, ncol=cols.combined)
matrix.combined[, seq(1, cols.combined, 2)] <- matrix.odd
matrix.combined[, seq(2, cols.combined, 2)] <- matrix.even
Ответ 2
Smth, как это должно делать:
m <- cbind(matrix.odd, matrix.even) # combine
m <- m[, c(matrix(1:ncol(m), nrow = 2, byrow = T))] # then reorder
Еще один вариант для развлечения:
matrix(rbind(matrix.odd, matrix.even), nrow = nrow(matrix.odd))
И играть в игру многих матриц:
weave = function(...) {
l = list(...)
matrix(do.call(rbind, l), nrow = nrow(l[[1]]))
}
Ответ 3
alternate.cols <- function(m1, m2) {
cbind(m1, m2)[, order(c(seq(ncol(m1)), seq(ncol(m2))))]
}
identical(matrix.combined, alternate.cols(matrix.odd, matrix.even))
# [1] TRUE
который также делает правильную вещь (субъективную), если m1
и m2
имеют различное количество столбцов:
alternate.cols(matrix.odd, matrix.even[, -3])
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 2 3 4 5
# [2,] 1 2 3 4 5
# [3,] 1 2 3 4 5
Легко обобщить на любое число матриц:
alternate.cols <- function(...) {
l <- list(...)
m <- do.call(cbind, l)
i <- order(sequence(sapply(l, ncol)))
m[, i]
}
Ответ 4
Вы можете превратиться в трехмерный массив, а затем транспонировать...
arr <- array( c(m1,m2) , dim = c(dim(m1),2) )
matrix( aperm( arr , c(1,3,2) ) , nrow(m1) )
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 1 2 3 4 5 6
[3,] 1 2 3 4 5 6
И как функция, универсальная для многих матриц...
bindR <- function(...){
args <- list(...)
dims <- c( dim(args[[1]]) , length(args) )
arr <- array( unlist( args ) , dim = dims )
matrix( aperm( arr , c(1,3,2) ) , dims[1] )
}
bindR(m1,m2,m1,m2)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
#[1,] 1 2 1 2 3 4 3 4 5 6 5 6
#[2,] 1 2 1 2 3 4 3 4 5 6 5 6
#[3,] 1 2 1 2 3 4 3 4 5 6 5 6
Ответ 5
Скорее всего, это будет более сжатый способ сделать это. Если матрицы большие, вам, скорее всего, придется искать более эффективный метод.
# Test data
(X <- matrix(1:16, nrow=4, ncol=4))
(Y <- matrix(-16:-1, nrow=4, ncol=4))
# Set indices for the new matrix
X.idx <- seq(1, ncol(X)*2, by=2)
Y.idx <- seq(2, ncol(Y)*2+1, by=2)
# Column bind the matrices and name columns according to the indices
XY <- cbind(X, Y)
colnames(XY) <- c(X.idx, Y.idx)
# Now order the columns
XY[, order(as.numeric(colnames(XY)))]