Adjust the values ​​of two variables row by row using the square spiral algorithm

I have a data.frame like this:

        X1       X2 n
1 -80.3845 43.19402 4
2 -80.3845 43.19402 4
3 -80.3845 43.19402 4
4 -80.3845 43.19402 4

      

You will notice that the values ​​are the same for every variable. What I am trying to do is create a new dataframe that is set up so that the X1 and X2 variables do not overlap. I need them to have a difference of 0.1. The final data file should look like this:

        X1       X2 n
1 -80.3845 43.19402 4
2 -80.3845 43.29402 4
3 -80.2845 43.29402 4
4 -80.2845 43.19402 4

      

This figure can help you visualize what is happening:

enter image description here

The values ​​represent longitudes and latitudes, and I kept the first point in place and then went up one place, then right one spot, and then one spot to number 4.

It's pretty easy to do it manually for a few lines, but when we add more points it gets more complicated. For any "n" the first line will remain with the same values, and the lines will snake clockwise. So for 8 lines it will look like this:

        X1       X2 n
1 -80.3845 43.19402 8
2 -80.3845 43.29402 8
3 -80.2845 43.29402 8
4 -80.2845 43.19402 8
5 -80.2845 43.09402 8
6 -80.3845 43.09402 8
7 -80.4845 43.09402 8
8 -80.4845 43.19402 8

      

The largest "n" I will have is around 400. My thought process is that I should try to calculate in advance what positions each number from 1-400 will have in a configuration like the images above. that is, they are ... -3, -2, -1,0,1,2,3, ... the rows / columns are away from the center point. Then use that to calculate the adjusted values ​​in X1 (which can be thought of as a coordinate for columns) and X2 (which can be thought of as a coordinate for rows) respectively.

Can anyone think of a better way to do this?

+3


source to share


1 answer


Here's a simple loop:

get_spiral <- function(orig,incr,n){

  ng   <- ceiling(sqrt(n))
  myg  <- -floor((ng-1)/2):ceiling((ng-1)/2)
  x0   <- which(myg==0)
  y0   <- which(myg==0)

  vecs <- lapply(orig,`+`,myg*incr)
  res  <- matrix(,n,2)

  x    <- 0
  y    <- 0
  goin <- "up"
  ring <- 0
  for (i in 1:n){
    res[i,] <- c(vecs[[1]][x0+x],vecs[[2]][y0+y])

    if(goin=="up"   ){y=y+1; if(y==  ring+1){ring=ring+1; goin="right"}; next}
    if(goin=="right"){x=x+1; if(x==  ring  ){             goin="down" }; next}
    if(goin=="down" ){y=y-1; if(y== -ring  ){             goin="left" }; next}
    if(goin=="left" ){x=x-1; if(x== -ring  ){             goin="up"   }; next}
  }
  res
}

      

Examples:



require(ggplot2)
mat<-get_spiral(c(10,10),1,22); df<-data.frame(mat); ggplot(df,aes(X1,X2))+geom_path()

      

Result from the example

+1


source







All Articles