Thanks for taking a look at my question.
I'm having some trouble with a nested for loop in R. The data I'm trying to loop through is a list of spatial lines items - sfc_linestring. There are 142 linestrings in total. I would like to rotate each linestring element 1000 times about it's centroid. Therefore I have an outer loop designed to loop over the 142 linestring elements and an inner loop designed to rotate each linestring element 1000 times. My code looks like this:
library(tidyverse)
library(sf)
library(sfheaders)
vlines_rotate<- st_sfc(st_linestring(matrix(c(0,0), 1000,2)),
st_linestring(matrix(c(0,0), 1000,2)))
theta=runif(n=142000, min=1, max=359)
for(i in seq_along(vlines_sfc)){
for(j in seq_along(theta)){
vlines_rotate[j]=(vlines_sfc[i]-
vlines_centroid[i])*rot(theta[j])+vlines_centroid[i]
}
}
where "vlines_sfc" is my 142 element linestring object, "vlines_centroid" is a list of 142 elements of sfc_point data corresponding to the centroid of each of the 142 linestring elements in "vlines_sfc", "theta" is a vector of values for the rotation of length 142,000 and "rot" is a predefined function to execute the rotation:
rot = function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)
When I run that code as is, it only loops over the first element of the "vline_sfc" list.
Here are three elements of the "vlines_sfc" list to help provide a reproducible example:
first:
structure(c(-8.04785755607144, -8.04785755455143,
-8.04791145480662,
-8.04819648729046, 52.6437603276574, 52.643758935097,
52.6435415730872,
52.6436586891848), .Dim = c(4L, 2L), .Dimnames = list(NULL, c("x",
"y")), class = c("XY", "LINESTRING", "sfg"))
second:
structure(c(-9.59085243559515, -9.59113171718261,
-9.59142986404616, -9.59178373602288, -9.59223453048505,
-9.59244593714847, -9.59275643486916, -9.59282667794028,
52.3098294867051, 52.3099104253679, 52.3099669079775,
52.309925838634, 52.3098350614709, 52.3096749090167,
52.3095255206016, 52.3092825718973), .Dim = c(8L, 2L), .Dimnames =
list(NULL, c("x", "y")), class = c("XY", "LINESTRING", "sfg"))
and third:
structure(c(-8.04123430428425, -8.04208275315675, -8.04302533321555,
-8.0443453420333, -8.0451940859463, -8.04657772707061,
-8.04811912935648, -8.04887424957855, 52.6418076510363,
52.6413674859761, 52.6407551588562, 52.6403339300028,
52.6402379861024, 52.6405625693178, 52.6413843131718,
52.6419003695025), .Dim = c(8L, 2L), .Dimnames = list(NULL, c("x",
"y")), class = c("XY", "LINESTRING", "sfg"))
And here are the corresponding centroid points, from the "vlines_centroid" list, for each of the above linestring elements:
first:
structure(c(-8.04798232118289, 52.6436215876677), class = c("XY",
"POINT", "sfg"))
second:
structure(c(-9.59193417120938, 52.309787085248), class = c("XY",
"POINT", "sfg"))
third:
structure(c(-8.04507115847921, 52.6408903075153), class = c("XY",
"POINT", "sfg"))
I have tried executing the loops individually and they work as expected; i.e. when running the outer loop alone with a basic function like "print" inside, it runs as you might expect. Similarly, when I run the inner loop and call individual elements of "vlines_sfc" object, i.e. substituting [i] for [1] or [2] etc, and reducing "theta" to 1000, this works perfectly. I therefore suspect this has something to do with how I've nested the loops(?). Other things I have tried include substituting "seq_along()" for "1:length()" in the outer loop but I get an identical result. I have also tried using double brackets around [[i]] to ensure the loop recognises that "vlines_sfc" and "vlines_centroid" are lists but to no success.
This is the first time I have attempted to nest for loops so would really appreciate any advice. I realise that for loops are not looked upon as 'good code' and I would appreciate an answer where I can achieve what I need through vectorisation but unfortunately I find for loops easier to understand and execute, so if you might have a way to vectorise this then please, if you can, could you also explain or help me understand how to go about it too.
Hopefully I have provided enough detail but please comment if not (I'm new to Stack Overflow). Thank you to the user that did comment and prompted me for more detail.
Many Thanks