Strange behavior of apply/ reverse function in R - r

I have a simple matrix:
mat = rbind(c(1:3),c(4:6),c(7:9))
mat
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# [3,] 7 8 9
I want to now reverse the matrix row-wise. That is I want to obtain:
revMat
# [,1] [,2] [,3]
# [1,] 3 2 1
# [2,] 6 5 4
# [3,] 9 8 7
To do this I tried
apply(mat, 1, rev)
And the result was:
# [,1] [,2] [,3]
# [1,] 3 6 9
# [2,] 2 5 8
# [3,] 1 4 7
I find this to be extremely strange. It's like the rows are reversed and then the final matrix is transposed. I don't understand why. If I try simply, for instance,
apply(mat, 2, rev)
it gives me the expected reversal of each column
# [,1] [,2] [,3]
# [1,] 7 8 9
# [2,] 4 5 6
# [3,] 1 2 3
Therefore to obtain the final result I have to perform
t(apply(t(bg), 2, rev))
Thus obtaining the required matrix is NOT a problem for me, but I don't understand the "anomaly" in the behavior of apply/ reverse. Can anyone explain this to me?
Edit: To make clear the distinction, I already know how to do the reversal. I want to know WHY this happens. How to is clear from many earlier questions including
How to reverse a matrix in R?

apply always puts the result in the first dimension. See ?apply for more information. Assuming this input:
mat <- matrix(1:9, 3, byrow = TRUE)
here are some alternatives:
1) transpose
t(apply(mat, 1, rev))
2) avoid apply with indexing
mat[, 3:1]
3) iapply An idempotent apply was posted here:
https://stat.ethz.ch/pipermail/r-help/2006-January/086064.html
Using that we have:
iapply(mat, 1, rev)
There was also an idempotent apply, iapply, in version 0.8.0 of the reshape package (but not in the latest version of reshape): https://cran.r-project.org/src/contrib/Archive/reshape/
4) rollapply rollapply in the zoo package can be used:
library(zoo)
rollapply(mat, 1, rev, by.column = FALSE)
5) tapply The tapply expression here returns a list giving us the opportunity to put it together in the way we want -- in this case using rbind:
do.call("rbind", tapply(mat, row(mat), rev))
6) multiply by a reverse diagonal matrix Since rev is a linear operator it can be represented by a matrix:
mat %*% apply(diag(3), 1, rev)
or
mat %*% (row(mat) + col(mat) == 3+1)

If you look at the help for apply(), this is exactly the behavior you would expect:
Value
If each call to FUN returns a vector of length n, then apply returns
an array of dimension c(n, dim(X)[MARGIN]) if n > 1.
a nice option to do what you want is to use indexing:
mat[,ncol(mat):1]

Related

Select one data point per row using indexing vector with negative values

Suppose you have a matrix a
a <- matrix(1:9, 3, 3)
a
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
and a vector b indicating which element of each row you want to extract. That is, the vector b indicates the column of the element, for instance:
b <- c(1, 3, 1)
If we want to extract the indicated data points, we can simply index each desired element like this:
a[cbind(1:nrow(a),b)]
[1] 1 8 3
I would like to do it with a negative index vector. That is, R should return a matrix where exactly one element per row is omitted (in this case, a 3x2 matrix). If I try it in a naive approach, R throws an error:
c = -b
a[cbind(1:nrow(a),c)]
Error in a[cbind(1:nrow(a), c)] :
negative values are not allowed in a matrix subscript
Thank you!
Not pretty, but you could do
b <- c(1, 3, 1) + 3 * 0:2
matrix(c(t(a))[-b], 3, 2, byrow = TRUE)
Maybe this is another naive approach. We loop over every row in the matrix and remove index specified in b.
t(sapply(seq_len(nrow(a)), function(x) a[x, -b[x]]))
# [,1] [,2]
#[1,] 4 7
#[2,] 2 5
#[3,] 6 9
Or using mapply with split
t(mapply(`[`, split(a, seq_len(nrow(a))), -b))

Forcing matrix to have even dimensions without conditional

I am looking for a clever way to force the dimensions (both nrow and ncol) of a matrix to be even without using an if statement. By force I mean subtract the first appropriate column and/or row so that both dimensions are even.
I was hoping something like this would work:
## build a matrix with odd number of columns and even number of rows
x=matrix(1:12,nrow=4,ncol=3)
## we can check which (if any) dimensions are odd with
dim(x) %% 2 ## 0,1
## I would like get a matrix that looks like
[,1] [,2]
[1,] 5 9
[2,] 6 10
[3,] 7 11
[4,] 8 12
## By using something similar to
x.even = x[-nrow(x)%%2,-ncol(x)%%2]
Obviously the last line does not give the desired result. Is there a clever way to do this without using a conditional?
Just divide nrow and ncol by 2, take floor, and multiply by 2 again
x.even = x[1:(2*floor(nrow(x)/2)),1:(2*floor(ncol(x)/2))]
One way that builds on your solution:
#start rows and columns from 1
#also subtract remainder from total rows and columns
x[1:(nrow(x) - nrow(x) %% 2), 1:(ncol(x) - ncol(x) %% 2)]
output:
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8

Reshape each row of a data.frame to be a matrix in R

I am working with the hand-written zip codes dataset. I have loaded the dataset like this:
digits <- read.table("./zip.train",
quote = "",
comment.char = "",
stringsAsFactors = F)
Then I get only the ones:
ones <- digits[digits$V1 == 1, -1]
Right now, in ones I have 442 rows, with 256 column. I need to transform each row in ones to a 16x16 matrix. I think what I am looking for is a list of 16x16 matrix like the ones in this question:
How to create a list of matrix in R
But I tried with my data and did not work.
At first I tried ones <- apply(ones, 1, matrix, nrow = 16, ncol = 16) but is not working as I thought it was. I also tried lapply with no luck.
An alternative is to just change the dims of your matrix.
Consider the following matrix "M":
M <- matrix(1:12, ncol = 4)
M
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
# [2,] 2 5 8 11
# [3,] 3 6 9 12
We are looking to create a three dimensional array from this, so you can specify the dimensions as "row", "column", "third-dimension". However, since the matrix is constructed by column, you first need to transpose it before changing the dimensions.
`dim<-`(t(M), c(2, 2, nrow(M)))
# , , 1
#
# [,1] [,2]
# [1,] 1 7
# [2,] 4 10
#
# , , 2
#
# [,1] [,2]
# [1,] 2 8
# [2,] 5 11
#
# , , 3
#
# [,1] [,2]
# [1,] 3 9
# [2,] 6 12
though there are probably simple ways, you can try with lapply:
ones_matrix <- lapply(1:nrow(ones), function(i){matrix(ones[i, ], nrow=16)})

Meaning of %o% in R

I encountered the following in R:
x=x+y%o%c(1.5,1.5)
I am wondering what is the meaning of %o% here. I tried googling but didn't have much luck
There are a number of shortcuts in R that use the %...% notation. %o% is the outer product of arrays
> 1:3 %o% 1:3
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 4 6
[3,] 3 6 9
There are a number of others, my most used is %in%:
3 %in% c(1,2,3,4) #TRUE
5 %in% c(1,2,3,4) #FALSE
3.4 %in% c(1,2,3,4) #FALSE
There are a few others, I don't know them all off the top of my head. But when you encounter them, you can check for documentation by using backticks around the %o% like ?`%o%`, or quotes ?'%o%' (or ?"%o%").
They are obviously difficult to google because of the percent sign.
An intuition. %o% is outer product, look at the example, it returns a matrix. a[1] * b is the first row of matrix, a[2] * b is the second row of the matrix.
> a = c(1, 2, 3)
> b = c(0, 2, 4)
> a %o% b
[,1] [,2] [,3]
[1,] 0 2 4
[2,] 0 4 8
[3,] 0 6 12

How to apply function to each of the vectors in the vertical (3rd) direction of an array in R?

I'm new to the R language and is now stuck with a simple question.
Say I've got an array: A <- array(1:12, c(2, 2, 3)). I would like to use "apply" to calculate the mean of the elements in each of the 4 vectors in the vertical (3rd) dimension. (i.e. the result would be a 2 by 2 matrix)
The answer in this case should be:
[,1] [,2]
[1,] 5 7
[2,] 6 8
I've only come up with the idea of using 2 for loops to calculate the mean for 4 times. However since my array is very big, I was wondering is there a simple way to use "apply" to achieve this?
You are looking for this:
> apply(A, c(1,2), mean)
[,1] [,2]
[1,] 5 7
[2,] 6 8
Edit
If you want to get the means of each column in each of the 3 matrices, then try:
> apply(A, 2:3, mean)
[,1] [,2] [,3]
[1,] 1.5 5.5 9.5
[2,] 3.5 7.5 11.5
Note that the index in apply are 1 is for rows (the first dimension of an array), 2 is for columns (the second dimension of an array) and 3 is for the third dimension of your array

Resources