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:
combn
produces a matrix of combinations (albeit sideways from what you want, so transpose witht
)- make a matrix of zeros with number of rows = number of combinations and number of columns = total length - length of combination on this iteration
- bind column-wise
- 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
Classic Case of 'Sum' Returning Na Because It Doesn't Sum Nas
R Histogram from Frequency Table
Programmatically Create Tab and Plot in Markdown
Filtering Multiple Columns with Str_Detect
Http Error 400 on Google_Elevation() Call
Extra Curly Braces When Using Xtable and Knitr, After Specifiying Size
How to 'Subset' a Named Vector in R
R Ggplot2 Using Italics and Non-Italics in the Same Category Label
Population Pyramid Plot with Ggplot2 and Dplyr (Instead of Plyr)
Dealing with Nan's in Matlab Functions
R: Need Finite 'Ylim' Values in Function
Get Value of Last Non-Na Row Per Column in Data.Table
Find Closest Points (Lat/Lon) from One Data Set to a Second Data Set
R - Check If String Contains Dates Within Specific Date Range
In R Data.Frame, Promote Rownames to Actual Column
How to Sort a Vector of Alphanumeric Values Using Lexical Ordering in R