前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用 GeoPandas 绘制超高颜值数据地图

用 GeoPandas 绘制超高颜值数据地图

作者头像
数据STUDIO
发布2021-12-15 13:10:51
5K0
发布2021-12-15 13:10:51
举报
文章被收录于专栏:数据STUDIO

写在前面

通常情况下,在执行 EDA 时,我们会面临显示有关地理位置的信息的情况。例如,对于 COVID 19 数据集,人们可能希望显示各个区域的病例数。这是 Python 库 GeoPandas 的用武之地。

本文和大家一起学习如何使用 GeoPandas有效地可视化地理空间数据。

与 GeoPandas 相关的地理空间分析相关术语

地理空间数据[1]描述相对于地球位置(坐标)的物体、事件或其他特征。

空间数据 由几何对象的基本类型表示。

几何

代表

点 points

地块位置的中心点等。

线 lines

道路、溪流

多边形 polygons

建筑物、湖泊、州、省等的边界。

CRS/坐标参考系统告诉我们如何(使用投影 或数学方程)将圆形地球上的位置(坐标)转换为扁平的二维坐标系(例如计算机屏幕或纸张)上的相同位置地图)。最常用的 CRS 是“EPSG:4326”。

什么是GeoPandas?

GeoPandas 基于Pandas。它扩展了 Pandas 数据类型以包含几何列并执行空间操作。因此,任何熟悉Pandas的人都可以轻松采用 GeoPandas。

▲ GeoPandas – GeoDataFrame 和 GeoSeries

GeoPandas的主要数据结构是GeoDataFrame延伸的PandasDataFrame。所以所有基本的DataFrame操作都可以在GeoDataFrame上执行。GeoDataFrame包含一个或多个GeoSeries(延伸PandasSeries)每个都包含在一个不同的几何形状的投影(GeoSeries.crs)。虽然GeoDataFrame可以有多个GeoSeries列,但其中只有一个是活动几何图形,即所有几何操作都在该列上。

在下一节中,我们将一起学习如何使用一些常见的函数,如边界、质心和最重要的绘图方法。为了演示地理空间可视化的工作,让我们使用来自2021年奥运会数据集的Teams数据。

数据准备

在导入 GeoPandas 之前阅读Teams数据集,数据集和代码可以在公众号『数据STUDIO』回复【GeoPandas】获取。

团队的数据集包含团队名称、项目、NOC(国家/地区)和事件列。在本练习中,我们将仅使用 NOC项目 列。

代码语言:javascript
复制
import pandas as pd
df_teams = pd.read_excel("data/Teams.xlsx")
总结每个国家的项目并绘制它。
代码语言:javascript
复制
df_teams_countries_disciplines = df_teams   \
    .groupby(by="NOC").agg({'Discipline':'count'} )  \
    .reset_index().sort_values(by='Discipline', ascending=False)
    
ax = df_teams_countries_disciplines.plot.bar(x='NOC', xlabel = '', figsize=(20,8))

▲ df_teams_countries_disciplines–条形图

导入 GeoPandas 并读取数据

代码语言:javascript
复制
import geopandas as gpd
df_world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
print(f"{type(df_world)}, {df_world.geometry.name}")
print(df_world.head())
print(df_world.geometry.geom_type.value_counts())

naturalearth_lowres ”是我们加载的geopandas提供的底图

▲ df_world

df_world 的类型是 GeoDataFrame 与大陆(国家)的名称和几何列(国家地区)。geometry 属于GeoSeries 类型,是具有以 PolygonMultiPolygon 类型表示的国家区域的活动几何体。

现在绘制世界地图
代码语言:javascript
复制
df_world.plot(figsize=(10,6))

▲ df_world-plot

合并 teams 和 world 数据集

代码语言:javascript
复制
df_world_teams = df_world.merge(df_teams_countries_disciplines, 
                                how="left", 
                                left_on=['name'], 
                                right_on=['NOC'])
print("Type of DataFrame : ", 
      type(df_world_teams), df_world_teams.shape[0])
df_world_teams.head()

▲ 合并数据框

注意:
  • df_world_teams 将有一些 NOC 和 Discipline 为 NaN 的记录。在里用的到是**'left'而不是'right'**合并,这里是有意这样做的,因为我们数据中也有一些没有参与的国家。
  • 很少有国家名称在奥运会和世界数据集之间不一致。所以尽可能调整了国家名称。详细信息在源代码中。

开始绘图

显示一个简单的世界地图 - 只有边界的地图

作为第一步,我们绘制基本地图——只有边界的世界。在接下来的步骤中,将为我们感兴趣的国家/地区着色。

代码语言:javascript
复制
ax = df_world["geometry"].boundary.plot(figsize=(20,16))

▲ 世界地图

显示 Choropleth 地图 - 绘制区域

接下来,我们根据国家参加的学科数量为参加奥运会的国家涂上颜色的深浅。国家参加的学科越多,颜色越深,反之亦然。等值线图为与数据变量相关的区域/多边形着色。

代码语言:javascript
复制
df_world_teams.plot( column="Discipline", ax=ax, cmap='OrRd', 
                     legend=True, 
                    legend_kwds={"label": "Participation", 
                                 "orientation":"horizontal"})
ax.set_title("参加2021年奥运会的国家Vs项目数量")

在这里需要注意的是:

  • ax是绘制地图的轴
  • cmap是颜色图的名称
  • legend & legend_kwds控制图例的显示
参加奥运会的国家

▲ 参加奥运会的国家

根据阴影,我们可以很快看出,中国、日本、美国、意大利、德国和澳大利亚是参与较多项目的国家。

请注意,底部的图例看起来不太好。我们修改 df_world_teams.plot 以使可视化更易于展示。

代码语言:javascript
复制
fig, ax = plt.subplots(1, 1, figsize=(20, 16))
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="2%", pad="0.5%")

df_world_teams.plot(column="Discipline", ax=ax, cax=cax, cmap='OrRd',
legend=True, legend_kwds={"label": "Participation"})

▲ 带有整洁的颜色图

这个可视化不是更整洁吗?

对未参加的国家进行着色

绘制missing_kwds

现在,哪些没有参加的国家呢?所有没有阴影(即白色)的国家都是没有参加的国家。但是我们通过将这些国家/地区涂成灰色来使这一点更加明显。我们可以使用带有纯色或带有颜色和图案的 missing_kwds

代码语言:javascript
复制
df_world_teams.plot(column="Discipline", 
                    ax=ax, cax=cax, 
                    cmap='OrRd',
                    legend=True, 
                    legend_kwds={"label": "Participation"},

missing_kwds={'color': 'lightgrey'})

▲ 未参加奥运会的国家-灰色阴影

代码语言:javascript
复制
df_world_teams.plot(column= 'Discipline', ax=ax,  
                    cax=cax, cmap='OrRd', 
                    legend=True, 
                    legend_kwds={"label": "Participation"}, 
                    missing_kwds={"color": "lightgrey", 
                                  "edgecolor": "white", "hatch": "|"})

▲ 未参加奥运会的国家-灰色阴影和阴影线

标记参与最少的项目的国家-绘制点

哪个项目的参与最少?
代码语言:javascript
复制
df_discipline_countries = \
df_teams.groupby(by='Discipline'
                ).agg({'NOC':'count'}
                     ).sort_values(by='NOC', 
                                   ascending=False)
ax = df_discipline_countries.plot.bar(figsize=(8, 6))

▲ 项目与国家数量

因此,棒球/垒球是参与国家数量最少的项目(12 个)。现在我们来了解一下有哪些国家参加了这个项目?

为此,首先创建一个仅包含参与最少的国家的数据集,然后将此数据集 df_teams_least_participated_disciplinesdf_world 合并,然后计算质心。

代码语言:javascript
复制
# 创建一个只有参与最少的国家的数据集

councountries_in_least_participated_disciplines = df_discipline_countries[df_discipline_countries['NOC']<13].index.tolist()

print(least_participated_disciplines)

df_teams_least_participated_disciplines = \
df_teams[df_teams['Discipline'].
         isin(countries_in_least_participated_disciplines)]\
.groupby(by=['NOC','Discipline']).agg({'Discipline':'count'})

df_teams_least_participated_disciplines.groupby(by=['NOC']
                                               ).agg({'Discipline':'count'}
                                                    ).sort_values(by='Discipline',
                                                                  ascending=False)

# 合并 

df_teams_least_participated_disciplines 与 df_world
df_world_teams_least_participated_disciplines = df_world.merge(
  df_teams_least_participated_disciplines,
  how="right", 
  left_on=['name'], 
  right_on=['NOC'])
df_world_teams_least_participated_disciplines['centroid'] = \
df_world_teams_least_participated_disciplines.centroid
print("Type of DataFrame : ",
type(df_world_teams_least_disciplines),
      df_world_teams_least_participated_disciplines.shape[0])
print(df_world_teams_least_participated_disciplines[:5])

所以澳大利亚、加拿大、多米尼加共和国和其他国家参加了参与最少的学科。

将以下行添加到我们之前编写的绘图代码中,用深蓝色填充圆圈标记这些国家。

代码语言:javascript
复制
df_world_teams_least_participated_disciplines["centroid"] \
   .plot(ax=ax, color="DarkBlue")
df_world_teams_least_participated_disciplines.apply(lambda x: ax.annotate(text=x['name'], 
xy=(x['centroid'].coords[0][0],
x['centroid'].coords[0][ 1]-5), 
ha='center'),axis=1)

▲ 参与最少的项目的国家

现在我们在世界地图上显示了奥运代表队。我们可以进一步扩展它,使其信息更丰富。

警告:不要以牺牲清晰度为代价向地图添加太多细节。

参考资料

[1] 地理空间数据: https://www.ibm.com/topics/geospatial-data

[2] 图片来源: https://www.earthdatascience.org/courses/earth-analytics/spatial-data-r/intro-to-coordinate-reference-systems/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据STUDIO 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 与 GeoPandas 相关的地理空间分析相关术语
  • 什么是GeoPandas?
  • 数据准备
    • 总结每个国家的项目并绘制它。
      • 导入 GeoPandas 并读取数据
        • 现在绘制世界地图
      • 合并 teams 和 world 数据集
        • 注意:
    • 开始绘图
      • 显示一个简单的世界地图 - 只有边界的地图
        • 显示 Choropleth 地图 - 绘制区域
          • 参加奥运会的国家
        • 对未参加的国家进行着色
          • 绘制missing_kwds
        • 标记参与最少的项目的国家-绘制点
          • 哪个项目的参与最少?
        • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档