I'm stumped using indexing in R. I have two matrices, one with logical values and one with data. I want to use the first to index into the second one. However, I've noticed that R reorders my values when doing so.
My data looks roughly like this:
ind <- matrix(c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE), nrow = 3, ncol = 4, byrow = TRUE)
data <- matrix(c(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4), nrow = 3, ncol = 4, byrow = TRUE)
Now, when indexing result <- data[ind], I was obtaining the following: c(1, 3, 4) when I was trying to obtain c(1, 4, 3).
How can I prevent R from reordering columwise? I'd appreciate any input. I'm sure it's an easy fix - I just don't know which.
Thank you!
When converting matrices to and from vectors, R makes the transformation columnwise.
as.vector(data)
[1] 1 1 1 2 2 2 3 3 3 4 4 4
As this happens to both your ind and your data this is generally not a problem.
So to retain your order, you have to transpose both matrices:
> t(data)[t(ind)]
[1] 1 4 3
PS: have you tried which with a matrix?
> which(arr.ind = T, ind)
row col
[1,] 1 1
[2,] 3 3
[3,] 2 4
Here is another base R trick (but I recommend the answer by #c0bra)
> rowSums(data * ind)
[1] 1 4 3
Related
For the matrix M <- matrix(1:24, nrow = 6, ncol = 4), if you want to subset its elements by the index pairs, which are stored as rows in matrix indexes <- cbind(1:3, 2:4), you can do:
M[indexes]
# [1] 7 14 21
However, I haven't found a simple way to combine index pairs and index grids in slicing higher-dimensional arrays. For example, we have the array A <- array(1:24, dim = c(2,3,4), of which the first dimension should be kept and the last two dimensions are to be subsetted by index pairs. A wordy solution might be:
sapply(1:nrow(indexes), \(i) A[, indexes[i,1], indexes[i,2]])
# and structure the matrix back to the array form, if A has even higher dimension.
# [,1] [,2] [,3]
# [1,] 7 15 23
# [2,] 8 16 24
But I still want something as clean as
A[, indexes[,1], indexes[,2], pairwise = TRUE] # does it exist?
Update 1
Moreover, I have checked what the Numpy in Python has for their arrays, and I found the following example from this site:
X = np.arange(12).reshape((3, 4))
X
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
X[row, col]
# array([ 2, 5, 11])
X[row[:, np.newaxis], col] # broadcasting rules
# array([[ 2, 1, 3],
# [ 6, 5, 7],
# [10, 9, 11]])
The python version of the solution is quite simple and clear. In the same spirit,
As a result of seeing THIS EXAMPLE, I was wondering how I could create one set of 15 shuffled orderings of 1 through 4 in R?
On THIS Website, you can get 1 Set of 15 shuffled Numbers
Ranging: From 1 to 4
As an example, on my run I got:
Set #1:
3, 2, 2, 1, 1, 1, 3, 2, 2, 3, 2, 1, 3, 4, 1
Is there a way I can replicate the above in R?
If I understood correctly your question, at first it comes to mind a solution like the following one: very basic, but it does its job.
size <- 40
vec <- sample(1:4, size = size, replace = TRUE)
while(length(unique(vec)) < 4){
vec <- sample(1:4, size = size, replace = TRUE)
}
vec
The while cycle will not go on for long as it's very unlikely that a digit does not appear in the random vector vec if you sample 40 times.
Of course you can change the size of your vector, the code will still work, except you want vec to be < 4; in that case, the loop will go on indefinitely.
I have a matrix
1 2
1 3
I want to duplicate each columns three times to create a matrix like this:
1 1 1 2 2 2
1 1 1 3 3 3
I dont think I can use rep. Really appreciate any help
You can use rep in this situation, just not on the matrix itself.
This does what you want:
mat1 = cbind(c(1,1), c(2,3))
mat2 = mat1[, rep(1:2, each=3)]
You can actually do it with a single rep inside matrix.
m <- matrix(c(1, 1, 2, 2), nrow = 2)
matrix(rep(as.numeric(t(m)), each = 3), nrow = nrow(m), byrow = TRUE)
Depending on the size of your matrix this might be quicker than using apply.
Assuming your initial matrix is called m1, one option could be:
m2 <- matrix(data = apply(m1, 2, function(x) rep(x, 3)), ncol = ncol(m1)*3)
I have the following matrix
m <- matrix(c(2, 4, 3, 5, 1, 5, 7, 9, 3, 7), nrow=5, ncol=2,)
colnames(x) = c("Y","Z")
m <-data.frame(m)
I am trying to create a random number in each row where the upper limit is a number based on a variable value (in this case 1*Y based on each row's value for for Z)
I currently have:
samp<-function(x){
sample(0:1,1,replace = TRUE)}
x$randoms <- apply(m,1,samp)
which work works well applying the sample function independently to each row, but I always get an error when I try to alter the x in sample. I thought I could do something like this:
samp<-function(x){
sample(0:m$Z,1,replace = TRUE)}
x$randoms <- apply(m,1,samp)
but I guess that was wishful thinking.
Ultimately I want the result:
Y Z randoms
2 5 4
4 7 7
3 9 3
5 3 1
1 7 6
Any ideas?
The following will sample from 0 to x$Y for each row, and store the result in randoms:
x$randoms <- sapply(x$Y + 1, sample, 1) - 1
Explanation:
The sapply takes each value in x$Y separately (let's call this y), and calls sample(y + 1, 1) on it.
Note that (e.g.) sample(y+1, 1) will sample 1 random integer from the range 1:(y+1). Since you want a number from 0 to y rather than 1 to y + 1, we subtract 1 at the end.
Also, just pointing out - no need for replace=T here because you are only sampling one value anyway, so it doesn't matter whether it gets replaced or not.
Based on #mathematical.coffee suggestion and my edited example this is the slick final result:
m <- matrix(c(2, 4, 3, 5, 1, 5, 7, 9, 3, 7), nrow=5, ncol=2,)
colnames(m) = c("Y","Z")
m <-data.frame(m)
samp<-function(x){
sample(Z + 1, 1)}
m$randoms <- sapply(m$Z + 1, sample, 1) - 1
I'm sure this is trivial - nonetheless, any help would be appreciated.
The problem is simple: given a matrix, I'd like to get TRUE if the matrix in question has at least one element equal to zero. So, checking
A <- matrix(c(1, 2, 3, 4, 5, 0), nrow = 2, ncol = 3, byrow = TRUE)
> A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 0
would return TRUE, while
B <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3, byrow = TRUE)
> B
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
would return FALSE.
Something like
if ( A == 0 ) { cat("\nZero detected")}
gives a warning. Is there a simple way to do this?
The warning is generated because you're presenting a vector of logical to if, which expects a single value. any is a function to tell if any of the logical values are TRUE:
any(A==0)
## [1] TRUE
any(B==0)
## [1] FALSE
There's also a function all which determines if all of the values in a logical vector are TRUE.
Try
0 %in% A
It should return TRUE or FALSE. It works for NA too:
x = matrix(1:24, ncol = 4)
x[3, 3] = NA
NA %in% x
#TRUE