Is it possible to select a subset of a three dimensional array with a two-dimensional binary array? I would like to be able to do this so that I can push values into the selection
For example I have an array dim(a) = (lat, long, time), and I want to select with dim(b) = (lat, long) which is an array full of TRUE/FALSE values. I want to be able to do something like:
> a <- array(c(1,2,3,4,5,6,7,8),c(2,2,2))
> b <- matrix(c(0,1,0,0), c(2,2))==TRUE
> a[[b]] <- 0
> a
, , 1
[,1] [,2]
[1,] 1 3
[2,] 0 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 0 8
Edit : ok, so this looks like a stupid question, as I just realised that it works exactly as stated above, if you use a[b] <- 0 (single brackets). But that only works if the dimension(s) you want to span are the ones at the end. So, to make it more interesting:
How can you do this if the dimension you want to span is the first or second dimension - eg. if dim(b)==(lat, years)?
R supports matrix subsetting of arrays with the [ operator (i.e. single bracket, not double - the double bracket will always only return a single element):
a[b] <- 0
a
, , 1
[,1] [,2]
[1,] 1 3
[2,] 0 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 0 8
Notice that this is somewhat different from the result you specify in your question. In your question, the second element (i.e. bottom left element of the matrix) is 1, thus you would expect the second element of each array slice to be modified. (In other words not the first, as you have in your example.)
Related
I got many matrix of size 300*300, which are saved in a list, named L. This is binary matrix, i only have 0 and 1 values.
I plot image from those matrix (for exemple with c.img).
What is the best way to create a stack of those matrix? I want to create a new matrix, and or the pixel at the (i,j) position, i want to look in all my matrix saved in L, and if one or more matrix have a 1 at this position, then the (i,j) pixel in my new matrix will have value 1, else 0.
Here a pseudo code to help you understand my goal
L <- list(rep(matrix(0 or 1,300,300),n)
new_matrix<-matrix(0,300,300)
new_matrix[i,j]<- max(L[i,j])
but this code doesnt work because data is a list. I'm prety sure sure i can achieve this task using 3 loop (i,j,n), but because i got many matrix that'll take too long and i'm looking for a faster solution.
You can use :
matrix(as.numeric(Reduce(`+`, data) > 0), 300, 300)
Sum all matrix then convert values greater than 0 to 1 with as.numeric.
I would use a multi-dimensional array if all images are the same dimensions.
# Two matrices
m1 <- matrix(1,5,5)
m2 <- matrix(0,5,5)
# Placing them in an array (two matrices of dimension 5x5)
my_array <- array(c(m1,m2),dim = c(5,5,2))
# Investigating content of position 1,1 for matrices 1 to 2
my_array[1,1,1:2]
[1] 1 0
# You can even look at larger regions across matrices
> my_array[1:3,1:3,1:2]
, , 1
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 1 1 1
[3,] 1 1 1
, , 2
[,1] [,2] [,3]
[1,] 0 0 0
[2,] 0 0 0
[3,] 0 0 0
I'm trying to name a vector with only a single column, i.e. say I have
vector<-c(1,2,3,4)
I want to name a single column of (1,2,3,4) as "a", i.e. I want something like:
a
1
2
3
4
If I try
colnames(vector)<- c("a")
It gives me output:
Error in `colnames<-`(`*tmp*`, value = "a") :
attempt to set 'colnames' on an object with less than two dimensions
If I try
names(vector)<- c("a")
Vector is named as
a <NA> <NA> <NA>
1 2 3 4
My question is if such a vector is allowed in R? Specifically, is this allowed without using a matrix or data.frame or any other such class which can store more than one columns? If yes, how do I create it?
If you want something with a column name and that will print in the column format then use a single column matrix or data.frame:
vector <- matrix( c(1,2,3,4), dimnames=list(NULL, "a") )
vector <- data.frame( a=c(1,2,3,4) )
There is a 1d object type but rather confusingly it requires that the assignment of a single dimension value to be its length. See:
?dim
dim(vector)=1L
Error in dim(vector) = 1L :
dims [product 1] do not match the length of object [4]
> dim(vector)=4L
> vector
[1] 1 2 3 4
> str(vector)
num [1:4(1d)] 1 2 3 4
Actually the dim function help page doesn't appear to document the requirement that the product of the dim-result will equal the length. My guess is that your homework assignment was intended to get you to read the dim help page and then discover (as I just did) that a one-d object is possible but a bit confusing.
As it turns out the distinction between row and column vectors is not enforced:
> vector %*% matrix(1:16,4)
[,1] [,2] [,3] [,4]
[1,] 30 70 110 150
> t(vector) %*% matrix(1:16,4)
[,1] [,2] [,3] [,4]
[1,] 30 70 110 150
> t(vector) %*% matrix(1:16,4) %*% vector
[,1]
[1,] 1100
> vector %*% matrix(1:16,4) %*% vector
[,1]
[1,] 1100
This question already has an answer here:
Solve homogenous system Ax = 0 for any m * n matrix A in R (find null space basis for A)
(1 answer)
Closed 4 years ago.
I am using the pracma package, which contains the function nullspace(), returning normalized basis vectors of the Null(A):
> require(pracma)
> (A = matrix(c(1,2,3,4,5,6), nrow=2, byrow=T))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
> nullspace(A)
[,1]
[1,] 0.4082483
[2,] -0.8164966
[3,] 0.4082483
which is perfectly fine. However (don't ask), I want to quickly check the values I'd get if I were to produce the reduced row echelon form:
> rref(A)
[,1] [,2] [,3]
[1,] 1 0 -1
[2,] 0 1 2
and from there "manually" figure out the null space as
N(A) = [1, -2, 1]'
Yes, the latter is a scalar multiple of the former:
> c(1,-2,1)/nullspace(A)
[,1]
[1,] 2.44949
[2,] 2.44949
[3,] 2.44949
but I'd still like to get the latter, non-normalized form of a basis of the null space, as though the values were directly obtained from the reduced row echelon matrix.
You may want to try
B = rref(A)
solve(B[,1:2], -B[,3])
This gives you the combination your need for the first two columns to get one unit of the third column. Just add one to get your result.
Similarly for the case where size of null space is larger than one.
I was wondering if anyone could help me understand the output of this function. I know it's supposed to return the positions in which there is a run of length 2 but I am not exactly sure how to interpret the output.
fun1 = function(M,k) {
n = nrow(M)
m = ncol(M)
runs = vector('list',length=m)
for(i in 1:m) {
for(j in 1:(n-k+1)) {
if(all(M[j:(j+k-1),i]==1)) runs[[i]] = c(runs[[i]],j)
}
}
return(runs)
}
set.seed(123)
M = matrix(sample(0:1,size=15,replace=TRUE),ncol=3,nrow=5)
fun1(M,2)
Output:
[[1]]
[1] 4
[[2]]
[1] 2 3
[[3]]
[1] 3
Each element in the list is the output for a column, starting at the left-most column. The list of numbers (or NULL if there are none) gives you the row numbers in that column where there are two 1's in a row.
To interpret the sample output you have:
- In the first (left-most) column, there are two 1's starting at row 4 (M[4,1] and M[5,1] are 1)
- In the second column, there are two 1's starting at row 2 (meaning row 2 and row 3 are 1's) and also at row 3 (meaning row 3 and row 4 are 1's)
- In the third row, there are two 1's starting at row 3
You can check that this is true if you print our the matrix M, which given your seed looks like this
[,1] [,2] [,3]
[1,] 0 0 1
[2,] 1 1 0
[3,] 0 1 1
[4,] 1 1 1
[5,] 1 0 0
I hope that makes it clear.
By the way, in the future, try to format your code better with proper indentations and line breaks. I had to manually add line breaks to make the sample code work, but good job giving a seed :)
I would like to delete rows from a large matrix using the following criteria:
Any row that contains 100 in its second column should be removed.
How can this be done? I know how to select those rows but I'm not sure how to remove them using a rule.
R > mat = matrix(c(1,2,3,100,200,300), 3,2)
R > mat
[,1] [,2]
[1,] 1 100
[2,] 2 200
[3,] 3 300
R > (index = mat[,2] == 100)
[1] TRUE FALSE FALSE
R > mat[index, ]
[1] 1 100
R > mat[!index, ]
[,1] [,2]
[1,] 2 200
[2,] 3 300
Previously I was confused by the index with another method which, here is the solution by which:
R > (index2 = which(mat[,2] == 100))
[1] 1
R > mat[-index2, ]
[,1] [,2]
[1,] 2 200
[2,] 3 300
Watch out the different use for those index (! and -).
Here's how I would do it in Matlab with a matrix A.
Option 1
for (i=size(A,1):-1:0)
if (A(i,2)==100)
A(i,:)=[];
end
end
This loops over rows (starting at the bottom), and sets any row with 100 in the 2nd element to an empty set, which effectively deletes it.
Maybe you can convert this to r, or maybe it will help somebody else who is having this problem.
Option 2
logicalIndex=(A(:,2)==100);
A(logicalIndex,:)=[];
This first finds rows with 100 in the 2nd column, then deletes them all.