3

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'll notice the values are all the same in each variable. What I'm trying to do is to create a new dataframe that is adjusted so that the variables X1 and X2 do not overlap. I need them to have a difference of 0.1. The final dataframe 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 graphic might help to represent what's happening:

enter image description here

The values represent longitudes and latitudes and I have kept the first dot in place and then gone upwards one place, then to the right one spot, then down one spot to number 4.

This is pretty easy for a few rows to do manually, but when we add more dots it gets more complicated. For any 'n' the first row is going to remain with the same values and the rows will snake around in a clockwise fashion. Therefore, for 8 rows it would 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 highest number of 'n' I will have is about 400. My thought process is that I should try and calculate in advance what positions each number from 1-400 would be in in such a configuration as the images above. i.e. are they ... -3,-2,-1,0,1,2,3,... rows/columns away from the center point. Then use this to calculate the adjusted values in X1 (which can be thought of as the coordinate for columns) and X2 (which can be thought of as the coordinate for rows) accordingly.

Can anyone think of a better way of doing this?

jalapic
  • 13,792
  • 8
  • 57
  • 87
  • Not sure if you need them to all be completely different, but you could consider 'jittering' the points [see this](https://stat.ethz.ch/R-manual/R-devel/library/base/html/jitter.html) – Minnow May 22 '15 at 17:30
  • 2
    I just googled "square spiral algorithm". Judging from the preview pictures it might be relevant? – Henrik May 22 '15 at 17:33
  • @Henrik thanks - adjusted the title, that's exactly what I'm after – jalapic May 22 '15 at 17:50
  • Efficiency might be improved my mimicking some answers here: http://stackoverflow.com/questions/398299/looping-in-a-spiral I didn't really have a careful look. – Frank May 22 '15 at 17:58

1 Answers1

1

Here's a straightforward 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

Frank
  • 66,179
  • 8
  • 96
  • 180
  • Thanks, but I don't think that this is making a square spiral with large numbers of n, going outwards from the center in concentric squares - perhaps I'm missing something - e.g. `df<-get_spiral(c(10,10),1,20); df <- data.frame(df); ggplot(df,aes(X1,X2)) + geom_path()` – jalapic May 22 '15 at 18:39
  • @jalapic Okay, I think it's fixed. I just added another variable tracked in the loop for the current "ring", and changed `x` and `y` to iterate over `myg` instead of `seq_along(myg)` as they did before. – Frank May 22 '15 at 19:27