I am creating a "nested" SpatialLinesDataFrame like so:

lines.list <- list()

id.vect <- c("A", "B", "C")

for (lines.index in 1:3) {
  line.list <- list()
  for (line.index in 1:2) {
    # create random path data:
    path <- matrix(data = rnorm(20), ncol = 2)
    # transform them to a line:
    line <- Line(path)
    # add to line list:
    line.list[[line.index]] <- line
  # convert the line list to a Lines object:
  lines <- Lines(slinelist = line.list, ID = id.vect[lines.index])
  # write to lines list:
  lines.list[[lines.index]] <- lines

# Convert the Lines list to a SpatialLines object:
spatial.lines <- SpatialLines(LinesList = lines.list)

# create a data frame with the Lines IDs:
id.df <- as.data.frame(x = id.vect, row.names = id.vect)
colnames(id.df) <- "Lines_ID"

# convert to SpatialLinesDataFrame:
spatial.lines.df <- SpatialLinesDataFrame(sl = spatial.lines,
                                          data = id.df,
                                          match.ID = T)

Which works perfectly fine. The SpatialLinesDataFrame looks like this:

enter image description here

However, when I write this SpatialLinesDataFrame to a shapefile and read it back in, like so:

# go to output directory:

# write output shapefile:
shapefile(x = spatial.lines.df, file = "output_shapefile.shp", overwrite = T)

# read the shapefile back in for comparison:
output.shapefile <- shapefile("output_shapefile.shp")

then the resulting SpatialLinesDataFrame (output.shapefile) looks different:

enter image description here

In particular, the Lines IDs have changed from 'A', 'B', 'C' to '0', '1', '2'. So I lost my originally defined IDs, likely while writing the shapefile. How can I prevent this?

Alternatively, is there a better way to create such a "nested" SpatialLinesDataFrame? My approach seems unhandy when even more levels need to be nested.

I am using R version 3.6.2 through RStudio version 1.2.5033 on macOS 10.14.6.

  • You should probably steer clear of the attribute name "ID" when working with shapefiles. Many implementations copy the Esri use pattern of generating a phantom integer field with a zero-based offset with that name. I suggest you use "LINE_ID" for the name of your character field. – Vince Sep 30 '20 at 12:37
  • Ok, how do I change this? I never used "ID" explicitly, it is just the name of the Lines() function argument. – Abdirizak Sep 30 '20 at 12:53
  • This suggests that slot names can't be changed. – Abdirizak Sep 30 '20 at 13:12

You can't prevent that happening easily. The values in those IDs aren't written to the shapefile. When the shapefile is read back, R will create new unique IDs for each unique item.

If you want to save and restore an R object identically, use saveRDS:

> saveRDS(spatial.lines.df, file = "out.RDS")
> testin = readRDS("out.RDS")
> identical(spatial.lines.df, testin)
[1] TRUE

which works for most R objects.

I don't see why this is "Nested", and I don't see the value in keeping an ID in the list of lines the same as a column in the data frame - once constructed the matching between lines and data frame rows is in the order of the items in the two slots.

  • As to the "nesting", imagine you have lines for households, which you want to group by municipality, then in turn group those by region, state, nation etc. So there should be a different level of grouping for every level of spatial aggregation, which should be reflected by the list structure of the SLDF. I was wondering if that is possible for an arbitrary number of levels. – Abdirizak Oct 1 '20 at 9:32
  • As to the IDs, is it therefore sufficient to keep them in a column in the data frame? – Abdirizak Oct 1 '20 at 9:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.