Nested for-loop skips loops - r

this is my problem:
I have a grid (see plot below), and I need to get and store in a list the coordinates of each vertex of each block (cell). The order of blocks that I need is '1-1', ... '4-1', '1-2', ... '4-2'. To keep it simple I'm just working with the indexes for now.
Based on two vectors with the common East and North coordinates I've written a little function, which is partially producing the output that I need. It is skipping the cell '1-2' and '2-2' (see output below). I can't see where exactly is the error, but I suspect that the issue is in my nested for loop. (There are many questions on for loop, but none helped me with my problem).
Any help will be appreciated and apologise if this is too basic to be asked here.
vectors:
x.breaks <- c(191789.1, 291789.1, 391789.1)
y.breaks <- c(5172287, 5272287, 5372287, 5472287, 5572287)
Function:
getting_vertices <- function(x.breaks, y.breaks){
xs <- list()
ys <- list()
polys <- list()
for(i in 1 : (length(x.breaks)-1)){
xs[[i]] <- c(i, i+1 , i+1, i, i)
}
for(j in 1 : (length(y.breaks)-1)){
ys[[j]] <- c(j, j, j+1, j+1, j)
}
for(v in 1 : length(sapply(ys, length)) ){
for(k in 1: length(sapply(xs, length))){
polys[[v*k]] <- cbind(xs[[k]], ys[[v]])
}
}
return(polys)
}
getting_vertices(x.breaks, y.breaks)
Output (this is partially correct):
[[1]]
[,1] [,2]
[1,] 1 1
[2,] 2 1
[3,] 2 2
[4,] 1 2
[5,] 1 1
[[2]]
[,1] [,2]
[1,] 1 2
[2,] 2 2
[3,] 2 3
[4,] 1 3
[5,] 1 2
[[3]]
[,1] [,2]
[1,] 1 3
[2,] 2 3
[3,] 2 4
[4,] 1 4
[5,] 1 3
[[4]]
[,1] [,2]
[1,] 1 4
[2,] 2 4
[3,] 2 5
[4,] 1 5
[5,] 1 4
[[5]]
NULL
[[6]]
[,1] [,2]
[1,] 2 3
[2,] 3 3
[3,] 3 4
[4,] 2 4
[5,] 2 3
[[7]]
NULL
[[8]]
[,1] [,2]
[1,] 2 4
[2,] 3 4
[3,] 3 5
[4,] 2 5
[5,] 2 4

The logic behind the line polys[[v*k]] <- ... is incorrect, for example, v=2, k=1 will overwrite v=1, k=2. There are no combinations of v and k that make 5 or 7, hence these entries are empty.
I expect that you meant to write something like:
polys[[v+(k-1)*(length(ys))]] <- ...
or
polys[[k+(v-1)*(length(xs))]] <- ...
depending on the order that you want your results in

Related

Sort matrix based on the nearest distance between two coordinates

How can I sort matrix based on the nearest distance between two coordinates?
For example, I have this matrix :
> x
[,1] [,2]
[1,] 1 1
[2,] 3 9
[3,] 2 6
[4,] 2 8
I want the first row of the matrix will be somewhat an initial coordinate. After I calculate the distance manually between two coordinates, I found that x[1,] has the closest distance with x[3,]. Then, x[3,] has the closest distance with x[4,]. x[4,] has the closest distance with x[2,]. So the sorted matrix will be:
[,1] [,2]
[1,] 1 1
[2,] 2 6
[3,] 2 8
[4,] 3 9
I tried to write the R code below. But it did not work.
closest.pair <- c(NA,NA)
closest.distance <- Inf
for (i in 1:(n-1))
for (j in (i+1):n) {
dist <- sum((houses[i,]-houses[j,])^2)
if (dist<closest.distance) {
closest.pair <- c(i,j)
}
print(houses[closest.pair,])
}
Here is a possible solution using a loop:
## We determine the minimum distance between the coordinates at the current index cur
## and those at the remaining indexes ind
cur = 1;
ind = c(2:nrow(x));
## We put our resulting sorted indexes in sorted
sorted = 1;
while(length(ind)>=2){
pos = ind[which.min(rowSums((x[cur,]-x[ind,])^2))];
## At each iteration we remove the newly identified pos from the indexes in ind
## and consider it as the new current position to look at
ind = setdiff(ind,pos);
cur = pos;
sorted = c(sorted,pos)}
sorted = c(sorted,ind)
res = x[sorted,];
[,1] [,2]
[1,] 1 1
[2,] 2 6
[3,] 2 8
[4,] 3 9
You can use a for loop as shown below:
D=`diag<-`(as.matrix(dist(x)),NA)# Create the distance matrix, and give the diagonals NA values.
Then run a for loop
x[c(i<-1,sapply(1:(nrow(x)-1),function(j)i<<-which.min(D[i,]))),]
[,1] [,2]
[1,] 1 1
[2,] 2 6
[3,] 2 8
[4,] 3 9
This for-loop might seem weird! take a look:
m=c()
i=1
for(j in 1:(nrow(x)-1)){
i= which.min(D[i,])
m=c(m,i)
}
x[c(1,m),]
[,1] [,2]
[1,] 1 1
[2,] 2 6
[3,] 2 8
[4,] 3 9
you can also use Reduce
x[Reduce(function(i,j)which.min(D[,i]),1:(nrow(x)-1),1,,T),]
[,1] [,2]
[1,] 1 1
[2,] 2 6
[3,] 2 8
[4,] 3 9

represent nested for-loops for function with two parameters using same looping variables

I try to find a more efficient way to write that piece of code,
I considered apply, mapply and sweep, but I see no way how to rewrite it...
points.proj is m x k matrix, data.proj is n x k matrix.
So essentially I'd like to apply fun to each element of points.mat with the corresp. same columnnumber of the other matrix data.mat...the result should be an m x k matrix again.
for(i in 1:m){
for(j in 1:k){
Bounds[i,j] <- fun(points.proj[i,j],data.proj[,j])
}}
fun <- function(a,b) sum(a<b)
> points.proj
[,1] [,2]
[1,] 6 5
[2,] 7 6
[3,] 8 5
> data.proj
[,1] [,2]
[1,] 8 3
[2,] 2 0
[3,] 9 4
[4,] 6 7
[5,] 2 9
> Bounds
[,1] [,2]
[1,] 2 2
[2,] 2 2
[3,] 1 2
Thanks for helping

Data structure to hold multiple matrices

I have an array of strings which are actually names of datasets. I perform several measures on each dataset and get result of each measure in a matrix.
I want to save the results of one dataset in some data structure.
So, for example:
We have a string "glass".
From measurements on dataset "glass" I get 3 matrices a,b,c.
How could I save a,b,c in one structure?
Thanks.
Use a list.
> mydata <- list()
> mydata[[1]] <- matrix(1:4, 2, 2)
> mydata[[2]] <- matrix(1:10, 5, 2)
> mydata[[3]] <- matrix(1:16, 4, 4)
> mydata
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
[[3]]
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
>
> # To access the first matrix in the list...
> mydata[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
See ?list for more information.
Since they are the same size you can choose either list or a array. Dason showed the list option.
a=matrix(rnorm(16),nrow=4)
b=matrix(rnorm(16),nrow=4)
d=matrix(rnorm(16),nrow=4)
glass=array(c(a,b,d),dim=c(4,4,3))

R indexing issue

Sorry for vague question title, i couldn't figure out something more specific.
I have 3x2 matrix c:
> c
[,1] [,2]
[1,] 1 2
[2,] 1 3
[3,] 2 3
It is important that ncol(c) == 2.
I also have matrix ind:
> ind
[,1] [2] [,3] [,4]
[1,] 2 2 2 1
[2,] 1 1 2 2
[3,] 2 2 2 1
It is important that nrow(c) == nrow(ind), and that the values of matrix ind are 1 and 2 (like column indices for each row of c)
What i want to get is matrix a with same dim as ind such that a[i,j] == c[i,ind[i,j]]:
> a
[,1] [2] [,3] [,4]
[1,] 2 2 2 1
[2,] 1 1 3 3
[3,] 3 3 3 2
I can do something similar in less comprehensive situations, for example if nrow(c) == 1 i'll use apply:
> apply(c,2,function(x){return(matrix(x[ind], nrow(ind)))})
I know there is a way to iterate by 2 lists using mapply, but
1) i don't know what's the best way to represent matrix as list of rows
2) i fing this solution ugly
What is the best way to achieve what i descibed here?
Matrix indexing to the rescue!
> c.mat <- matrix(c(1,1,2,2,3,3), ncol=2)
> ind <- matrix(c(2,1,2,2,1,2,2,2,2,1,2,1), ncol=4)
> matrix(c.mat[cbind(as.vector(row(ind)), as.vector(ind))], ncol=ncol(ind))
[,1] [,2] [,3] [,4]
[1,] 2 2 2 1
[2,] 1 1 3 3
[3,] 3 3 3 2
f<-function(x,row1){
for(i in 1:length(x)){
x[i]=cc[i,ind[i,row1]]
}
x
}
a=apply(cc,1,f,nrow(a))
You can use apply like this. Note: cc is your c matrix

Construct dynamic-sized array in R

I was wondering about what are the ways to construct dynamic-size array in R.
For one example, I want to construct a n-vector but its dimension n is dynamically determined. The following code will work:
> x=NULL
> n=2;
> for (i in 1:n) x[i]=i;
> x
[1] 1 2
For another example, I want to construct a n by 2 matrix where the number of rows n is dynamically determined. But I fail even at assigning the first row:
> tmp=c(1,2)
> x=NULL
> x[1,]=tmp
Error in x[1, ] = tmp : incorrect number of subscripts on matrix
> x[1,:]=tmp
Error: unexpected ':' in "x[1,:"
Thanks and regards!
I think the answers you are looking for are rbind() and cbind():
> x=NULL # could also use x <- c()
> rbind(x, c(1,2))
[,1] [,2]
[1,] 1 2
> x <- rbind(x, c(1,2))
> x <- rbind(x, c(1,2)) # now extend row-wise
> x
[,1] [,2]
[1,] 1 2
[2,] 1 2
> x <- cbind(x, c(1,2)) # or column-wise
> x
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 1 2 2
The strategy of trying to assign to "new indices" on the fly as you attempted can be done in some languages but cannot be done that way in R.
You can also use sparse matrices provided in the Matrix package. They would allow assignments of the form M <- sparseMatrix(i=200, j=50, x=234) resulting in a single value at row 200, column 50 and 0's everywhere else.
require(Matrix)
M <- sparseMatrix(i=200, j=50, x=234)
M[1,1]
# [1] 0
M[200, 50]
# [1] 234
But I think the use of sparse matrices is best reserved for later use after mastering regular matrices.
It is possible to dimension the array after we fill it (in a one-dimensional, vector, fashion)
Emulating the 1-dimension snippet of the question, here's the way it can be done with higher dimensions.
> x=c()
> tmp=c(1,2)
> n=6
> for (i in seq(1, by=2, length=n)) x[i:(i+1)] =tmp;
> dim(x) = c(2,n)
> x
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 1 1 1
[2,] 2 2 2 2 2 2
>
Rather than using i:(i+1) as index, it may be preferable to use seq(i, length=2) or better yet, seq(i, length=length(tmp)) for a more generic approach, as illustrated below (for a 4 x 7 array example)
> x=c()
> tmp=c(1,2,3,4)
> n=7
> for (i in seq(1, by=length(tmp), length=n))
x[seq(i, length=length(tmp))] = tmp;
> dim(x) = c(length(tmp),n)
> x
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1 1 1 1 1 1 1
[2,] 2 2 2 2 2 2 2
[3,] 3 3 3 3 3 3 3
[4,] 4 4 4 4 4 4 4
>
We can also obtain a similar result by re-assigning x with cbind/rbind, as follow.
> tmp=c(1,2)
> n=6
> x=rbind(tmp)
> for (i in 1:n) x=rbind(x, tmp);
> x
[,1] [,2]
tmp 1 2
tmp 1 2
tmp 1 2
tmp 1 2
tmp 1 2
tmp 1 2
tmp 1 2
Note: one can get rid of the "tmp" names (these are a side effect of the rbind), with
> dimnames(x)=NULL
You can rbind it:
tmp = c(1,2)
x = NULL
rbind(x, tmp)
I believe this is an approach you need
arr <- array(1)
arr <- append(arr,3)
arr[1] <- 2
print(arr[1])
(found on rosettacode.org)
When I want to dynamically construct an array (matrix), I do it like so:
n <- 500
new.mtrx <- matrix(ncol = 2, nrow = n)
head(new.mtrx)
[,1] [,2]
[1,] NA NA
[2,] NA NA
[3,] NA NA
[4,] NA NA
[5,] NA NA
[6,] NA NA
Your matrix is now ready to accept vectors.
Assuming you already have a vector, you pass that to the matrix() function. Notice how values are "broken" into the matrix (column wise). This can be changed with byrow argument.
matrix(letters, ncol = 2)
[,1] [,2]
[1,] "a" "n"
[2,] "b" "o"
[3,] "c" "p"
[4,] "d" "q"
[5,] "e" "r"
[6,] "f" "s"
[7,] "g" "t"
[8,] "h" "u"
[9,] "i" "v"
[10,] "j" "w"
[11,] "k" "x"
[12,] "l" "y"
[13,] "m" "z"
n = 5
x = c(1,2) %o% rep(1,n)
x
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 1 1 1
# [2,] 2 2 2 2 2
x = rep(1,n) %o% c(1,2)
x
# [,1] [,2]
# [1,] 1 2
# [2,] 1 2
# [3,] 1 2
# [4,] 1 2
# [5,] 1 2

Resources