I have a 10000 x 7 data.table dat . I would like to multiply each row of dat by a 7x7 matrix c. I have tried the following
apply(dat, 1, function(x) sqrt(as.matrix(x) %*% as.matrix(c) %*% t(as.matrix(x))))
I get this error
Error in as.matrix(x) %*% as.matrix(c) : non-conformable arguments
This function works when I take a single row from dat (so 1 x 7) but not when I use apply.
How do I make this work using apply?
Thanks!
Additional info - I could achieve what I need another way. I could multiply the entire data.frame by the matrix and take sqrt(diag(x)). However, I need to do this a lot of times, so it would be more efficient to take this row by row and return a single figure.
I think you should use t(as.matrix(x))%*% as.matrix(c) %*% as.matrix(x) in your apply function, since the argument as.matrix(x) is indeed a column-vector (not a row-vector).
res <- apply(dat, 1, function(x) sqrt(t(as.matrix(x))%*% as.matrix(c) %*% as.matrix(x)))
Example
set.seed(1)
dat <- data.frame(matrix(sample(70),ncol = 7))
c <- matrix(sample(49),ncol = 7)
res <- apply(dat, 1, function(x) sqrt(t(as.matrix(x))%*% as.matrix(c) %*% as.matrix(x)))
such that
> res
[1] 1522.7206 1208.6306 1105.7509 1063.4341 1066.3423 1124.8271
[7] 1219.2280 1665.8301 1609.4704 954.3694
Note: c() is a commonly used function in R, using c as variable name is therefore not good practice, I use c_ below instead.
When multiplying matrices the number of columns in the first matrix needs to be the same as the number of rows in the second. In the as.matrix(x) %*% as.matrix(c) part in your code the first matrix has one column and the second has 7 rows. That is why you get the error.
Multiplying the transposed row of dat with c first and then the row fixes this.
apply(dat2, 1, function(x) sqrt(t(as.matrix(x)) %*% as.matrix(c_) %*% (as.matrix(x))))
Or making the function more explicit in regard to the matrix you want to create from the row also works:
apply(dat, 1, function(x) sqrt(matrix(x, 1) %*% c_ %*% t(matrix(x, 1))))
Both solutions produce the same results.
Related
What is this? I can't find help by using ?. (Sorry for being dumb)
> 1%*%1
[,1]
[1,] 1
> 10%*%10
[,1]
[1,] 100
> c(1:2)%*%c(1:2)
[,1]
[1,] 5
It's a matrix multiplication operator!
From the documentation:
Description:
Multiplies two matrices, if they are conformable. If one argument is a vector, it will be promoted to either a row or column matrix to make the two arguments conformable. If both are vectors of the same length, it will return the inner product (as a matrix).
Usage:
x %*% y
Arguments:
x, y numeric or complex matrices or vectors
> c(1,2,3) %*% c(4,5,6)
[,1]
[1,] 32
> c(1,2,3) * c(4,5,6)
[1] 4 10 18
Like MadSeb said, it is the matrix multiplication operator. If you give it two vectors, it will coerce them to (logical) 1-row & a 1-col matrix and multiply them.
It is also the inner (or dot) product between two vectors and finds wide usage in linear algebra, computational geometry and a host of other applications.
http://en.wikipedia.org/wiki/Dot_product
BTW, the vectors have to be in the same space (same number of dimensions)
> c(1,2,3) %*% c(4,5,6,7)
Error in c(1, 2, 3) %*% c(4, 5, 6, 7) : non-conformable arguments
I created a question 'What is the calculation behind the %*% operator in R?' which was marked as a duplicate of this question. The %*% operator is used to multiply two matrices. I didn't realise 'matrix multiplication' was an established algebraic method so it was useful to learn the underlying calculation, not yet described explicitly in other answers here. Passing on useful links from comments in the duplicate question
https://en.m.wikipedia.org/wiki/Matrix_multiplication#Definition
http://matrixmultiplication.xyz/
This operator is used to multiply a matrix with its transpose.
M = matrix( c(2,6,5,1,10,4), nrow = 2,ncol = 3,byrow = TRUE)
t = M %*% t(M)
print(t)
from tutorialspoints
I have a list of matrices of mostly similar sizes. I need to keep the upper triangle of each matrix equal to 0. I can make the upper tri of an individual matrix equal to 0 by using:
matrix[upper.tri(matrix)] <- 0
When I try to apply this to the list of matrices using lapply it replaces the entire matrix list with 0's. For example:
list.matrix <- lapply(list.matrix, function (x) x[upper.tri(x)] <- 0)
$`matrix1`
[1] 0
$`matrix2`
[1] 0
...
Can anyone provide input as to why this might be happening?
This was resolved by including the function in lapply as a new function:
f <- function(x) {
x[upper.tri(x)] <- 0
x
}
as suggested here: lapply to turn specified matrix elements within list to NA.
We can use replace
f <- function(x) replace(x, upper.tri(x), 0)
f(m1)
data
m1 <- matrix(1:9, 3, 3)
i am working with consumer price index CPI and in order to calculate it i have to multiply the index matrix with the corresponding weights:
grossCPI77_10 <- grossIND1977 %*% weights1910/100
grossCPI82_10 <- grossIND1982 %*% weights1910/100
of course i would rather like to have a code like the one beyond:
grossIND1982 <- replicate(20, cbind(1:61))
grossIND1993 <- replicate(20, cbind(1:61))
weights1910_sc <- c(1:20)
grossIND_list <- mget(ls(pattern = "grossIND...."))
totalCPI <- mapply("*", grossIND_list, weights1910_sc)
the problem is that it gives me a 1200x20 matrix. i expected a normal matrix (61x20) vector (20x1) multiplication which should result in a 20x1 vector? could you explain me what i am doing wrong? thanks
part of your problem is that you don't have matrices but 3D arrays, with one singleton dimension. The other issue is that mapply likes to try and combine the results into a matrix, and also that constant arguments should be passed via MoreArgs. But actually, this is more a case for lapply.
grossIND1982 <- replicate(20, cbind(1:61))[,1,]
grossIND1993 <- replicate(20, cbind(1:61))[,1,]
weights1910_sc <- c(1:20)
grossIND_list <- mget(ls(pattern = "grossIND...."))
totalCPI <- mapply("*", grossIND_list, MoreArgs=list(e2 = weights1910_sc), SIMPLIFY = FALSE)
totalCPI <- lapply(grossIND_list, "*", e2 = weights1910_sc)
I am not sure if I understood all aspects of your problem (especially concerning what should be colums, what should be rows, and in which order the crossproduct shall be applied), but I will try at least to cover some aspects. See comments in below code for clarifications of what you did and what you might want. I hope it helps, let me know if this is what you need.
#instead of using mget, I recommend to use a list structure
#otherwise you might capture other variables with similar names
#that you do not want
INDlist <- sapply(c("1990", "1991"), function(x) {
#this is how to set up a matrix correctly, check `?matrix`
#I think your combination of cbind and rep did not give you what you wanted
matrix(rep(1:61, 20), nrow = 61)
}, USE.NAMES = TRUE, simplify = F)
weights <- list(c(1:20))
#the first argument of mapply needs to be a function, in this case of two variables
#the body of the function calculates the cross product
#you feed the arguments (both lists) in the following part of mapply
#I have repeated your weights, but you might assign different weights for each year
res <- mapply(function(x, y) {x %*% y}, INDlist, rep(weights, length(INDlist)))
dim(res)
#[1] 61 2
I have two matrices:
mat <- matrix(1:6, 2, 3)
mat2 <- matrix(1:2, 2, 3)
and a parameter
a <- 1
using ifelse, is it possible to return a matrix when a is a certain value?
the code that I am using, does not work. For example:
mat.new <- ifelse(a == 1, mat, mat2)
The length of the return is completely decided by length(a == 1). See also the helpfile with ?ifelse. Your code will only return a single value.
ifelse targets vector input / output. Even if you get the length correct, say: ifelse(rep(TRUE, 6), mat, mat2), you get a vector rather than a matrix output. So an outer matrix call to reset dimension is necessary.
Tip 1:
For your example, looks like a simple result <- if (a == 1) mat else mat2 is sufficient. No need to touch ifelse.
Tip 2:
It is not impossible to ask ifelse to return a matrix, but you have to protect it by a list (remember a list is a vector):
ifelse(TRUE, list(mat), list(mat2))
But, this is inconvenient.
So I took some information from a CSV, stored it as a matrix, and tried to compute the following operations on the result, but it gave me a 2x2 array of NA. Not seeing the problem here.
data <- read.csv('qog.csv', sep=';')
X <- matrix( log( data$wdi_gnipc ) )
X <- cbind(X, data$ciri_empinx_new)
t(X) %*% X
When I look at X and t(X) they look like how I expect them to, so I am matrix-multiplying a 2xn matrix with an nx2 matrix (n is some large number like 193) and so the matrix product should be well-defined and give a meaningful 2x2 answer.
Any ideas what could be going wrong?
Note: When I try
a <- rbind(c(1,2), c(3,4))
t(a) %*% a
it gives the desired result. Not sure what the important difference is between that and what I'm doing with the data.
Let's make that an answer. For the cross product to be filled with NA, you must have at least one NA per column inside X. You can find the number of NAs per column by running:
colSums(is.na(X))
and by all likelihood you will have that
all(colSums(is.na(X)) > 0)
# [1] TRUE