I have following problem:
myvec <- c(1:3)
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 multiply the mymat with myvec and construct new vector such that
sum(6*1, 16*2, 26*3)
sum(7*1, 17*2, 27*3)
....................
sum(15*1, 25*2, 35*3)
Sorry, this is simple question that I do not know...
Edit: typo corrected
The %*% operator in R does matrix multiplication:
> mymat %*% myvec
[,1]
[1,] 116
[2,] 122
...
[10,] 170
An alternative, but longer way can be this one:
rowSums(t(apply(mymat, 1, function(x) myvec*x)),na.rm=T)
Is the only way that I found that can ignore NA's inside the matrix.
Matrices are vectors in column major order:
colSums( t(mymat) * myvec )
(Edited after hopefully reading question correctly this time.)
Related
I have a 3D R array, e.g.:
a <- array(1:27, dim = c(3,3,3))
How can I (efficiently) convert this into a matrix in which the 3rd dimension is bound / stacked below each other, i.e.:
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
[4,] 10 13 16
[5,] 11 14 17
[6,] 12 15 18
[7,] 19 22 25
[8,] 20 23 26
[9,] 21 24 27
I can clumsily achieve this with:
rbind(a[,,1], a[,,2], a[,,3])
but this is not generalizable well if I have many entries in the 3rd dimension (except with looping).
There must be a more elegant way to achieve this, but I could not find it. Ideas like
apply(a, 3, rbind)
apply(a, 3, c)
create a matrix, but the 3rd dimension simply become the columns. I want to keep the 2D matrices of the first 2 dimensions and just bind them together. I am aware this will mess up the indices, but we can disregard this for my use case.
I would be especially happy about a base R solution, but am also interested if this can be achieved with a (lightweight) package.
Edit:
This answer to a seemingly unrelated question provided a useful hint. This approach seems to achieve the desired result:
matrix(aperm(a, c(1, 3, 2)), nrow = dim(a)[1] * dim(a)[3])
Are there other ideas?
With aperm we transpose an array by permuting its dimensions and optionally resizing it:
y <- aperm(a, c(1, 3, 2))
dim(y) <- c(prod(dim(a)[-2]), dim(a)[2])
y
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
[4,] 10 13 16
[5,] 11 14 17
[6,] 12 15 18
[7,] 19 22 25
[8,] 20 23 26
[9,] 21 24 27
Probably this would be easy. I have a Matrix:
testM <- matrix(1:40, ncol = 4, byrow = FALSE)
testM
[,1] [,2] [,3] [,4]
[1,] 1 11 21 31
[2,] 2 12 22 32
[3,] 3 13 23 33
[4,] 4 14 24 34
[5,] 5 15 25 35
[6,] 6 16 26 36
[7,] 7 17 27 37
[8,] 8 18 28 38
[9,] 9 19 29 39
[10,] 10 20 30 40
and I want to "reduce" the matrix summing column pairs by row. Expected result:
[,1] [,2]
[1,] 12 52
[2,] 14 54
[3,] 16 56
[4,] 18 58
[5,] 20 60
[6,] 22 62
[7,] 24 64
[8,] 26 66
[9,] 28 68
[10,] 30 70
I tried this but doesn't work
X <- apply(1:(ncol(testM)/2), 1, function(x) sum(testM[x], testM[x+1]) )
Error in apply(1:(ncol(testM)/2), 1, function(x) sum(testM[x], testM[x + :
dim(X) must have a positive length
testM[,c(T,F)]+testM[,c(F,T)];
## [,1] [,2]
## [1,] 12 52
## [2,] 14 54
## [3,] 16 56
## [4,] 18 58
## [5,] 20 60
## [6,] 22 62
## [7,] 24 64
## [8,] 26 66
## [9,] 28 68
## [10,] 30 70
Here's a solution using rowSums()
sapply( list(1:2,3:4) , function(i) rowSums(testM[,i]) )
if the number of columns should be arbitrary, it gets more complicated:
li <- split( 1:ncol(testM) , rep(1:(ncol(testM)/2), times=1 , each=2))
sapply( li , function(i) rowSums(testM[,i]) )
We can do a matrix multiplication:
M <- matrix(c(1,1,0,0, 0,0,1,1), 4, 2)
testM %*% M
another solution with tapply():
g <- gl(ncol(testM)/2, 2)
t(apply(testM, 1, FUN=tapply, INDEX=g, sum))
How about:
matrix(c(testM[, 1] + testM[, 2], testM[, 2] + testM[, 4]), nrow = 10)
a solution around your initial idea:
sapply(seq(2, ncol(testM), 2), function(x) apply(testM[, (x-1):x], 1, sum))
I have 17 square matrices of order 430 and a large matrix of dimension 92235 x 34
For each square matrix, I wish to add each row's value (from 1 to 430) to a column in the large matrix, taking only those values above the main diagonal. So [1,2][1,3][1,4]..[1,430][2,3][2,4]...[2,430]...[429,430] -- hence, the 92235 row length of the large matrix (A sample of Step 1 is shown here http://imgur.com/4SlUenK)
The square matrix is transposed
Step 1 is repeated but the row values are added to the next column in the large matrix
Repeat Steps 1-3 16 more times until the large matrix is filled
How do I go about doing this?
TIA
EDIT FOR COMMENT
mat = matrix(1:25,5,5)
mat
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
mat2 = cbind(mat[upper.tri(mat)])
mat2
[,1]
[1,] 6
[2,] 11
[3,] 12
[4,] 16
[5,] 17
[6,] 18
[7,] 21
[8,] 22
[9,] 23
[10,] 24
This reads columns then rows. Instead, I would like to read rows then columns so that the result should be:
[,1]
[1,] 6
[2,] 11
[3,] 16
[4,] 21
[5,] 12
[6,] 17
[7,] 22
[8,] 18
[9,] 23
[10,] 24
If you have 17 square matrices ('m1', 'm2',...'m17'), keep them in a list and then use upper.tri to extract the elements above the diagonal and cbind with the elements from the transpose
lst1 <- mget(paste0('m', 1:17))
Out <- do.call(cbind,lapply(lst1, function(x) {x1 <- t(x)
cbind(x[upper.tri(x)], x1[upper.tri(x1)]) }))
dim(Out)
#[1] 92235 34
Here I created the matrices in a list.
Update
Based on the row order of the data,
mat1 <- mat
mat1[lower.tri(mat1, diag=TRUE)] <- NA
as.vector(na.omit(unlist(tapply(mat1, row(mat1), FUN=I))))
#[1] 6 11 16 21 12 17 22 18 23 24
Or as #David Arenburg mentioned in the comments
temp <- t(mat)
temp[lower.tri(temp)]
#[1] 6 11 16 21 12 17 22 18 23 24
You can replace the steps as here in the lapply.
data
set.seed(24)
lst1 <- replicate(17, matrix(sample(1:200, 430*430, replace=TRUE),
430, 430), simplify=FALSE)
I have a character matrix mtr of n rows and 3 columns.
I have a numeric vector nmb with some numbers, for example, 4,5,6
I want to sort only the rows of mtr, the numbers of which are contained by nmb, by the first column of my matrix.
So in my case I want to leave my matrix untouched except for rows 4,5,6 which I would like to be sorted by the first column and, of course, written back into my matrix mtr.
How could I do that? Thanks.
You can do it in this way:
mtr[nmb,] <- mtr[order(mtr[nmb,1]),]
I think this will do it
mtr[nmb,] <- mtr[nmb,][order(mtr[nmb,1]),]
An example:
nmb <- 4:6
mtr <- matrix(30:1, ncol=3)
> mtr
[,1] [,2] [,3]
[1,] 30 20 10
[2,] 29 19 9
[3,] 28 18 8
[4,] 27 17 7
[5,] 26 16 6
[6,] 25 15 5
[7,] 24 14 4
[8,] 23 13 3
[9,] 22 12 2
[10,] 21 11 1
> mtr[nmb,] <- mtr[nmb,][order(mtr[nmb,1]),]
> mtr
[,1] [,2] [,3]
[1,] 30 20 10
[2,] 29 19 9
[3,] 28 18 8
[4,] 25 15 5 <-
[5,] 26 16 6 <- sorted
[6,] 27 17 7 <-
[7,] 24 14 4
[8,] 23 13 3
[9,] 22 12 2
[10,] 21 11 1
I have a vector with 49 numeric values. I want to have a 7x7 numeric matrix instead.
Is there some sort of convenient automatic conversion statement I can use, or do I have to do 7 separate column assignments of the correct vector subsets to a new matrix? I hope that there is something like the oposite of c(myMatrix), with the option of giving the number of rows and/or columns I want to have, of course.
Just use matrix:
matrix(vec,nrow = 7,ncol = 7)
One advantage of using matrix rather than simply altering the dimension attribute as Gavin points out, is that you can specify whether the matrix is filled by row or column using the byrow argument in matrix.
A matrix is really just a vector with a dim attribute (for the dimensions). So you can add dimensions to vec using the dim() function and vec will then be a matrix:
vec <- 1:49
dim(vec) <- c(7, 7) ## (rows, cols)
vec
> vec <- 1:49
> dim(vec) <- c(7, 7) ## (rows, cols)
> vec
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1 8 15 22 29 36 43
[2,] 2 9 16 23 30 37 44
[3,] 3 10 17 24 31 38 45
[4,] 4 11 18 25 32 39 46
[5,] 5 12 19 26 33 40 47
[6,] 6 13 20 27 34 41 48
[7,] 7 14 21 28 35 42 49