Due to a problem loading large osm files in osmar, I have decided to split my osm file in small parts, load them individually and the merge them.

I currently face two problems :

  1. The code splitting the osm file tends to "lose" data around the bounding box. Therefore, I can't merge the objects afterwards because I have lost information in the process. This is done using osmconvert : osmconvert filename.osm -b=4,44,5,45 -o=filename_out.osm for your information.
  2. To solve this, I now take a margin around each bounding box to make sure I don't lose nodes or ways. Consequently, I have to merge objects with overlapping nodes / ways in some cases. This is done with c() applied to objects of class osmar. And the result is not satisfying (see images below, with a map split in 3*3 tiles and then combined again) : the normal map and the map with errors

The code used to display these maps is spplot(as_sp(osmar_object, "lines"), zcol=4) for your information.

How am I supposed to merge these files ? Should I find a way to merge osm files with overlapping nodes and ways or should I learn a better way to split the file than osmconvert ?

I'm opened to any approach, including switching to sp objects if needed.

1 Answer 1


I managed to merge osmar objects with 99% accuracy, and would like to share my code with you. The idea is to rewrite the c() function in order to manually group the dataframes inside of osmar objects.

Warning : In the code below, relations are completely ignored because I don't use them. Those of you willing to properly use relations should adapt the code accordingly.

# This is the equivalent of the c function for osmar objects
# l : list of objects of class "osmar"
osmar_c_list <- function(l, verbose = F) {

  # C is the result of the script. We initialise it as l[[1]], but will rewrite its components
  c <- first(l) 

  # Data.table does not like POSIXlt, so we have to convert timestamps
  l <- lapply(X = l, FUN = function(elem) {
    elem$nodes$attrs$timestamp     <- as.POSIXct(elem$nodes$attrs$timestamp)
    elem$ways$attrs$timestamp      <- as.POSIXct(elem$ways$attrs$timestamp)
    elem$relations$attrs$timestamp <- as.POSIXct(elem$relations$attrs$timestamp)

  # The idea here is to rbind every dataframe in the osmar object
  # After that, we call the "unique" function to make sure we don't add the same object twice
  c$nodes$attrs      <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$nodes$attrs    )))
  c$nodes$tags       <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$nodes$tags     )))
  c$ways$attrs       <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$ways$attrs     )))
  c$ways$tags        <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$ways$tags      )))
  c$ways$refs        <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$ways$refs      )))
  c$relations$attrs  <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$relations$attrs)))
  c$relations$tags   <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$relations$tags )))
  c$relations$refs   <- unique(rbindlist(lapply(X = l, FUN = function(elem) elem$relations$refs )))

  # Calling the unique function was not without problem though. Indeed, in the case of a loop
  # i.e. a road from node A to node A, we have destroyed the last segment.
  # Let's detect duplicated nodes in ways and append them

  duplic_i    <- rbindlist(lapply(X = l, FUN = function(elem) elem$ways$refs[duplicated(elem$ways$refs),]))
  c$ways$refs <- rbind(c$ways$refs, unique(duplic_i))
  c$ways$refs <- c$ways$refs[order(c$ways$refs$id),]

  # Lets go back to POSIXlt
  c$nodes$attrs     <- data.frame(c$nodes$attrs)
  c$ways$attrs      <- data.frame(c$ways$attrs)
  c$relations$attrs <- data.frame(c$relations$attrs)
  c$nodes$attrs$timestamp     <- as.POSIXlt(c$nodes$attrs$timestamp)
  c$ways$attrs$timestamp      <- as.POSIXlt(c$ways$attrs$timestamp)
  c$relations$attrs$timestamp <- as.POSIXlt(c$relations$attrs$timestamp)


Warning : This code produces 99% accuracy for me, not 100%. I advise against using it as-is if your application requires high levels of accuracy.

Final note, I use this code to merge files with overlapping bounding boxes. I don't think it would work without some overlap.

  • Im facing the same issue ie limitation of R to load big osm files. I realize its long ago since this question been answered but maybe you still read it: have you made some progress in this area? also @VeilleData writes that this script ignors relations but i see you rbind them. Do i miss something? BR
    – Andreas
    Jul 18, 2020 at 1:06

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.