I have the following problem :
w <- matrix(1:3,nrow=3,ncol=1)
mymat <- as.matrix(cbind(a = 6:15, b = 16:25, c= 26:35))
mymat
a b c
[1,] 6 16 26
[2,] 7 17 27
[3,] 8 18 28
[4,] 9 19 29
[5,] 10 20 30
[6,] 11 21 31
[7,] 12 22 32
[8,] 13 23 33
[9,] 14 24 34
[10,] 15 25 35
I want to obtain the following results in a matrix the same size as mymat:
a b c
[1,] 6*1 16*2 26*3
[2,] 7*1 17*2 27*3
[3,] 8*1 18*2 28*3
...
I've tried the lappy function but I am unable to get the results I want. Thanks!
Using sweep():
sweep(mymat, 2, w, "*")
Converting w into a matrix of the same dimensions:
mymat * t(w)[rep(1, NROW(mymat)), ]
1) diag Post multipy it by the appropriate diagonal matrix. We can omit c(), although it won't hurt, if w is a vector rather than a matrix.
mymat %*% diag(c(w))
2) KhatriRao We could alternately use the KhatriRao product. If w is the w defined in the question then matrix could be optionally omitted but we included it in case w is actually a vector. Note that the Matrix package comes with R so it does not have to be installed.
library(Matrix)
KhatriRao(mymat, t(matrix(w)))
3) mapply
mapply(`*`, as.data.frame(mymat), w)
We can use also use col to replicate the values and then multiply in base R
mymat * w[col(mymat)]
Related
In R, is there a more efficient and/or general way to produce the desired output from the two matrices below? I'm suspicious that what I've done is just some esoteric matrix multiplication operation of which I'm not aware.
ff <- matrix(1:6,ncol=2)
# [,1] [,2]
# [1,] 1 4
# [2,] 2 5
# [3,] 3 6
bb <- matrix(7:10,ncol=2)
# [,1] [,2]
# [1,] 7 9
# [2,] 8 10
# DESIRE:
# 7 36
# 14 45
# 21 54
# 8 40
# 16 50
# 24 60
This works, but isn't the general solution I'm looking for:
rr1 <- t(t(ff) * bb[1,])
rr2 <- t(t(ff) * bb[2,])
rbind(rr1,rr2)
# [,1] [,2]
# [1,] 7 36
# [2,] 14 45
# [3,] 21 54
# [4,] 8 40
# [5,] 16 50
# [6,] 24 60
This next code block seems pretty efficient and is general. But is there a better way?
Something like kronecker(ffa,bba)? (which clearly doesn't work in this case)
ffa <- matrix(rep(t(ff),2), ncol=2, byrow=T)
bba <- matrix(rep(bb,each=3), ncol=2)
ffa * bba
# [,1] [,2]
# [1,] 7 36
# [2,] 14 45
# [3,] 21 54
# [4,] 8 40
# [5,] 16 50
# [6,] 24 60
This is related to my other questions:
Using apply function over the row margin with expectation of stacked results, where I'm trying to understand the behavior of apply itself and:
Is this an example of some more general matrix product?, where I'm asking about the theoretical math, specifically.
Use a kronecker product and pick off the appropriate columns:
kronecker(bb, ff)[, c(diag(ncol(bb))) == 1]
or using the infix operator for kronecker:
(bb %x% ff)[, c(diag(ncol(bb))) == 1]
Another approach is to convert the arguments to data frames and mapply kronecker across them. For the case in the question this performs the calculation cbind(bb[, 1] %x% ff[, 1], bb[, 2] %x% ff[, 2]) but in a more general manner without resorting to indices:
mapply(kronecker, as.data.frame(bb), as.data.frame(ff))
or using the infix operator for kronecker:
mapply(`%x%`, as.data.frame(bb), as.data.frame(ff))
The functionality you are seeking for is available within the Matrix package as the function KhatriRao. Since the function is in Matrix, output is a matrix of class "dgCMatrix" (sparse matrix). You can transform it to an ordinary matrix of class "matrix" by as.matrix.
library(Matrix)
as.matrix(KhatriRao(bb, ff))
I have a matrix like:
mymat:
a b c
[1,] 1 16 26
[2,] 7 17 27
[3,] 8 18 28
And a list of vectors like
myvec <- c(1:3)
I want to multiply the mymat with myvec like the following
a b c
[1,] 1*1 16*2 26*3
[2,] 7*1 17*2 27*3
[3,] 8*1 18*2 28*3
total 16 102 243
I tried doing mymat %*% myvec in R, but it gave me sum of rows, not the sum of columns like the above. If I try to transpose the matrix I get the following error
> t(mymat) %*% myvec
Error in t(mymat) %*% myvec : non-conformable arguments
I have a 3-dimensional array and would like to collapse to a 2-dimensional by stacking one dimension by rows (combining rows of one dimension). In my code, I have filled a "worksheet" (3rd dimension) with a 2-d array at each index, and now I want to take that 3-d array and stack these sheets' rows on top of one another.
Here an example array so I can explain what I want the end result to look like:
x <- array(1:24, dim=c(2, 3, 4),
dimnames=list(letters[1:2], LETTERS[1:3], letters[23:26]))
dim(x)
I would like w, x, y, z to be stacked on top of one another in a 2-dimensional array, which would have 8 rows and 3 columns. Here is a way to do it that is cumbersome (and not possible in my loop):
x1<-x[,,1]
x2<-x[,,2]
x3<-x[,,3]
x4<-x[,,4]
All<-rbind(x1,x2,x3,x4)
I have looked at abind and adrop but they are not quite right.
I have also tried aperm but I don't think you can reduce dimensions with this, just transpose (?)
Alternatively, I could create a list (this would be ideal, actually, since arrays might have different row numbers). In that case, how would I combine the rows of multiple elements in a list the same way?
I'll promote my comment to an answer, though I still think there should be a way to do this just altering the dimensions.
apply(x, 2, c)
#or if you're really pushing for speed, the simpler function:
apply(x, 2, identity)
# Giving:
# A B C
#[1,] 1 3 5
#[2,] 2 4 6
#[3,] 7 9 11
#[4,] 8 10 12
#[5,] 13 15 17
#[6,] 14 16 18
#[7,] 19 21 23
#[8,] 20 22 24
Matches the requested output sans the rownames:
all.equal(apply(x,2,c), All, check.attributes=FALSE)
#[1] TRUE
Here's how to do it by manipulating the dimensions:
y <- aperm(x, c(1, 3, 2))
dim(y) <- c(prod(dim(x)[-2]), dim(x)[2])
# the above evaluates to c(8, 3)
y
# [,1] [,2] [,3]
# [1,] 1 3 5
# [2,] 2 4 6
# [3,] 7 9 11
# [4,] 8 10 12
# [5,] 13 15 17
# [6,] 14 16 18
# [7,] 19 21 23
# [8,] 20 22 24
Follow up with colnames(y) <- colnames(x) if you need to.
I have a matrix, like the one generated with this code:
> m = matrix(data=c(1:50), nrow= 10, ncol = 5);
> colnames(m) = letters[1:5];
If I filter the columns, and the result have more than one column, the new matrix keeps the names. For example:
> m[, colnames(m) != "a"];
b c d e
[1,] 11 21 31 41
[2,] 12 22 32 42
[3,] 13 23 33 43
[4,] 14 24 34 44
[5,] 15 25 35 45
[6,] 16 26 36 46
[7,] 17 27 37 47
[8,] 18 28 38 48
[9,] 19 29 39 49
[10,] 20 30 40 50
Notice that here, the class is still matrix:
> class(m[, colnames(m) != "a"]);
[1] "matrix"
But, when the filter lets only one column, the result is a vector, (integer vector in this case) and the column name, is lost.
> m[, colnames(m) == "a"]
[1] 1 2 3 4 5 6 7 8 9 10
> class(m[, colnames(m) == "a"]);
[1] "integer"
The name of the column is very important.
I would like to keep both, matrix structure (a one column matrix) and the column's name.
But, the column's name is more important.
I already know how to solve this by the long way (by keeping track of every case). I'm wondering if there is an elegant, enlightening solution.
You need to set drop = FALSE. This is good practice for programatic use
drop
For matrices and arrays. If TRUE the result is coerced to the lowest possible dimension (see the examples)
m[,'a',drop=FALSE]
This will retain the names as well.
You can also use subset:
m.a = subset(m, select = colnames(m) == "a")
I have an N-by-M matrix X, and I need to calculate an N-by-N matrix Y:
Y[i, j] = sum((X[i,] - X[j,]) ^ 2) 0 <= i,j <= N
For now, I have to use nested loops to do it with O(n2). I would like to know if there's a better way, like using matrix operations.
more generally, sum(....) can be a function, fun(x1,x 2) of which x1, x2 are M-by-1 vectors.
you can use expand.grid to get a data.frame of possible pairs:
X <- matrix(sample(1:5, 50, replace=TRUE), nrow=10)
row.ind <- expand.grid(1:dim(X)[1], 1:dim(X)[2])
Then apply along each pair using a function:
myfun <- function(n) {
sum((X[row.ind[n, 1],] - X[row.ind[n, 2],])^2)
}
Y <- matrix(unlist(lapply(1:nrow(row.ind), myfun)), byrow=TRUE, nrow=nrow(X))
> Y
[,1] [,2] [,3] [,4] [,5]
[1,] 0 28 15 31 41
[2,] 31 28 33 30 33
[3,] 28 0 15 7 19
[4,] 33 30 19 34 11
[5,] 15 15 0 12 22
[6,] 10 19 10 21 20
[7,] 31 7 12 0 4
[8,] 16 17 16 13 2
[9,] 41 19 22 4 0
[10,] 14 11 28 9 2
>
I bet there is a better way but its Friday and I'm tired!
(x[i]-x[j])^2 = x[i]² - 2*x[i]*x[j] + x[j]²
and than is middle part just matrix multiplication -2*X*tran(X) (matrix) and other parts are just vetrors and you have to run this over each element
This has O(n^2.7) or whatever matrix multiplication complexity is
Pseudocode:
vec=sum(X,rows).^2
Y=X * tran(X) * -2
for index [i,j] in Y:
Y[i,j] = Y[i,j] + vec[i]+vec[y]
In MATLAB, for your specific f, you could just do this:
Y = pdist(X).^2;
For a non-"cheating" version, try something like this (MATLAB):
[N, M] = size(X);
f = #(u, v) sum((u-v).^2);
helpf = #(i, j) f(X(i, :), X(j, :))
Y = arrayfun(helpf, meshgrid(1:N, 1:N), meshgrid(1:N, 1:N)');
There are more efficient ways of doing it with the specific function sum(...) but your question said you wanted a general way for a general function f. In general this operation will be O(n^2) times the complexity of each vector pair operation because that's how many operations need to be done. If f is of a special form, some calculations' results can be reused.