In R, considering a generic matrix A, how can I move the triangle NA to the position in matrix B? What about if the matrix is m x n?
> A <- matrix(c(3, NA, NA, 4, 2, NA, 1, 5, 3), nrow = 3)
> A
[,1] [,2] [,3]
[1,] 3 4 1
[2,] NA 2 5
[3,] NA NA 3
> B <- matrix(c(3, 2, 3, 4, 5, NA, 1, NA, NA), nrow = 3)
> B
[,1] [,2] [,3]
[1,] 3 4 1
[2,] 2 5 NA
[3,] 3 NA NA
Thanks!
I don't know if there's a more idiomatic way, but this seems to do what you want:
A <- matrix(c(3, NA, NA, 4, 2, NA, 1, 5, 3), nrow = 3)
A
[,1] [,2] [,3]
[1,] 3 4 1
[2,] NA 2 5
[3,] NA NA 3
t(apply(A, 1, function(x) x[order(is.na(x))]))
[,1] [,2] [,3]
[1,] 3 4 1
[2,] 2 5 NA
[3,] 3 NA NA
A <- matrix(c(3, NA, NA, NA, 4, 2, NA, NA, 1, 5, 3, NA), nrow=4)
A
[,1] [,2] [,3]
[1,] 3 4 1
[2,] NA 2 5
[3,] NA NA 3
[4,] NA NA NA
t(apply(A, 1, function(x) x[order(is.na(x))]))
[,1] [,2] [,3]
[1,] 3 4 1
[2,] 2 5 NA
[3,] 3 NA NA
[4,] NA NA NA
A <- matrix(c(3, NA, NA, 4, 2, NA, 1, 5, 3, 6, 7, 8), nrow=3)
A
[,1] [,2] [,3] [,4]
[1,] 3 4 1 6
[2,] NA 2 5 7
[3,] NA NA 3 8
t(apply(A, 1, function(x) x[order(is.na(x))]))
[,1] [,2] [,3] [,4]
[1,] 3 4 1 6
[2,] 2 5 7 NA
[3,] 3 8 NA NA
A possible way is to rotate 180 over columns. I assumed that the NA triangle from A is used to set NA in matrix B after rotation. One can use the same technique to rotate in A matrix itself.
A <- matrix(c(3, NA, NA, 4, 2, NA, 1, 5, 3), nrow = 3)
A
[,1] [,2] [,3]
[1,] 3 4 1
[2,] NA 2 5
[3,] NA NA 3
B <- matrix(c(3, 2, 3, 4, 5, 4, 1, 6, 8), nrow = 3)
B
[,1] [,2] [,3]
[1,] 3 4 1
[2,] 2 5 6
[3,] 3 4 8
#Find NA in A
NA_Val <- is.na(A)
#Rotate NA matrix on column
NA_VAL_180 <- NA_Val[1:nrow(NA_Val),ncol(NA_Val):1]
#Set corresponding values NA in B.
B[NA_VAL_180] <- NA
B
[,1] [,2] [,3]
[1,] 3 4 1
[2,] 2 5 NA
[3,] 3 NA NA
Related
I have a list of matrices that I've created. The matrices in the list have different dimensions, and I would like to fill the matrices that don't have a 3x3 dimension with NAs.
I have included my expected outcome below. I would like to include this in a if statement, where if the matrix in the list doesn't have a 3x3 dimension I would like to added empty columns/rows to those matrices and fill them with an NA. Is there an efficient way of doing this in 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)
One option would be to create a NA matrix and replace the values with the 'x' based on the row/col index
dummy <- matrix(ncol = 3, nrow = 3)
l2 <- lapply(l1, function(x) replace(dummy, cbind(c(row(x)), c(col(x))), x))
-checking
> all.equal(l2, expected)
[1] TRUE
You can replace parts of a matrix with matrix indexing.
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
Update see comment by 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
First answer: not correct output:
Here is another approach:
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
I think there are better solutions but mine will handle a 1x1 matrix as well, which is really just a vector.
You can use the function I've made here resize_matrix in your code however you'd like. It is pretty verbose, but I thinks it's easy to understand exactly what it's doing under the hood. Note: the function is meant to be used in an lapply() call.
The input:
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
The function:
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)
}
The output:
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
Created on 2022-04-16 by the reprex package (v2.0.1)
I would like to make a cumsum of multiple matrix obtaining the steps. If we consider:
A <- structure(c(1, 2, 3, 2, 3, 1, 4, 1, 2), .Dim = c(3, 3))
# [,1] [,2] [,3]
# [1,] 1 2 4
# [2,] 2 3 1
# [3,] 3 1 2
B <- structure(c(6, 1, 9, 6, 3, 7, 3, 2, 8), .Dim = c(3, 3))
# [,1] [,2] [,3]
# [1,] 6 6 3
# [2,] 1 3 2
# [3,] 9 7 8
C <- structure(c(1, 1, 2, 5, 3, 3, 3, 9, 1), .Dim = c(3, 3))
# [,1] [,2] [,3]
# [1,] 1 5 3
# [2,] 1 3 9
# [3,] 2 3 1
I would like the following results:
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 2 3 1
[3,] 3 1 2
[,1] [,2] [,3]
[1,] 7 8 7
[2,] 3 6 3
[3,] 12 8 10
[,1] [,2] [,3]
[1,] 8 13 10
[2,] 4 9 12
[3,] 14 11 11
with all steps! I could do this with a for loop, but it's slow with big matrix, how can I do this with apply ?
This is a perfect job for Reduce:
Reduce("+", list(A,B,C), accumulate=TRUE)
[[1]]
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 2 3 1
[3,] 3 1 2
[[2]]
[,1] [,2] [,3]
[1,] 7 8 7
[2,] 3 6 3
[3,] 12 8 10
[[3]]
[,1] [,2] [,3]
[1,] 8 13 10
[2,] 4 9 12
[3,] 14 11 11
I have a vector v, and I would like to create the following matrix. How can I do this in R?
v = c(1, 2, 3, 4)
> m = matrix(c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,4), nrow=4)
> m
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 1 2 3 4
[3,] 1 2 3 4
[4,] 1 2 3 4
See ?matrix and the nrow, ncol, byrow arguments:
matrix(v, nrow=4, ncol=4, byrow=TRUE)
# [,1] [,2] [,3] [,4]
#[1,] 1 2 3 4
#[2,] 1 2 3 4
#[3,] 1 2 3 4
#[4,] 1 2 3 4
I have a matrix m and a vector v. I would like to multiply the matrix m into vetcor vand get a matrix whith same dimension as m means that multiply first element of m to v and .... How can I do this in R?
m = matrix(c(1, 2, 3, 4, 5), ncol=1)
v = c(1, 2, 3, 4, 5)
> z
[,1]
[1,] 1
[2,] 4
[3,] 9
[4,] 16
[5,] 25
Cross products can be obtained using the %*% operator:
> m = matrix(c(1, 2, 3, 4, 5), ncol=1)
> v = c(1, 2, 3, 4, 5)
> m %*% v
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 2 4 6 8 10
[3,] 3 6 9 12 15
[4,] 4 8 12 16 20
[5,] 5 10 15 20 25
> m * v
[,1]
[1,] 1
[2,] 4
[3,] 9
[4,] 16
[5,] 25
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Removing empty rows of a data file in R
How would I remove rows from a matrix or data frame where all elements in the row are NA?
So to get from this:
[,1] [,2] [,3]
[1,] 1 6 11
[2,] NA NA NA
[3,] 3 8 13
[4,] 4 NA NA
[5,] 5 10 NA
to this:
[,1] [,2] [,3]
[1,] 1 6 11
[2,] 3 8 13
[3,] 4 NA NA
[4,] 5 10 NA
Because the problem with na.omit is that it removes rows with any NAs and so would give me this:
[,1] [,2] [,3]
[1,] 1 6 11
[2,] 3 8 13
The best I have been able to do so far is use the apply() function:
> x[apply(x, 1, function(y) !all(is.na(y))),]
[,1] [,2] [,3]
[1,] 1 6 11
[2,] 3 8 13
[3,] 4 NA NA
[4,] 5 10 NA
but this seems quite convoluted (is there something simpler that I am missing?)....
Thanks.
Solutions using rowSums() generally outperform apply() ones:
m <- structure(c( 1, NA, 3, 4, 5,
6, NA, 8, NA, 10,
11, NA, 13, NA, NA),
.Dim = c(5L, 3L))
m[rowSums(is.na(m)) != ncol(m), ]
[,1] [,2] [,3]
[1,] 1 6 11
[2,] 3 8 13
[3,] 4 NA NA
[4,] 5 10 NA
Sweep a test for all(is.na()) across rows, and remove where true. Something like this (untested as you provided no code to generate your data -- dput() is your friend):
R> ind <- apply(X, 1, function(x) all(is.na(x)))
R> X <- X[ !ind, ]