0

I'm trying to convert the nodes of a graphml file to an sf object in R. It works until I create the sfc object. Once I've added the attributes, R is no longer able to plot or do any operation with it.

library(igraph)
library(sf)

#read the graph
gi <- read.graph(
 "https://jospueyo.github.io/root/girona.graphml",
  format = "graphml")

#Extract coordinates and create id vector
x <- as.numeric(V(gi)$x)
y <- as.numeric(V(gi)$y)
id <- as.data.frame(seq(1:length(V(gi))))
 
#convert to sf object
nodes <- st_multipoint(cbind(x,y))
nodes <- st_sfc(nodes, crs=4326)
nodes <- st_sf(id, geometry = nodes)

#here it crashes
plot(st_geometry(nodes))

I tried with different graphs, obtained by different methods, and I got the same result.

Thank you.

Josep Pueyo
  • 387
  • 2
  • 11

2 Answers2

1

An alternative solution could be to use tidygraph as a mediator to convert the data into tibble structures that can be more easily passed to sf:

library(igraph)
library(sf)
library(tidygraph)

gi <- read_graph(
  "https://jospueyo.github.io/root/girona.graphml",
  format = "graphml")

(nodes <- as_tbl_graph(gi) %>% 
  activate("nodes") %>% 
  as_tibble() %>% 
  st_as_sf(coords = c('x', 'y'), crs = 4326))
#> Simple feature collection with 6362 features and 4 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 2.786515 ymin: 41.93955 xmax: 2.895689 ymax: 42.02881
#> geographic CRS: WGS 84
#> # A tibble: 6,362 x 5
#>    ref   highway osmid      id                    geometry
#>  * <chr> <chr>   <chr>      <chr>              <POINT [°]>
#>  1 ""    ""      2818883585 2818883585 (2.810092 41.97531)
#>  2 ""    ""      772161540  772161540   (2.814935 41.9714)
#>  3 ""    ""      2818883588 2818883588  (2.80979 41.97537)
#>  4 ""    ""      2818883590 2818883590 (2.810225 41.97548)
#>  5 ""    ""      772177927  772177927  (2.830774 41.98178)
#>  6 ""    ""      772227076  772227076  (2.850591 41.96948)
#>  7 ""    ""      1622622216 1622622216  (2.80656 41.96506)
#>  8 ""    ""      2818883593 2818883593 (2.809976 41.97563)
#>  9 ""    ""      800522251  800522251  (2.828536 41.98674)
#> 10 ""    ""      2818883592 2818883592 (2.810574 41.97554)
#> # ... with 6,352 more rows

plot(st_geometry(nodes))

loreabad6
  • 195
  • 1
  • 7
0

The error was because st_multipoint creates a single geometry with all the points, so when I created the sf object using a vector of length:6000 as attributes, it was forces to repeat 6000 times the same geometry of 6000 point 6000, resulting in an object of 36.000.000 points overlapping in 6.000 positions. Here is the solution to convert the nodes of a graph in an sf object:

library(igraph)
library(sf)

#read the graph
gi <- read.graph(
 "https://jospueyo.github.io/root/girona.graphml",
  format = "graphml")

#Extract coordinates and create id vector
x <- as.numeric(V(gi)$x)
y <- as.numeric(V(gi)$y)
id <- as.data.frame(seq(1:length(V(gi))))
colnames(id) <- "id"
 
#create the first sfc object
xi <- x[1]
yi <- y[1]
xyi <- cbind(xi,yi)
nodei <- st_point(xyi)
node_sfc <- st_sfc(nodei)

#add a new sfc for each pair of coordinates
for (i in 2:length(V(gi))){
  xi <- x[i]
  yi <- y[i]
  xyi <- cbind(xi,yi)
  nodei <- st_point(xyi)
  node_sfci <- st_sfc(nodei)
  node_sfc <- c(node_sfc, node_sfci)
  print(i)
}

#create sf object
st_crs(node_sfc) <- 4326
nodes <- st_sf(id, geometry = node_sfc)

I hope it would prevent someone else to do the same silly mistake than me.

Josep Pueyo
  • 387
  • 2
  • 11