ggplot 不从 sf 对象绘制线串点
ggplot not plotting linestring points from sf object
给定以下数据:
library(tidyverse)
library(sf)
df <- structure(list(geometry = c("LINESTRING (-85.76 38.34, -85.72 38.38)",
"LINESTRING (-85.46 38.76, -85.42 38.76)",
"LINESTRING (-85.89 38.31, -85.89 38.31)"
), var1 = c(4, 5, 6
), var2 = c(1, 2, 3
)), row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame"
))
df
df_sf <- sf::st_as_sf( df, wkt = "geometry" )
# Simple feature collection with 3 features and 2 fields
# geometry type: LINESTRING
# dimension: XY
# bbox: xmin: -85.89 ymin: 38.31 xmax: -85.42 ymax: 38.76
# CRS: NA
# # A tibble: 3 x 3
# geometry var1 var2
# <LINESTRING> <dbl> <dbl>
# 1 (-85.76 38.34, -85.72 38.38) 4 1
# 2 (-85.46 38.76, -85.42 38.76) 5 2
# 3 (-85.89 38.31, -85.89 38.31) 6 3
我们可以使用 plot
绘制数据,包括 LINESTRING
在同一位置(行 = 3)有两个点:
plot(st_geometry(df_sf), lwd = 10)
给予:
但是当我们使用 ggplot
绘制它时,点被删除了:
ggplot() +
geom_sf(data = df_sf, lwd = 8)
在不手动提取仅包含一个点的位置的情况下,是否有一种快速的方法告诉 ggplot
绘制这些位置?我可以看到这些点在技术上不是一条线,因为它们之间没有距离,但 plot
能够拾取它们。这个 似乎相关但略有不同,我的 LINESTRING
已经创建了。
谢谢
我认为,如果修改长度等于 0 的 LINESTRING 几何图形并将它们转换为 POINTS,则可以解决该问题。例如:
# packages
library(ggplot2)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
# data
df <- structure(
list(
geometry = c(
"LINESTRING (-85.76 38.34, -85.72 38.38)",
"LINESTRING (-85.46 38.76, -85.42 38.76)",
"LINESTRING (-85.89 38.31, -85.89 38.31)"
),
var1 = c(4, 5, 6),
var2 = c(1, 2, 3)
),
row.names = c(NA, -3L),
class = c("tbl_df", "tbl", "data.frame")
)
df_sf <- st_as_sf( df, wkt = "geometry" )
# Rebuild the geometry column in such a way that the zero-length LINESTRINGS are
# actually POINTS:
new_df_sf_geometry <- st_geometry(df_sf)
idx <- which(st_length(new_df_sf_geometry) == 0)
for (i in idx) {
new_df_sf_geometry[i] <- unique(st_cast(new_df_sf_geometry[i], "POINT"))
}
# This is the result
new_df_sf_geometry
#> Geometry set for 3 features
#> geometry type: GEOMETRY
#> dimension: XY
#> bbox: xmin: -85.89 ymin: 38.31 xmax: -85.42 ymax: 38.76
#> CRS: NA
#> LINESTRING (-85.76 38.34, -85.72 38.38)
#> LINESTRING (-85.46 38.76, -85.42 38.76)
#> POINT (-85.89 38.31)
# Replace the geometry
st_geometry(df_sf) <- new_df_sf_geometry
# Plot
ggplot(df_sf) +
geom_sf(size = 3)
由 reprex package (v0.3.0)
于 2020-05-25 创建
如果需要,您还可以采用比 for 循环更复杂的方法,例如 purrr::map_if
。
这是头台表情符号可能派上用场的情况之一:
ggplot() +
geom_sf(data = df_sf, lwd = 8, lineend = "round")
从包的 vignette on aesthetic specs 来看,默认的 lineend 是“butt”,它精确地停在一行的终点(因此长度为 0 的行不会显示任何内容),而“圆形”替代方案超出终点:
TL;DR:未删除长度为 0 的线串。我们只是看不到它。
给定以下数据:
library(tidyverse)
library(sf)
df <- structure(list(geometry = c("LINESTRING (-85.76 38.34, -85.72 38.38)",
"LINESTRING (-85.46 38.76, -85.42 38.76)",
"LINESTRING (-85.89 38.31, -85.89 38.31)"
), var1 = c(4, 5, 6
), var2 = c(1, 2, 3
)), row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame"
))
df
df_sf <- sf::st_as_sf( df, wkt = "geometry" )
# Simple feature collection with 3 features and 2 fields
# geometry type: LINESTRING
# dimension: XY
# bbox: xmin: -85.89 ymin: 38.31 xmax: -85.42 ymax: 38.76
# CRS: NA
# # A tibble: 3 x 3
# geometry var1 var2
# <LINESTRING> <dbl> <dbl>
# 1 (-85.76 38.34, -85.72 38.38) 4 1
# 2 (-85.46 38.76, -85.42 38.76) 5 2
# 3 (-85.89 38.31, -85.89 38.31) 6 3
我们可以使用 plot
绘制数据,包括 LINESTRING
在同一位置(行 = 3)有两个点:
plot(st_geometry(df_sf), lwd = 10)
给予:
但是当我们使用 ggplot
绘制它时,点被删除了:
ggplot() +
geom_sf(data = df_sf, lwd = 8)
在不手动提取仅包含一个点的位置的情况下,是否有一种快速的方法告诉 ggplot
绘制这些位置?我可以看到这些点在技术上不是一条线,因为它们之间没有距离,但 plot
能够拾取它们。这个 LINESTRING
已经创建了。
谢谢
我认为,如果修改长度等于 0 的 LINESTRING 几何图形并将它们转换为 POINTS,则可以解决该问题。例如:
# packages
library(ggplot2)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
# data
df <- structure(
list(
geometry = c(
"LINESTRING (-85.76 38.34, -85.72 38.38)",
"LINESTRING (-85.46 38.76, -85.42 38.76)",
"LINESTRING (-85.89 38.31, -85.89 38.31)"
),
var1 = c(4, 5, 6),
var2 = c(1, 2, 3)
),
row.names = c(NA, -3L),
class = c("tbl_df", "tbl", "data.frame")
)
df_sf <- st_as_sf( df, wkt = "geometry" )
# Rebuild the geometry column in such a way that the zero-length LINESTRINGS are
# actually POINTS:
new_df_sf_geometry <- st_geometry(df_sf)
idx <- which(st_length(new_df_sf_geometry) == 0)
for (i in idx) {
new_df_sf_geometry[i] <- unique(st_cast(new_df_sf_geometry[i], "POINT"))
}
# This is the result
new_df_sf_geometry
#> Geometry set for 3 features
#> geometry type: GEOMETRY
#> dimension: XY
#> bbox: xmin: -85.89 ymin: 38.31 xmax: -85.42 ymax: 38.76
#> CRS: NA
#> LINESTRING (-85.76 38.34, -85.72 38.38)
#> LINESTRING (-85.46 38.76, -85.42 38.76)
#> POINT (-85.89 38.31)
# Replace the geometry
st_geometry(df_sf) <- new_df_sf_geometry
# Plot
ggplot(df_sf) +
geom_sf(size = 3)
由 reprex package (v0.3.0)
于 2020-05-25 创建如果需要,您还可以采用比 for 循环更复杂的方法,例如 purrr::map_if
。
这是头台表情符号可能派上用场的情况之一:
ggplot() +
geom_sf(data = df_sf, lwd = 8, lineend = "round")
从包的 vignette on aesthetic specs 来看,默认的 lineend 是“butt”,它精确地停在一行的终点(因此长度为 0 的行不会显示任何内容),而“圆形”替代方案超出终点:
TL;DR:未删除长度为 0 的线串。我们只是看不到它。