R: How to Match/Join 2 Matrices of Different Dimensions (Nrow/Ncol)

R: How to match/join 2 matrices of different dimensions (nrow/ncol)?

See below using R's match function (I renamed your small matrix):

a = c("A", "B", "C", "D", "E", "F")
full_matrix = matrix(nrow = length(a), ncol=length(a))
dimnames(full_matrix) <- list(levels(as.factor(a)), levels(as.factor(a)))

small_matrix = matrix(c(2, 4, 3, 1, 5, 7, 3, 1, 6), nrow=3, ncol=3)
dimnames(small_matrix) <- list(as.factor(c("B","C","E")), as.factor(c("A","B","F")))

You can then use:

rowmatch <- match(rownames(small_matrix), rownames(full_matrix))
colmatch <- match(colnames(small_matrix), colnames(full_matrix))
full_matrix[rowmatch, colmatch] <- small_matrix

Which gives you the desired output:

   A  B  C  D  E  F
A NA NA NA NA NA NA
B 2 1 NA NA NA 3
C 4 5 NA NA NA 1
D NA NA NA NA NA NA
E 3 7 NA NA NA 6
F NA NA NA NA NA NA

Or alternatively, you can use %in% with slighly different syntax:

full_matrix[rownames(full_matrix) %in% rownames(small_matrix), 
colnames(full_matrix) %in% colnames(small_matrix)] <- small_matrix

R: How to match/join 2 matrices of different dimensions (nrow/ncol) in a LOOP?

I would create your full "matrix" as a 3-dimensional array rather than a list, and then fill in this array with a list of smaller matrices by looping through the corresponding index of the 3d dimension of the array.

library(abind)

a = c("A", "B", "C", "D", "E", "F")
full_matrix = array(dim=c(6,6,2))
dimnames(full_matrix) <- list(levels(as.factor(a)), levels(as.factor(a)),
c("mat1","mat2"))

small_matrix_1 = matrix(c(2, 4, 3, 1, 5, 7, 3, 1, 6), nrow=3, ncol=3)
dimnames(small_matrix_1) <- list(c("B","C","E"), c("A","B","F"))

small_matrix_2 = matrix(c(20, 40, 30, 10, 50, 70, 30, 10, 60), nrow=3, ncol=3)
dimnames(small_matrix_2) <- list(c("B","C","E"), c("A","B","F"))

small_matrix_list <- list(small_matrix_1, small_matrix_2)

for(i in seq_along(small_matrix_list)){
afill(full_matrix[, , i], local= TRUE ) <- small_matrix_list[[i]]
}

giving
full_matrix
with the 3rd index corresponding to each of the small matrices.

, , mat1

A B C D E F
A NA NA NA NA NA NA
B 2 1 NA NA NA 3
C 4 5 NA NA NA 1
D NA NA NA NA NA NA
E 3 7 NA NA NA 6
F NA NA NA NA NA NA

, , mat2

A B C D E F
A NA NA NA NA NA NA
B 20 10 NA NA NA 30
C 40 50 NA NA NA 10
D NA NA NA NA NA NA
E 30 70 NA NA NA 60
F NA NA NA NA NA NA

Edit: Instead of creating data.frames with dcast as in your previous question, I would cast the data as arrays (acast) so that they can inserted into the larger array.

library(reshape2) 
small_matrix <- vector(mode = "list", length = 2) # Pre-allocate space in the list

for (i in seq(Import_Year)){
small_matrix[[i]] <- acast(OC ~ TC, data = Import_Year[[i]], value.var = "Value")
}

Compare dimension of two matrices in R

As suggested by @eipi10, I now use identical(dim(x), dim(y)).

How to aggregate matrices which have different dimensions? [R]

Here are some alternative solutions:

1) Convert each to long form giving both and then use tapply to aggregate and convert back to wide form:

both <- rbind(as.data.frame.table(a), as.data.frame.table(b))
tapply(both[[3]], both[-3], sum, default = 0)

giving:

    Var2
Var1 0 1 2 3
0 2 7 12 10
1 4 9 14 11
2 3 6 9 12

2) This creates a matrix zero having the shape of the result and then defines a function upleft which inserts its first argument into the upper left of zero. Finally we add them together.

upleft <- function(x, zero) replace(zero, cbind(c(row(x)), c(col(x))), x)
zero <- array(0, pmax(dim(a), dim(b)))
upleft(a, zero) + upleft(b, zero)

giving:

     [,1] [,2] [,3] [,4]
[1,] 2 7 12 10
[2,] 4 9 14 11
[3,] 3 6 9 12

R: Adding two matrices with different dimensions based on columns

So you want to sum all of the matrices to end up with one matrix? A simple but perhaps slow (I suspect, but it's probably not a big deal with your matrices) way is to use the plyr and reshape2 libraries. You could start with a list of your matrices:

make.matrix <- function() {
cols <- sample(month.name, runif(1, 2, 12))
matrix(rnorm(length(cols)*10), 10, length(cols), dimnames=list(NULL, cols))
}

# Make 10 matrices filled with random numbers, having
# varying numbers of columns named after months
my.matrices <- replicate(10, make.matrix())

Then you can melt all the matrices into one big dataframe

matrix.df <- ldply(my.matrices, melt, varnames=c("row", "col"))
head(matrix.df)
# row col value
# 1 1 February -0.4239145
# 2 2 February 1.1773608
# 3 3 February -2.9565403
# 4 4 February 0.3955096
# 5 5 February -0.3784917
# 6 6 February -0.6234579

and then cast it back into a matrix.

sum.matrix <- acast(matrix.df, row ~ col, sum)

Combine matrices with different arrays using loop FOR in R

Something like this?

src <- c(1, 2, 3, 4)
len <- length(src)
acc <- list()

for (i in 1:len) {
c <- t(combn(src, i))
zeros <- matrix(0, nrow = dim(c)[1], ncol = len - i)
acc[[i]] <- cbind(c, zeros)
}

do.call(rbind, acc)

Output:

      [,1] [,2] [,3] [,4]
[1,] 1 0 0 0
[2,] 2 0 0 0
[3,] 3 0 0 0
[4,] 4 0 0 0
[5,] 1 2 0 0
[6,] 1 3 0 0
[7,] 1 4 0 0
[8,] 2 3 0 0
[9,] 2 4 0 0
[10,] 3 4 0 0
[11,] 1 2 3 0
[12,] 1 2 4 0
[13,] 1 3 4 0
[14,] 2 3 4 0
[15,] 1 2 3 4

Explanation:

  1. combn produces a matrix of combinations (albeit sideways from what you want, so transpose with t)
  2. make a matrix of zeros with number of rows = number of combinations and number of columns = total length - length of combination on this iteration
  3. bind column-wise
  4. outside the loop, bind all the accumulated matrices for each iteration row-wise.

BTW, I looked the the combinations function you were using and I'm not sure if you need that over the built-in combn function which is why I used it. combn just gives you all combinations of a certain length, which is what you want.

R: How to fill one column matrices of different dimensions in a LOOP?

This could be one solution using data.table:

library(data.table)
#create a big data.table with all the elements
biglist <- rbindlist(dfList)
#use lapply to operate on individual dfs
lapply(dfList, function(x) {
#use the big data table to merge to each one of the element dfs
temp <- merge(biglist[, list(CNTRY)], x, by='CNTRY', all.x=TRUE)
#remove the duplicate values
temp <- temp[!duplicated(temp), ]
#convert CNTRY to character and set the order on it
temp[, CNTRY := as.character(CNTRY)]
setorder(temp, 'CNTRY')
temp
})

Output:

$`111.2000`
CNTRY Value
1: A NA
2: B 3
3: C 1
4: D 4
5: E NA

$`112.2000`
CNTRY Value
1: A 3
2: B 5
3: C NA
4: D NA
5: E 15

EDIT

For your updated output you could do:

lapply(dfList, function(x) {
temp <- merge(biglist[, list(CNTRY)], x, by='CNTRY', all.x=TRUE)
temp <- temp[!duplicated(temp), ]
temp[, CNTRY := as.character(CNTRY)]
setorder(temp, 'CNTRY')
data.frame(Value=temp$Value, row.names=temp$CNTRY)
})

$`111.2000`
Value
A NA
B 3
C 1
D 4
E NA

$`112.2000`
Value
A 3
B 5
C NA
D NA
E 15

But I would really suggest keeping the list with data.table elements rather than converting to data.frames so that you can have row.names.



Related Topics



Leave a reply



Submit