I'm currently studying the basics of GIS with R at this link. I'm at Vector Data > Lines section and I'm experiencing something that looks like a bug when trying to plot some LINESTRING objects with ggspatial
package.
Below my code:
library(ggplot2)
library(ggspatial)
library(patchwork)
#### 3 LINESTRING OBJECTS
l1 <- matrix(c(10,10,10,12,14,16,15,10), ncol = 2, byrow = T) |> sf::st_linestring()
l2 <- matrix(c(14,16,10,19), ncol = 2, byrow = T) |> sf::st_linestring()
l3 <- matrix(c(10,12,5,13), ncol = 2, byrow = T) |> sf::st_linestring()
#### SF OBJECT WITH GEOMETRIES, CRS AND ATTRIBUTES
line_sfc <- sf::st_sfc(l1,l2,l3, crs = 4326)
l_att <- data.frame(road_name = c("Viale Garibaldi", "Via Voltaire", "Viale Pasolini"),
speed_limit = c(75, 50, 30))
line_sf <- sf::st_sf(l_att, line_sfc)
line_sf
## Simple feature collection with 3 features and 2 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: 5 ymin: 10 xmax: 15 ymax: 19
## Geodetic CRS: WGS 84
## road_name speed_limit line_sfc
## 1 Viale Garibaldi 75 LINESTRING (10 10, 10 12, 1...
## 2 Via Voltaire 50 LINESTRING (14 16, 10 19)
## 3 Viale Pasolini 30 LINESTRING (10 12, 5 13)
Now, if I use base plot()
function as shown in the GIS crash course I linked above, the plot works as intended.
plot(line_sf)
But when I use ggplot2
and ggspatial
packages, a 4th line is added to speed_limit plot, and I really don't know why.
sp_df <- ggspatial::df_spatial(line_sf)
p1 <- ggplot2::ggplot(sp_df, aes(x,y)) +
ggspatial::geom_spatial_path(aes(colour = road_name)) +
ggspatial::coord_sf(crs = 4326) +
xlab("lon") +
ylab("lat") +
ggtitle("road_name")
p2 <- ggplot2::ggplot(sp_df, aes(x,y)) +
ggspatial::geom_spatial_path(aes(color = speed_limit)) +
ggspatial::coord_sf(crs = 4326) +
xlab("lon") +
ylab("lat") +
ggtitle("speed_limit")
p1 / p2
What's the problem here? Where that additional line comes from? Am I doing something wrong or is this a bug? Any help is appreciated.
You seem to be doing things the hard way, since ggplot has excellent sf
support. Rather than loading an extra dependency, using extra code and converting to a data frame, why not simply plot the sf
object directly?
p1 <- ggplot(line_sf) +
geom_sf(aes(geometry = line_sfc, color = road_name)) +
labs(title = "road_name", x = "lon", y = "lat")
p2 <- ggplot(line_sf) +
geom_sf(aes(geometry = line_sfc, color = speed_limit)) +
labs(title = "speed_limit", x = "lon", y = "lat")
p1 / p2
If you have good reasons for converting to a data frame, the alternative is to group the second plot by road name so that adjacent groups aren't connected:
sp_df <- ggspatial::df_spatial(line_sf)
p1 <- ggplot2::ggplot(sp_df, aes(x,y)) +
ggspatial::geom_spatial_path(aes(colour = road_name)) +
ggspatial::coord_sf(crs = 4326) +
xlab("lon") +
ylab("lat") +
ggtitle("road_name")
ggplot2::ggplot(sp_df, aes(x,y)) +
ggspatial::geom_spatial_path(aes(color = speed_limit, group = road_name)) +
ggspatial::coord_sf(crs = 4326) +
xlab("lon") +
ylab("lat") +
ggtitle("speed_limit")
p1 / p2