Search code examples
rmetaprogrammingr-sfquoting

Mutating the data a variable is pointing to in a for-loop in R


I don't know id the heading of this question is very adequate, but the issue is the following. I have lately been trying how non-standard evaluation in R works, but apparently I do not understand a lot...

This is an example with "spatial" data, but I guess it applies more generally too. So I this variable named nc and replicate it three times to get a vector of spatial datasets. Lets pretend they are different datasets.

nc = st_read(system.file("shape/nc.shp", package="sf"))
ncs = c(nc,nc,nc)

I then want to perform a operation on each element of this vector (I want to change its coordinate reference system in this case) and change the actual data?! the name is pointing to. So when I do the following, it not only appears to be complete rubbish, but it also does not work.

for (d in ncs) {
 d = st_transform(d, crs=4326) 
}

Instead of mutating each object in ncs I create one new object called d, which is actually transformed.

Of course I could do it 3 x manually:

ncs[[1]] = st_transform(ncs[[1]], crs=4326)
#...

But this is not the point. How could I solve this in the for-loop? I guess there needs to be some quoting, unquoting... But not really sure.


Solution

  • If you store your items a in a list

    library(sf)
    nc = st_read(system.file("shape/nc.shp", package="sf"))
    ncs = list(nc,nc,nc)
    

    Then you can use lapply to apply a function to each item in the list

    nsc <- lapply(ncs, st_transform, crs=4326)
    

    In R, it's usually a lot easier to use an apply function or mapping function that manually write the for loop. No need for metaprogramming or quoting for tasks like these.

    If you insist on using a loop, again, you want to make sure your items are in a list, and on each iteration, you'll need to explicitly update the item in the list

    for (i in seq_along(ncs)) {
      nc[[i]] <- st_transform(ncs[[i]], crs=4326)
    }