我正在尝试使用 Highcharter 包在 R 中创建世界地图。目标是绘制圣保罗与前 10 个出口目的地之间的连接(线),每个连接由地图上的一条线(地图线类型)表示。但是,线条未显示。
我尝试了多种方式格式化数据,但线条仍然没有显示在地图上。下面是我正在使用的代码,以及数据集结构和我的预期输出的描述。
# df
top_destinations <- tibble(
Cidade = rep("São Paulo - SP", 10),
Nome_Pais = c("China", "Canadá", "Estados Unidos", "Itália", "Bélgica",
"Emirados Árabes Unidos", "Suíça", "Argentina", "Índia", "Argélia"),
Lat_Municipio = rep(-23.6, 10),
Long_Municipio = rep(-46.6, 10),
Lat_PAIS = c(33.4, 59.1, 39.6, 42.7, 50.6, 23.5, 46.9, -35.4, 21.0, 28.2),
Long_PAIS = c(107.0, -109.0, -98.6, 12.8, 4.66, 54.2, 7.91, -65.2, 78.5, 2.63),
US_FOB = c(1e9, 3.46e8, 3.08e8, 2.26e8, 2.04e8, 1.63e8, 1.14e8, 1.08e8, 9.3e7, 8.12e7)
)
# Packages
library(highcharter)
library(dplyr)
# Load world map data
worldgeojson <- get_data_from_map(download_map_data("https://code.highcharts.com/mapdata/custom/world.geo.json"))
# Prepare data for destination points
dest_points <- data.frame(
lat = top_destinations$Lat_PAIS,
lon = top_destinations$Long_PAIS,
name = top_destinations$Nome_Pais,
US_FOB = top_destinations$US_FOB
)
# Prepare data for connections (maplines)
connections <- lapply(1:nrow(top_destinations), function(i) {
list(
from = list(lat = top_destinations$Lat_Municipio[i], lon = top_destinations$Long_Municipio[i]),
to = list(lat = top_destinations$Lat_PAIS[i], lon = top_destinations$Long_PAIS[i])
)
})
# Create the map with Highcharts
highchart(type = "map") %>%
# Add base map
hc_add_series(
mapData = worldgeojson,
showInLegend = FALSE,
nullColor = "#E0E0E0",
borderWidth = 0
) %>%
hc_mapNavigation(enabled = TRUE) %>%
# Add São Paulo as the origin point
hc_add_series(
type = "mappoint",
data = data.frame(
lat = top_destinations$Lat_Municipio[1],
lon = top_destinations$Long_Municipio[1],
name = "São Paulo",
color = "#3d9970",
US_FOB = sum(top_destinations$US_FOB)
),
marker = list(symbol = "circle", radius = 4),
tooltip = list(pointFormat = "City: {point.name}<br>Export Value: {point.US_FOB}")
) %>%
# Add destination points
hc_add_series(
type = "mappoint",
name = "Destinations",
data = dest_points,
color = "#d35400",
marker = list(symbol = "circle", radius = 3),
tooltip = list(pointFormat = "Country: {point.name}<br>Export Value: {point.US_FOB}")
) %>%
# Add connections between São Paulo and destinations
hc_add_series(
type = "mapline",
data = connections,
lineWidth = 1.5,
opacity = 0.8,
showInLegend = FALSE,
enableMouseTracking = FALSE
) %>%
# Title and tooltip settings
hc_title(text = "Main Export Destinations from São Paulo") %>%
hc_tooltip(useHTML = TRUE)
我相信您只能将
mapline
类型与 geo_json
或 geo_list
的 {geojsonio}
对象一起使用(参考:hc_add_series
用于 geo_json
和 geo_list
对象)。
我正在使用
sf
构建一组线串,这些线串将使用 highcharter
转换为 geojson_list()
。由于我无论如何都需要源点和目标点为 sf
/ sfc
对象,因此我为所有数据对象切换到 sf
的空间数据框。
无论出于何种原因,highcharts.com都没有为我切断world.geo.json,因此使用来自
{giscoR}
的底图。
library(highcharter)
library(geojsonio)
library(dplyr)
library(sf)
#> Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
worldgeojson <-
giscoR::gisco_countries %>%
geojsonio::geojson_json()
# sf object with a source point
src_point_sf <-
top_destinations %>%
summarise(
name = "São Paulo",
US_FOB = sum(US_FOB),
lat = first(Lat_Municipio),
lon = first(Long_Municipio)
) |>
st_as_sf(coords = c("lon", "lat"), crs = "WGS84")
# Prepare data for destination points
dest_points_sf <-
top_destinations %>%
st_as_sf(coords = c("Long_PAIS", "Lat_PAIS"), crs = "WGS84") %>%
select(name = Nome_Pais, US_FOB)
# sf object with connection lines (generate point pair, union, cast to line)
connections_sf <-
lapply(
st_geometry(dest_points_sf),
\(to) st_union(c(st_geometry(src_point_sf)[[1]], to)) %>% st_cast("LINESTRING") ) %>%
st_as_sfc(crs = st_crs(dest_points_sf)) %>%
st_sf(geometry = _) %>%
# with just 2 endpoints we'd get straight lines,
# adding a vertex at every 1000km introduces curves once linestrings are projected
st_segmentize(dfMaxLength = 1000*1000)
# Create the map with Highcharts
highchart(type = "map") %>%
# Add base map
hc_add_series(
mapData = worldgeojson,
showInLegend = FALSE,
nullColor = "#E0E0E0",
borderWidth = 0
) %>%
hc_mapNavigation(enabled = TRUE) %>%
# Add São Paulo as the origin point
hc_add_series(
data = geojson_list(src_point_sf),
type = "mappoint",
marker = list(symbol = "circle", radius = 4),
color = "#3d9970" ,
tooltip = list(pointFormat = "City: {point.properties.name}<br>Export Value: {point.properties.US_FOB}")
) %>%
# Add destination points
hc_add_series(
data = geojson_list(dest_points_sf),
type = "mappoint",
name = "Destinations",
color = "#d35400",
marker = list(symbol = "circle", radius = 3),
tooltip = list(pointFormat = "Country: {point.properties.name}<br>Export Value: {point.properties.US_FOB}")
) %>%
# Add connections between São Paulo and destinations
hc_add_series(
data = geojson_list(connections_sf),
type = "mapline",
lineWidth = 1.5,
opacity = 0.8,
showInLegend = FALSE,
enableMouseTracking = FALSE
) %>%
# Title and tooltip settings
hc_title(text = "Main Export Destinations from São Paulo") %>%
hc_tooltip(useHTML = TRUE)
示例数据:
# df
top_destinations <- tibble(
Cidade = rep("São Paulo - SP", 10),
Nome_Pais = c("China", "Canadá", "Estados Unidos", "Itália", "Bélgica",
"Emirados Árabes Unidos", "Suíça", "Argentina", "Índia", "Argélia"),
Lat_Municipio = rep(-23.6, 10),
Long_Municipio = rep(-46.6, 10),
Lat_PAIS = c(33.4, 59.1, 39.6, 42.7, 50.6, 23.5, 46.9, -35.4, 21.0, 28.2),
Long_PAIS = c(107.0, -109.0, -98.6, 12.8, 4.66, 54.2, 7.91, -65.2, 78.5, 2.63),
US_FOB = c(1e9, 3.46e8, 3.08e8, 2.26e8, 2.04e8, 1.63e8, 1.14e8, 1.08e8, 9.3e7, 8.12e7)
)