Getting elements of a matrix with vectors of coordinates - r

This is a really basic question, but I can't seem to solve it or find an answer for it anywhere : suppose I have two vectors x,y of coordinates and a matrix m.
I would like a vector z such that z[i] = m[x[i],y[i]]for all i.
I tried z=m[x,y], but that creates a memory overflow. The vector and matrix are quite large so looping is pretty much out of the question. Any ideas ?

Use cbind. Here's a simple example:
mat <- matrix(1:25, ncol = 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
x <- 1:5
y <- c(2, 3, 1, 4, 3)
mat[cbind(x, y)]
# [1] 6 12 3 19 15
## Verify with a few values...
mat[1, 2]
# [1] 6
mat[2, 3]
# [1] 12
mat[3, 1]
# [1] 3
From ?Extract:
A third form of indexing is via a numeric matrix with the one column for each dimension: each row of the index matrix then selects a single element of the array, and the result is a vector. Negative indices are not allowed in the index matrix. NA and zero values are allowed: rows of an index matrix containing a zero are ignored, whereas rows containing an NA produce an NA in the result.

Another way is to use the fact that you can index a matrix as if it were a vector, with elements numbered in column-major form. Using the example from #AnandoMahto:
mat[x+nrow(mat)*(y-1)]
[1] 6 12 3 19 15

Related

Changing 2D Array in R. 1st Dimension is a Row Number, and 2nd Dimension is a Pixel with one dimension

I'm having some problem :
I have this matrix array :
The dimension is : [1] 27455 784
I want to transform the 2nd Dimension into 28 x 28 array
Basically I want to change it into Convolution2D Input Shape (n_samples, height, width, channels) for TensorFlow
The channels number is 1 because the image is in grayscale
How can I transform the 784 into 28x28 array and add another array as channels = 1 ?
Thanks a lot!
I try this :
# reshape 1-D data into 3-D data
train_x_img <- train_x
dim(train_x_img) <- c(27455, 28,28)
test_x_img <- test_x
dim(test_x_img) <- c(7172, 28,28,)
# check the dimensions of the 3-D data
dim(train_x_img)
But I guess it is wrong, because the value is not inserted in a correct order.
When R handles indexing for arrays or matrices, it assumes that the ordering as primarily on the columns. You, however, appear to want to create a 25 x 25 matrix-slice based on successive rows of that larger matrix, so the first thing to do is transpose so the row values are in columns columns:
train_x_img <- t( train_x ) # now 784 x 27455
Fold the previous row values, now in columns by re-dimensioning:
dim(train_x_img) <- c(28,28, 27455)
And now, because you want the third dimension to be recast as the first index, use base R's aperm function:
train_x_img <- aperm(train_x_img, c(3, 1,2)
Demonstration with a somewhat smaller object:
x <- matrix(1:24, 4, 6) # 4 x 6 example
x
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 5 9 13 17 21 # desire rows to be "folded"
[2,] 2 6 10 14 18 22
[3,] 3 7 11 15 19 23
[4,] 4 8 12 16 20 24
a <- t(x) # now 6 x 4
dim(a) <- c(2,3,4) # fold the first dimension in two smaller dimensions
a2 <- aperm(a, c(3,1,2)) # reorder the indices
Examine the first entries indexed by the first index
a2[1,,]
[,1] [,2] [,3]
[1,] 1 9 17
[2,] 5 13 21 # success, that matrix is composed of the first row of x

Obtain the names of rows of a matrix in which every element is greater than a value

x <- matrix (1:20,ncol=4)
rownames(x) <-c(letters[1:5])
x
[,1] [,2] [,3] [,4]
a 1 6 11 16
b 2 7 12 17
c 3 8 13 18
d 4 9 14 19
e 5 10 15 20
Now I would like to obtain the names of rows in which every element is greater than 3, i.e. "d" and "e"
One way to do this is to generate an index using apply and all({some expression}) and use that to subset your rownames. In this case:
idx <- apply(x, 1, function(x) all(x>3))
rownames(x)[idx]

R: How to convert a vector into matrix without replicating the vector?

Here's my problem:
I have a vector and I want to convert it into a matrix with fixed number of columns, but I don't want to replicate the vector to fill the matrix when it's necessary.
For example:
My vector has a length of 15, and I want a matrix with 4 columns.I wish to get the matrix wit 15 elements from the vector and a 0 for the last element in the matrix.
How can I do this?
Edit:
Sorry for not stating the question clearly and misguiding you guys with my example. In my program,I don't know the length of my vector, it depends on other parameters and this question involves with a loop, so I need a general solution that can solve many different cases, not just my example.
Thanks for answering.
You could subset your vector to a multiple of the number of columns (so as to include all the elements). This will add necessary amount of NA to the vector. Then convert to matrix.
x = 1:15
matrix(x[1:(4 * ceiling(length(x)/4))], ncol = 4)
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 2 6 10 14
#[3,] 3 7 11 15
#[4,] 4 8 12 NA
If you want to replace NA with 0, you can do so using is.na() in another step
We can also do this with dim<- and length<-
n <- 4
n1 <- ceiling(length(x)/n)
`dim<-`(`length<-`(x, n*n1), c(n1, n))
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 2 6 10 14
#[3,] 3 7 11 15
#[4,] 4 8 12 NA
data
x <- 1:15

Vector calculaitons in R - troubles

I have some troubles in calculations in R. I have a vector of few numbers, and one sequence of numbers (vector as well, i think). Now i need to power all numbers of first vector on first element of second vector, sum that numbers and go on with each element of the second vector. So my result would be a vector of the same number of elements as the second vector. But i dont know how to program this equation. This is just the first part of my calculations, but i thing i can solve the rest by myself.
Thanks for reply!
Like this?
x <- 1:5
y <- 1:3
res <- outer(x, y, "^")
# [,1] [,2] [,3]
# [1,] 1 1 1
# [2,] 2 4 8
# [3,] 3 9 27
# [4,] 4 16 64
# [5,] 5 25 125
colSums(res)
#[1] 15 55 225

Bind the rows of sheets in a 3d array to make a 2d array

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.

Resources