geographical/geospatial 地图与 maps() - R

geographical/geospatial map with maps() - R

我已经经历了很多问题和文档,并且由于您需要付费才能使用 ggmaps()(因为 google 云服务)我开始寻找替代方案。我找到了 maps(),我正在尝试调整 解决方案:

data %>%
    rename(x = longitud, y = latitud) %>%
    ggplot() +
        geom_polygon(aes(x = long, y = lat), data = map_data("world")) +
        geom_point(aes(x = x, y = y))

但是,我遇到了一些问题:

这是数据:

data <- structure(list(latitud = c(-30.6833000183105, -41.4000015258789, 
-43.8189010620117, -34.2731018066406, -47.0666999816895, -40.3166999816895, 
-43.4491996765137, -35.7543983459473, -47.1413993835449, -36.6260986328125, 
-54.0410995483398, -37.2118988037109, -33.3086013793945, -37.2792015075684, 
-35.4524993896484, -36.5856018066406, -18.5832996368408, -18.2325000762939, 
-36.4668998718262, -44.75, -44.6591987609863, -44.5936012268066, 
-28.4647006988525, -28.6996994018555, -28.5118999481201, -28.6718997955322, 
-28.7306003570557, -30.5902996063232, -30.6667003631592, -35.1730995178223, 
-48.1591987609863, -48.377498626709, -45.4000015258789, -45.7832984924316, 
-29.94580078125, -38.8652992248535, -30.4386005401611, -31.6646995544434, 
-51.2000007629395, -51.3328018188477, -51.25, -45.5666999816895, 
-45.551700592041, -45.8372001647949, -39.0144004821777, -28.9414005279541, 
-28.7502994537354, -38.6081008911133, -34.9844017028809, -32.8403015136719, 
-29.9953002929688, -18.3999996185303, -35.9000015258789, -35.6169013977051, 
-35.9085998535156, -35.8166999816895, -33.7346992492676, -45.38330078125, 
-35.4068984985352, -32.7571983337402, -32.8502998352051, -33.5938987731934, 
-36.8386001586914, -33.4961013793945, -20.1119003295898, -27.8043994903564, 
-37.7332992553711, -30.9986000061035, -30.8006000518799, -21.9368991851807, 
-22.3652992248535, -22.273099899292, -22.0277996063232, -21.9755992889404, 
-22.289400100708, -22.2791996002197, -38.4303016662598, -38.6866989135742, 
-45.4057998657227, -38.7799987792969, -37.5503005981445, -37.6018981933594, 
-37.8997001647949, -38.0368995666504, -37.9897003173828, -37.7047004699707, 
-37.7963981628418, -37.7092018127441, -31.5835990905762, -27.3635997772217, 
-27.3194007873535, -29.8931007385254, -30.9242000579834, -21.4246997833252, 
-36.5703010559082, -38.2008018493652, -38.0661010742188, -38.4333000183105, 
-31.7422008514404, -31.6881008148193, -31.8117008209229, -31.7714004516602, 
-27.86669921875, -27.5160999298096, -27.9747009277344, -30.7047004699707, 
-36.8499984741211, -36.6500015258789, -36.86669921875, -35.3736000061035, 
-40.5167007446289, -33.4782981872559, -33.198299407959, -36.0499992370605, 
-35.9667015075684, -36.2332992553711, -34.4921989440918, -34.6581001281738, 
-32.8166999816895, -47.3499984741211, -47.5, -29.9811000823975, 
-32.4413986206055, -22.3922004699707, -22.3430995941162, -21.7124996185303, 
-22.4582996368408, -22.4419002532959, -22.4468994140625, -22.5060997009277, 
-33.7219009399414, -33.6613998413086, -35.5574989318848), longitud = c(-71.0500030517578, 
-73.2166976928711, -72.38330078125, -71.371696472168, -72.8000030517578, 
-72.9666976928711, -72.1074981689453, -71.0864028930664, -72.7257995605469, 
-72.4891967773438, -68.7975006103516, -72.3242034912109, -70.3572006225586, 
-71.9847030639648, -71.7332992553711, -71.5255966186523, -69.0466995239258, 
-69.331901550293, -72.6911010742188, -72.7166976928711, -71.8082962036133, 
-71.5477981567383, -71.1782989501953, -70.5500030517578, -71.0064010620117, 
-70.6464004516602, -70.5066986083984, -71.1714019775391, -71.5333023071289, 
-71.0911026000977, -73.0888977050781, -72.9589004516602, -72.5999984741211, 
-72.61669921875, -70.5327987670898, -71.7335968017578, -71.002197265625, 
-71.2546997070312, -72.9332962036133, -73.1091995239258, -72.5167007446289, 
-72.0832977294922, -72.0680999755859, -71.7769012451172, -73.0828018188477, 
-70.2481002807617, -70.4828033447266, -72.8478012084961, -72.0100021362305, 
-71.0255966186523, -70.5867004394531, -70.3000030517578, -71.5167007446289, 
-71.7677993774414, -71.2981033325195, -71.8332977294922, -70.3007965087891, 
-72.4666976928711, -72.2082977294922, -70.736701965332, -70.5093994140625, 
-70.3792037963867, -73.061897277832, -70.8167037963867, -68.8407974243164, 
-70.1268997192383, -72.61669921875, -71.0899963378906, -70.9697036743164, 
-68.5330963134766, -68.6418991088867, -68.1438980102539, -68.6207962036133, 
-68.6074981689453, -68.3447036743164, -68.2427978515625, -72.0105972290039, 
-72.502799987793, -72.6231002807617, -72.9468994140625, -72.5903015136719, 
-72.2782974243164, -71.6239013671875, -71.4781036376953, -71.5199966430664, 
-71.7683029174805, -71.6988983154297, -71.823600769043, -71.4606018066406, 
-70.3392028808594, -70.8380966186523, -71.2514038085938, -70.7731018066406, 
-70.053596496582, -71.5547027587891, -71.2988967895508, -71.3497009277344, 
-71.2332992553711, -71.1492004394531, -71.2658004760742, -70.9302978515625, 
-71.0639038085938, -70.0667037963867, -70.2647018432617, -69.997802734375, 
-70.9244003295898, -72.38330078125, -72.4499969482422, -72.3332977294922, 
-71.8292007446289, -73.2833023071289, -70.7172012329102, -70.8955993652344, 
-72.0832977294922, -72.0167007446289, -72, -71.3731002807617, 
-71.3019027709961, -71, -72.8499984741211, -72.9749984741211, 
-70.8981018066406, -71.3139038085938, -69.5299987792969, -69.5650024414062, 
-69.5167007446289, -68.7363967895508, -68.8886032104492, -68.8775024414062, 
-68.988899230957, -71.5550003051758, -71.3371963500977, -71.7067031860352
)), row.names = c(1L, 136L, 262L, 395L, 507L, 605L, 701L, 789L, 
868L, 996L, 1094L, 1124L, 1172L, 1218L, 61387L, 61546L, 75009L, 
87052L, 99246L, 110237L, 115091L, 125346L, 135758L, 135819L, 
144524L, 154009L, 172251L, 185024L, 192338L, 210797L, 228781L, 
228893L, 238299L, 244626L, 253673L, 274263L, 285367L, 304757L, 
316768L, 328069L, 336044L, 346167L, 351691L, 363302L, 375494L, 
385229L, 402720L, 422016L, 440373L, 451547L, 462674L, 483188L, 
491968L, 496483L, 511332L, 530494L, 546443L, 564800L, 575215L, 
586462L, 602135L, 622841L, 642834L, 657640L, 677273L, 688216L, 
706550L, 724524L, 731829L, 748442L, 748489L, 754030L, 763570L, 
776729L, 785860L, 799355L, 812606L, 832675L, 853030L, 860670L, 
878448L, 889066L, 889167L, 889273L, 889372L, 889466L, 889499L, 
889524L, 913996L, 929594L, 935459L, 953842L, 963352L, 983829L, 
991810L, 1005230L, 1005341L, 1011503L, 1022492L, 1029507L, 1047978L, 
1063655L, 1073799L, 1073936L, 1086040L, 1106251L, 1126146L, 1134776L, 
1154269L, 1170495L, 1181431L, 1192018L, 1197439L, 1212431L, 1231028L, 
1247598L, 1264197L, 1264302L, 1271900L, 1279499L, 1279618L, 1290282L, 
1309415L, 1320521L, 1320606L, 1320753L, 1320827L, 1337638L, 1344817L, 
1355030L, 1368899L, 1381979L, 1393175L), class = "data.frame")

以下代码使用简单要素 (sf) 库显示覆盖有提供的数据点的智利地图。边界框在参数中设置为 st_crop 并且可以根据需要进行调整而不会扭曲地图。代码使用 Admin 0 - Countries 形状文件,该文件位于 public 域,可以免费使用。

library(sf)
library(ggplot2)
library(dplyr);
library(magrittr);

# download world shapefile from
# https://www.naturalearthdata.com/downloads/
#        50m-cultural-vectors/50m-admin-0-countries-2/
# and extract zip file

world <- st_read(
    # change below line to path of extracted shape file
    'c:/path/to/ne_50m_admin_0_countries.shp' 
  );

world %<>% mutate(active = NAME_EN == 'Chile'); # used to highlight Chile

# convert the dataframe to a sf geometry object
dsf <- data %>% 
    rowwise %>% 
    mutate(geometry = list(st_point(c(longitud, latitud)))) %>%
    st_as_sf(crs=st_crs(world));

# plot the map
world %>% st_crop(xmin=-90, xmax=-30, ymin=-60, ymax=-10) %>%
    ggplot() + 
    geom_sf(aes(fill=active), show.legend=F) + # world map with Chile highlighted
    geom_sf(data=dsf, color='#000000') + # point overlay
    scale_fill_manual(values=c('#aaaa66', '#ffffcc')) + # country colors
    scale_x_continuous(expand=c(0,0)) +
    scale_y_continuous(expand=c(0,0)) +
    theme_void() + # remove axis labels and gridlines
    theme(panel.background=element_rect(fill='lightblue'))

输出如下所示。请注意,地图不会扭曲裁剪的区域。


补充说明

sf 包提供对简单特征 (sf) 几何的支持。简单要素提供了处理多边形和点等几何体的工具。有一个作弊 sheet here 提供了很好的概述。

绘制底图

从 3.0 版开始,ggplot2 提供了对可视化简单要素几何图形的原生支持。这允许我们写:

world <- st_read(
    # change below line to path of extracted shape file
    'c:/path/to/ne_50m_admin_0_countries.shp' 
  ); 

 ggplot(world) + geom_sf()

简单的要素对象通常存储在包含描述几何的列的数据框中。这使我们能够像这样显示智利地图:

 ggplot(world %>% filter(NAME_EN == 'Chile')) + geom_sf()

或突出显示智利的地图:

# create new geometry of world map
# cropped to (10°S, 60°S) and (90°W, 30°W)
chileregion <- world %>% st_crop(
    xmin=-90, 
    xmax=-30, 
    ymin=-60, 
    ymax=-10)

# show region with Chile highlighted
ggplot(chileregion %>% 
    mutate(is.chile = factor(NAME_EN == 'Chile'))) + 
    geom_sf(aes(fill=is.chile), show.legend = F) +
    scale_fill_manual(values=c('gray', 'red'))

绘制点

我们得到了一个包含两列的数据框,纬度和经度。

要转换为简单特征,我们首先使用 st_point 创建一个具有给定坐标值的新点:

dsf <- data %>% #begin with data
  rowwise %>%  # dplyr::rowwise applies mutation to each row individually
  # create a geometry column that provides the point as a geometry
  mutate(geometry = list(st_point(c(longitud, latitud))))

此时,dsf只是一个带有几何列的数据框;它还不是一个简单的特征对象。我们可以使用函数 st_as_sf 从数据框中创建一个 sf 对象。为此,我们还需要提供坐标参考系统 (CRS) 以允许 ggplot 将提供的坐标投影到地图渲染上。这里我们可以提供ESPG 4326作为CRS,直接将x和y坐标映射到lat/long:

  # call st_as_sf to convert data frame to a simple geometry object.
  dsf <- st_as_sf(crs=4326);

由于 dsf 现在是一个简单的几何图形,您可以这样绘制:

> ggplot(dsf) + geom_sf()

(请注意,您也可以简单地用 geom_point(data=data, aes(x=longitud, y=latitud)) 覆盖底图上的点,而无需先转换为 sf 对象。这将在这里起作用,因为底图的 CRS 也是 ESPG 4326,它将 x 和 y 分别直接映射到经度和纬度。但是,使用 geom_point 在对几何应用坐标变换时的一般情况下将不起作用。)

重叠

现在两个点都定义为几何图形,您可以简单地叠加:

ggplot() +
  geom_sf(data=chileregion) +
  geom_sf(data=dsf)

原始答案中的最终情节添加了一些额外的视觉美感(例如,蓝色背景)以生成最终地图输出。

这可能会有所帮助,您可以自己尝试一下:

world_map <- map_data("world")
Wmap <- data %>%
          rename(x =longitud , y = latitud) %>%
          ggplot() +
          geom_polygon(aes(x = long, y = lat, group = group), data = world_map, fill = "grey21", color = "grey21") +
          geom_point(aes(x = x, y = y, color = 'red')) +
          scale_color_identity() +
          coord_fixed() +
          xlab("") +
          ylab("")
Wmap
Chile_map <- map_data("world", region="Chile")
Cmap <- data %>%
          rename(x =longitud , y = latitud) %>%
          ggplot() +
          geom_polygon(aes(x = long, y = lat, group = group), data = Chile_map, fill = "grey21", color = "grey21") +
          geom_point(aes(x = x, y = y, color = 'red')) +
          scale_color_identity() +
          coord_fixed() +
          xlab("") +
          ylab("")

Cmap
dev.new()
windows.options(width=10, height=6)

vp_inset <- grid::viewport(width = 0.55, height = 0.45, x = -0.1, y = 0.60, just = c("left", "top"))
print(Wmap)
print(Cmap, vp = vp_inset)

注意: 群体审美决定了哪些案例连接在一起形成多边形。