Press "Enter" to skip to content

使用R进行南美地区的地理可视化 深入探究

Photo by Alexander Schimmeck on Unsplash

所以你是那种从小就喜欢地图和地理的数据科学家和业余VoAGI作家。你正在寻找一个好的主题,用于你之后的图表工作,最重要的是地图。这时你意识到你所在的国家巴西的官方统计机构发布了最新的人口普查数据。为什么不呢?为什么不拍一张巴西与南美洲邻国的照片呢?使用R和它的好包应该是一个简单的任务。让我们来做吧。

做出这个决定后的一分钟,你意识到这个简单的任务实际上是一次英雄的旅程,其中包含了发现最合适的带有shapefile的数据集、信息缺失、shapefile的互操作性、纬度和经度的数学计算、地理概念中的文化差异,甚至是地缘政治问题,比如如何正确处理法国海外领土的地图和数据。

下面的段落将解释在世界地图的一个划定区域中绘制人口统计信息的一些可能路径之一。下面描述的逐步方法对于所有对国际比较感兴趣的人来说可能是有用的,无论是比较非洲国家的用水情况还是北美的肥胖率。

Pachamama

让我们从整体来看:一个R版本的地球地图。请参见下面的图片和代码。

Mapa Mundi: Image by author
library(readxl)library(geobr)library(tidyverse)library(sf)library(spData)library(ggrepel)data("world")#mapa mundiworld %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  scale_fill_continuous_sequential(palette= "Heat 2" )+  theme_void() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("População em milhões de habitantes", 10)  )

我使用{spData}包作为全球各地领土shapefile的几何信息的数据框的参考。aes函数使用人口信息来填充形状。我们知道,中国和印度是世界上人口最多的国家,每个国家都有超过10亿人口。热度颜色显示了与其他所有国家的对比。大多数连续的颜色非常弱。我们几乎无法理解图片中颜色的渐变。如果你想要更好地理解颜色分布,对数是最好的选择。请参见下面的图片。

Mapa mundi with log scale. Image by author
world %>%  ggplot() +  geom_sf(aes(fill=pop)) +  scale_fill_continuous_sequential(palette= "Heat 2", trans= "log2" )+  theme_void() +  theme(    panel.background = element_rect(fill="#0077be"),    legend.position = "none"  )

在代码中,你可以看到在scale_fill_continuous_sequential函数中进行了对数变换。

在world数据框结构中,有一个大陆列。因此,使用这一列来过滤数据以获取南美洲地图是很明显的。请参见代码和地图。

South America map: first version. Image by author
world %>%  filter(continent == "南美洲") %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  scale_fill_continuous_sequential(palette= "Heat 2" )+  theme_void() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("人口(单位:百万)", 10)  )

如您所见,dplyr的filter函数运行正常;这正是我们想要看到的地图。但是它真的正确吗?

气候变化是一个重大问题,但海平面还没有上升到足以淹没南美洲北部出现的显著地区。这里发生了什么?现在让我们通过使用坐标和多边形命名来绘制另一张地图。

南美洲地图:第二版。图片由作者提供
southamerica<-  world %>%  filter(continent=="南美洲") southamerica$lon<- sf::st_coordinates(sf::st_centroid(southamerica$geom))[,1]   southamerica$lat<- sf::st_coordinates(sf::st_centroid(southamerica$geom))[,2]southamerica %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  scale_fill_continuous_sequential(palette= "Heat 2" )+  theme_light() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("人口(单位:百万)", 10)  )+  geom_text_repel(aes(x=lon, y=lat, label= str_wrap(name_long,20)),                   color = "black",                   fontface = "bold",                   size = 2.8)

使用theme_light而不是theme_void足以显示坐标。多边形命名需要更多的工作。我们需要计算每个多边形的质心并将此信息用作geom_text_repel函数中的x和y坐标。

通过这个新的地图版本和一些先前的知识,我们发现缺失的领土是法属圭亚那,位于南美洲北纬0°到10°,西经53°到55°之间。我们下一个任务是了解如何获取有关法属圭亚那的一些信息:多边形、人口和一些坐标,以填充我们的地图。

La Mer

我必须将法国与世界其他地方隔离开来,以了解{spData}包如何处理这个国家地图的数据。请看下面的结果。

法国地图。图片由作者提供
france<-  world %>%  filter(iso_a2 == "FR")france %>%  ggplot() +  geom_sf(aes(fill=pop)) +  scale_fill_continuous_sequential(palette= "Heat 2", trans= "log2" )+  theme_light() +  theme(    #panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("人口", 30)  )

法国有许多所谓的海外领土。{spData}包的方法是仅表示主要领土,以及地中海上的一个岛屿科西嘉和位于我们上一张南美洲地图中空白区域的法属圭亚那。

我的下一次尝试是将法国地理数据的数据框添加到我的南美洲过滤器中,但我知道我还需要更多的东西。请参阅下面的结果

南美洲 + 法国。图片由作者提供
southamerica %>%  bind_rows(france) %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  scale_fill_continuous_sequential(palette= "Heat 2" )+  theme_light() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("População em milhões de habitantes", 10)  )+  geom_text_repel(aes(x=lon, y=lat, label= str_wrap(name_long,20)),                   color = "black",                   fontface = "bold",                   size = 2.8)

如您所见,在代码中,我使用了bind_rows将南美地区与法国的shapefile合并。所以我们现在有了法属圭亚那的正确位置。另一方面,地图上没有人口信息,并且法国在殖民主义历史的背后是南美洲的一部分。

换句话说,我想要这张地图。

法属圭亚那位于南美洲地图上。图片作者:作者
data_guiana<-  insee::get_idbank_list('TCRED-ESTIMATIONS-POPULATION') %>%  filter(str_detect(REF_AREA_label_fr,"Guyane")) %>%  filter(AGE == "00-") %>% #所有年龄  filter(SEXE == 0) %>% #男性和女性  pull(idbank) %>%  insee::get_insee_idbank() %>%  filter(TIME_PERIOD == "2023") %>%   select(TITLE_EN,OBS_VALUE) %>%  mutate(iso_a2 = "FR")data_guiana <- janitor::clean_names(data_guiana)southamerica %>%  bind_rows(france) %>%  left_join(data_guiana) %>%  mutate(pop=ifelse(iso_a2=="FR",obs_value,pop))%>%  mutate(lon= ifelse(iso_a2=="FR", france[[11]][[1]][[1]][[1]][1,1], lon),         lat= ifelse(iso_a2=="FR",france[[11]][[1]][[1]][[1]][1,2], lat)) %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  scale_fill_continuous_sequential(palette= "Heat 2" )+  geom_text_repel(aes(x=lon, y=lat, label= str_wrap(name_long,20)),                   color = "black",                   fontface = "bold",                   size = 2.8)+  coord_sf(xlim = c(-82,-35), ylim=c(-60,15))+  theme_light() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("População em milhões de habitantes", 10)  )

如您所读,我使用了法国官方统计机构的一个R包来获取圭亚那的人口数据。此外,我将地图限制在适当的坐标范围内以观察南美洲。

Emolduram e aquarelam o meu Brasil

现在,地图英雄终于解决了南美洲的问题,并与法国和平相处,是时候回到巴西的数据和地图了。记住,我想要将巴西的人口普查细节与巴拿马以南的其他国家和地区进行比较。

人口普查数据可以在一个R包中或者一个API地址中获得。我选择了更具挑战性的API选项。在其他时间使用另一种选项可能是个好主意。请查看下面的代码和地图,其中我展示了巴西各州的人口与其他南美洲地区的对比。

南美洲+巴西各州。图片作者:作者
central_america<-  world %>%  filter(subregion == "中美洲")brasil<- geobr::read_country()estados<- geobr::read_state()#人口数据ibge2022<-  get_municipalies_data()estados<-  estados %>%  inner_join(    ibge2022 %>%      rename(abbrev_state = uf) %>%      summarise(.by=abbrev_state,                pop = sum(populacao_residente)      )  )southamerica %>%  filter(iso_a2!="BR") %>%  bind_rows(france) %>%  left_join(data_guiana) %>%  mutate(pop=ifelse(iso_a2=="FR",obs_value,pop))%>%  mutate(lon= ifelse(iso_a2=="FR", france[[11]][[1]][[1]][[1]][1,1], lon),         lat= ifelse(iso_a2=="FR",france[[11]][[1]][[1]][[1]][1,2], lat)) %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  geom_sf(data=estados, aes(fill=pop/10^6)) +  geom_sf(data=brasil,fill=NA, color="#00A859", lwd=1.2)+  geom_sf(data= central_america,fill= "#808080")+  scale_fill_continuous_sequential(palette= "Heat 2" )+  geom_text_repel(aes(x=lon, y=lat,                       label= str_wrap(name_long,20)),                   color = "black",                   fontface = "bold",                   size = 2.8)+  coord_sf(xlim = c(-82,-35), ylim=c(-60,15))+  theme_void() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("人口(百万)", 10)  )

我使用了上面提到的 API 编写了 get_municipalites_data 函数。代码在我的 gist 中可用。还要注意两个函数,它们提供了用于绘制巴西及其子区域边界的 shapefile:read_country 和 read_states。这些函数在 {geobr} 包中。

我在 world 数据帧中使用了另一个筛选器。在这种情况下,目的是显示中美洲亚大陆的起点,并用灰色着色。在这里,我们面临了一个文化分歧,因为我们在巴西学到的是美洲有三个亚大陆:北美洲、中美洲和南美洲。对于数据集的作者来说,中美洲是北美洲的一个子区域。现在是时候完成我的工作了。我想在地图上显示人口最多的八个地区的名称。即使在这个最后阶段,也有一些代码技巧。

人口最多的地区。作者提供的图片
estados$lon<- sf::st_coordinates(sf::st_centroid(estados$geom))[,1]   estados$lat<- sf::st_coordinates(sf::st_centroid(estados$geom))[,2]most_populated<-  southamerica %>%  filter(iso_a2 !="BR") %>%  rename(name= name_long) %>%  as_tibble() %>%  select(name, pop, lat, lon) %>%  bind_rows(    estados %>%      rename(name= name_state) %>%      as_tibble() %>%      select(name, pop, lat, lon)  ) %>%  slice_max(order_by = pop, n=8)southamerica %>%  filter(iso_a2!="BR") %>%  bind_rows(france) %>%  left_join(data_guiana) %>%  mutate(pop=ifelse(iso_a2=="FR",obs_value,pop))%>%  mutate(lon= ifelse(iso_a2=="FR", france[[11]][[1]][[1]][[1]][1,1], lon),         lat= ifelse(iso_a2=="FR",france[[11]][[1]][[1]][[1]][1,2], lat)) %>%  ggplot() +  geom_sf(aes(fill=pop/10^6)) +  geom_sf(data=estados, aes(fill=pop/10^6)) +  geom_sf(data=brasil,fill=NA, color="#00A859", lwd=1.2)+  geom_sf(data= central_america,fill= "#808080")+  scale_fill_continuous_sequential(palette= "Heat 2" )+  geom_text_repel(data= most_populated,                  aes(x=lon, y=lat,                       label= str_c(str_wrap(name,10),": ",round(pop/10^6,1))),                   color = "black",                   fontface = "bold",                   size = 2.9)+  coord_sf(xlim = c(-82,-35), ylim=c(-60,15))+  theme_void() +  theme(    panel.background = element_rect(fill="#0077be")  ) +  labs(    fill= str_wrap("人口(百万)", 10)  )

巴西有三个州是南美洲人口最多的八个地区之一。事实上,圣保罗是地图上第二人口最多的地方,除了哥伦比亚之外超过了所有其他国家。

现在,专注于代码,您可以看到我创建了一个新的数据框来构建这个排名,将两个不同的 sf 对象组合在一起。我选择了一部分列,并将类型从 sf 更改为 tibble,以启用行绑定。

所以就是这样。英雄已经完成了一条可能的路径,并为下一次旅程留下了足迹。现在轮到你了。回想一下你所有的项目,看看是否可以使用地图表示来显著改进。按照上面的步骤,并收集有关人口、社会经济问题等的所有可用数据,只需选择要填充多边形的变量即可。

代码和数据

完整的代码可以在 gist 上获得。

所有巴西数据集都被归类为公共领域,因为它们是由联邦政府机构产生的数据,在互联网上作为积极透明度提供,并受到巴西信息获取法的约束。

IBGE:巴西人口普查数据

IPEA:巴西的形状文件

法国的数据可以从开放数据门户获得,并列为开放许可证,允许商业目的使用这些信息。

Leave a Reply

Your email address will not be published. Required fields are marked *