I have a matrix M and a matrix L that contains 'pair of rows indexes' that i need to select in M, in order to apply a function. The function returns a matrix with 2 rows and the same number of columns of M:
set.seed(1)
# M has even number of rows
M = matrix(runif(24), ncol = 3)
# each row of L is a pair of row indexes that will be selected in M
# so the first 'pair' is M[1,] M[3,], the second is M[2,] M[4,] and so on
L = matrix(c(1,3,2,4,6,7), ncol = 2, byrow = T)
The function f is:
f = function(r1, r2)
{
matrix(c(r1+r2, r1-r2), nrow = 2, byrow = T)
}
The thing is that a need to loop over L, apply f for each 'pair' and append the results to another matrix. So, for the code above the final result would be:
#first row of L
res1 = f(M[1,], M[3,])
#second row of L
res2 = f(M[2,], M[4,])
#third row of L
res3 = f(M[6,], M[7,])
#append everything
RES = rbind(res1, res2, res3)
How can i vectorize this operation? The rows indexes in L are random, and the row order of the final result didn't matter.
Thanks for any help!
What if you wrap your f function in something that takes the matrix M as an additional argument:
fm <- function(rowVector, mat) {
f(mat[rowVector[1],], mat[rowVector[2],])
}
then call it with apply:
apply(L, 1, fm, mat=M)
[,1] [,2] [,3]
[1,] 0.8383620 1.2803317 1.84306495
[2,] -0.3073447 -0.5360839 -0.04628558
[3,] 0.8350886 0.2383430 1.15394514
[4,] 0.4231395 -0.1147705 -0.38573770
[5,] 1.0976537 1.7693513 0.86381629
[6,] 0.3375833 0.2144609 -0.43953124
Related
I am trying to multiply a list of matrices, in the order they appear within the list starting with matrix 1, by an initial vector and then recursively; so matrix 2 from the list multiplied by that resulting vector. I have tried various iteration of lapply and map but am unable to project forward and perform this recursively. More explicitly: A[[1]] % * % allYears[,1], then A[[2]] % * % allYears[,2],.....,A[[4]] % * % allYears[,4] which produces the final 5th column in "allYears". Below is the sample code with the known error in the for loop at A[[i]] indexing as i is not explicitly referenced.
A <- lapply(1:4, function(x) # construct list of matrices
matrix(c(0, 0, 10,
rbeta(1, 5, 4), 0, 0,
0, rbeta(1, 10, 2), 0), nrow=3, ncol=3, byrow=TRUE, ))
n <- c(1000, 100, 10) # initial vector of abundances
nYears <- 4 # define the number of years to project over
allYears <- matrix(0, nrow=3, ncol=nYears+1) # build a storage array for all abundances
allYears[, 1] <- n # set the year 0 abundance
for (t in 1:(nYears + 1)) { # loop through all years
allYears[, t] <- A[[i]] %*% allYears[, t - 1]
}
Based on the description, perhaps we need to loop over the sequence - i.e. length of A is 4, whereas the number of columns of 'allYears' is 5. Create an index from 2 to ncol of 'allYears', then loop over the sequence of that index, extract the corresponding element of 'A' based on the sequence whereas we get the allYears previous column
i1 <- 2:(nYears + 1)
for(t in seq_along(i1)) {
allYears[,i1[t]] <- A[[t]] %*% allYears[,i1[t]-1]
}
-output
> allYears
[,1] [,2] [,3] [,4] [,5]
[1,] 1000 100.00000 817.24277 2081.08322 333.6702
[2,] 100 261.46150 55.44237 423.22095 1244.6680
[3,] 10 81.72428 208.10832 33.36702 355.5175
Alternative, possibly too clever, solution:
Construct a list of (A[[1]], A[[1]] %*% A[[2]], ... )
Alist <- Reduce("%*%", A, accumulate=TRUE)
Multiply each of these by the initial value
vlist <- lapply(Alist, "%*%", n)
Combine:
do.call(cbind, vlist)
[,1] [,2] [,3] [,4]
[1,] 100.00000 856.66558 4864.20044 486.420
[2,] 569.23739 56.92374 543.02451 3307.690
[3,] 78.55101 553.62548 55.36255 445.619
#MikaelJagan points out that this can be done in fewer steps:
do.call(cbind,
rev(Reduce("%*%", rev(A), init = n, right = TRUE, accumulate = TRUE)))
or (in recent versions of R)
(A
|> rev()
|> Reduce(f = "%*%", init = n, right = TRUE, accumulate = TRUE)
|> rev()
|> do.call(what = cbind)
)
(The last step could be replaced by |> unlist() |> matrix(nrow = length(n)).)
I have two matrices, one of them has a NA value and I want to use a function that only runs if there are NAs present in the data, so if I run the function it should only work on df2 and not df1. How would I do this?
df1 <- matrix(1:4, nrow = 2, ncol = 2)
df2 <- matrix(1,2,3,NA, nrow = 2, ncol = 2)
Based on the comment above, here is a complete answer (assuming I understand what you are getting at). The function is set up to do something or not to the matrix depending on whether it has NA values.
df1 <- matrix(1:4, nrow = 2, ncol = 2)
df2 <- matrix(c(1,2,3,NA), nrow = 2, ncol = 2)
myfunc <- function(m) {
ret <- m
if (all(!is.na(m))) {
print("This matrix has no NAs")
} else {
print("This matrix has NAs")
}
return(ret)
}
myfunc(df1)
# [1] "This matrix has no NAs"
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
myfunc(df2)
# [1] "This matrix has NAs"
# [,1] [,2]
# [1,] 1 3
# [2,] 2 NA
let's assume we have 4 vectors
a <- c(200,204,209,215)
b <- c(215,220,235,245)
c <- c(230,236,242,250)
d <- c(240,242,243,267)
I basically want to create a loop which creates the differentials between each pair, and then calculate the Z scores for those differentials. So something like scale(d-a). How do I create the loop that basically goes scale(b-a), then scale(c-a), scale(d-a) etc? many thanks.
Single named variables don't lend themselves too well to "looping".
Let's use a list() of vectors instead:
vecs <- list(
a = c(200,204,209,215),
b = c(215,220,235,245),
c = c(230,236,242,250),
d = c(240,242,243,267)
)
This allows us to apply a function to all pairs using combn
scale_diff <- function(subset) {
z <- scale(subset[[1]] - subset[[2]])
colnames(z) <- paste(names(subset), collapse = " - ")
z
}
z_scores <- combn(vecs, 2, scale_diff, simplify = FALSE)
Now z_scores is a list of 6 matrices (column vectors). The column names show you which vectors were subtracted before scaling.
We can place it in a list and use combn to get the combinations and then apply the difference
lst1 <- list(a = a, b = b, c = c, d = d)
out <- combn(lst1, 2, FUN = function(x) scale(Reduce(`-`, x))[,1])
colnames(out) <- combn(names(lst1), 2, FUN = paste, collapse='_')
out
# a_b a_c a_d b_c b_d c_d
#[1,] 0.9108601 1.2009612 0.1290994 -0.7643506 -0.753390 -0.2219686
#[2,] 0.7759179 0.2401922 0.3872983 -0.9441978 -0.360317 0.3699477
#[3,] -0.5735045 -0.2401922 0.9036961 0.6744270 1.474024 1.1098432
#[4,] -1.1132735 -1.2009612 -1.4200939 1.0341214 -0.360317 -1.2578222
As #AlexR mentioned in the comments, if the attributes are important, then remove [,1] and keep it as a matrix of 1 column
out <- combn(lst1, 2, FUN = function(x) scale(Reduce(`-`, x)), simplify = FALSE)
I am trying to get a function that is the opposite of diff()
I want to add the values of adjacent columns in a matrix for each column in the matrix.
I do NOT need the sum of the entire column or row.
For example:
If I had:
[ 1 2 4;
3 5 8 ]
I would end up with:
[ 3 6;
8 13 ]
Of course for just one or two columns this is simple as I can just do x[,1]+x[,2], but these matrices are quite large.
I'm surprised that I cannot seem to find an efficient way to do this.
m <- matrix(c(1,3,2,5,4,8), nrow=2)
m[,-1] + m[,-ncol(m)]
[,1] [,2]
[1,] 3 6
[2,] 8 13
Or, just for the fun of it:
n <- ncol(m)
x <- suppressWarnings(matrix(c(1, 1, rep(0, n-1)),
nrow = n, ncol = n-1))
m %*% x
[,1] [,2]
[1,] 3 6
[2,] 8 13
Dummy data
mat <- matrix(sample(0:9, 100, replace = TRUE), nrow = 10)
Solution:
sum.mat <- lapply(1:(ncol(mat)-1), function(i) mat[,i] + mat[,i+1])
sum.mat <- matrix(unlist(sum.mat), byrow = FALSE, nrow = nrow(mat))
You could use:
m <- matrix(c(1,2,4,3,5,8), nrow=2, byrow=T)
sapply(2:ncol(m), function(x) m[,x] + m[,(x-1)])
I have 2 matrices.
The first one:
[1,2,3]
and the second one:
[3,1,2
2,1,3
3,2,1]
I'm looking for a way to multiply them.
The result is supposed to be: [11, 13, 10]
In R, mat1%*%mat2 don't work.
You need the transpose of the second matrix to get the result you wanted:
> v1 <- c(1,2,3)
> v2 <- matrix(c(3,1,2,2,1,3,3,2,1), ncol = 3, byrow = TRUE)
> v1 %*% t(v2)
[,1] [,2] [,3]
[1,] 11 13 10
Or potentially quicker (see ?crossprod) if the real problem is larger:
> tcrossprod(v1, v2)
[,1] [,2] [,3]
[1,] 11 13 10
mat1%%mat2 Actuall y works , this gives [ 16 9 11 ]
but you want mat1 %% t(mat2). This means transpose of second matrix, then u can get [11 13 10 ]
Rcode:
mat1 = matrix(c(1,2,3),nrow=1,ncol=3,byrow=TRUE)
mat2 = matrix(c(3,1,2,2,1,3,3,2,1), nrow=3,ncol=3,byrow=TRUE)
print(mat1)
print(mat2 )
#matrix Multiplication
print(mat1 %*% mat2 )
# matrix multiply with second matrix with transpose
# Note of using function t()
print(mat1 %*% t(mat2 ))
It's difficult to say what the best answer here is because the notation in the question isn't in R, it's in matlab. It's hard to tell if the questioner wants to multiple a vector, 1 row matrix, or 1 column matrix given the mixed notation.
An alternate answer to this question is simply switch the order of the multiplication.
v1 <- c(1,2,3)
v2 <- matrix(c(3,1,2,2,1,3,3,2,1), ncol = 3, byrow = TRUE)
v2 %*% v1
This yields an answer that's a single column rather than a single row matrix.
try this one
x<-c()
y<-c()
for(i in 1:9)
{
x[i]<-as.integer(readline("Enter number for 1st matrix"))
}
for(i in 1:9)
{
y[i]<-as.integer(readline("Enter number for 2nd matrix"))
}
M1 <- matrix(x, nrow=3,ncol = 3, byrow=TRUE)
M2 <- matrix(y, nrow=3,ncol = 3, byrow=TRUE)
print(M1%*%M2)