format/round GeoPandas 中的数字图例标签
format/round numerical legend label in GeoPandas
我正在寻找一种方法来 format/round GeoPandas 中 .plot()
函数生成的那些地图中的数字图例标签。例如:
gdf.plot(column='pop2010', scheme='QUANTILES', k=4)
这给了我一个有很多小数位的图例:
我希望图例标签是整数。
因为我最近遇到了同样的问题,而且 Stack Overflow 或其他网站上似乎没有现成的解决方案,所以我想我会 post 我采用的方法,以防它有用。
首先,使用geopandas
世界地图的基本情节:
# load world data set
world_orig = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
world = world_orig[(world_orig['pop_est'] > 0) & (world_orig['name'] != "Antarctica")].copy()
world['gdp_per_cap'] = world['gdp_md_est'] / world['pop_est']
# basic plot
fig = world.plot(column='pop_est', figsize=(12,8), scheme='fisher_jenks',
cmap='YlGnBu', legend=True)
leg = fig.get_legend()
leg._loc = 3
plt.show()
我使用的方法依赖于matplotlib.legend.Legend
对象的get_texts()
方法,然后迭代leg.get_texts()
中的项目,将文本元素拆分为下限和上限,然后创建一个应用了格式的新字符串,并使用 set_text()
方法进行设置。
# formatted legend
fig = world.plot(column='pop_est', figsize=(12,8), scheme='fisher_jenks',
cmap='YlGnBu', legend=True)
leg = fig.get_legend()
leg._loc = 3
for lbl in leg.get_texts():
label_text = lbl.get_text()
lower = label_text.split()[0]
upper = label_text.split()[2]
new_text = f'{float(lower):,.0f} - {float(upper):,.0f}'
lbl.set_text(new_text)
plt.show()
这在很大程度上是一种 'trial and error' 方法,所以如果有更好的方法,我不会感到惊讶。尽管如此,也许这会有所帮助。
方法一:
GeoPandas 使用 PySal mapclassify。这是分位数图 (k=5) 的示例。
import matplotlib.pyplot as plt
import numpy as np
import mapclassify # 2.3.0
import geopandas as gpd # 0.8.1
# load dataset
path = gpd.datasets.get_path('naturalearth_lowres')
gdf = gpd.read_file(path)
# generate a random column
np.random.seed(0)
gdf['random_col'] = np.random.normal(100, 10, len(gdf))
# plot quantiles map
fig, ax = plt.subplots(figsize=(10, 10))
gdf.plot(column='random_col', scheme='quantiles', k=5, cmap='Blues',
legend=True, legend_kwds=dict(loc=6), ax=ax)
这给了我们:
假设我们要对图例中的数字进行四舍五入。我们可以通过mapclassify
.
中的.Quantiles()
函数得到class化
mapclassify.Quantiles(gdf.random_col, k=5)
函数returns一个对象mapclassify.classifiers.Quantiles
:
Quantiles
Interval Count
------------------------
[ 74.47, 91.51] | 36
( 91.51, 97.93] | 35
( 97.93, 103.83] | 35
(103.83, 109.50] | 35
(109.50, 123.83] | 36
该对象有一个属性 bins
,它 returns 一个包含所有 classes.
上界的数组
array([ 91.51435701, 97.92957441, 103.83406507, 109.49954895,
123.83144775])
因此,我们可以使用此函数获取 classes 的所有边界,因为较低 class 中的上限等于较高 class 中的下限。唯一缺少的是最低 class 中的下限,它等于您要在 DataFrame 中 classify 的列的最小值。
以下是将所有数字四舍五入为整数的示例:
# get all upper bounds
upper_bounds = mapclassify.Quantiles(gdf.random_col, k=5).bins
# get and format all bounds
bounds = []
for index, upper_bound in enumerate(upper_bounds):
if index == 0:
lower_bound = gdf.random_col.min()
else:
lower_bound = upper_bounds[index-1]
# format the numerical legend here
bound = f'{lower_bound:.0f} - {upper_bound:.0f}'
bounds.append(bound)
# get all the legend labels
legend_labels = ax.get_legend().get_texts()
# replace the legend labels
for bound, legend_label in zip(bounds, legend_labels):
legend_label.set_text(bound)
我们最终会得到:
方法二:
除了GeoPandas的.plot()
方法,您还可以考虑geoplot提供的.choropleth()
功能,您可以在其中轻松使用不同类型的方案和数量classes 同时传递一个 legend_labels
arg 来修改图例标签。例如,
import geopandas as gpd
import geoplot as gplt
path = gpd.datasets.get_path('naturalearth_lowres')
gdf = gpd.read_file(path)
legend_labels = ['< 2.4', '2.4 - 6', '6 - 15', '15 - 38', '38 - 140 M']
gplt.choropleth(gdf, hue='pop_est', cmap='Blues', scheme='quantiles',
legend=True, legend_labels=legend_labels)
这给了你
我正在寻找一种方法来 format/round GeoPandas 中 .plot()
函数生成的那些地图中的数字图例标签。例如:
gdf.plot(column='pop2010', scheme='QUANTILES', k=4)
这给了我一个有很多小数位的图例:
我希望图例标签是整数。
因为我最近遇到了同样的问题,而且 Stack Overflow 或其他网站上似乎没有现成的解决方案,所以我想我会 post 我采用的方法,以防它有用。
首先,使用geopandas
世界地图的基本情节:
# load world data set
world_orig = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
world = world_orig[(world_orig['pop_est'] > 0) & (world_orig['name'] != "Antarctica")].copy()
world['gdp_per_cap'] = world['gdp_md_est'] / world['pop_est']
# basic plot
fig = world.plot(column='pop_est', figsize=(12,8), scheme='fisher_jenks',
cmap='YlGnBu', legend=True)
leg = fig.get_legend()
leg._loc = 3
plt.show()
我使用的方法依赖于matplotlib.legend.Legend
对象的get_texts()
方法,然后迭代leg.get_texts()
中的项目,将文本元素拆分为下限和上限,然后创建一个应用了格式的新字符串,并使用 set_text()
方法进行设置。
# formatted legend
fig = world.plot(column='pop_est', figsize=(12,8), scheme='fisher_jenks',
cmap='YlGnBu', legend=True)
leg = fig.get_legend()
leg._loc = 3
for lbl in leg.get_texts():
label_text = lbl.get_text()
lower = label_text.split()[0]
upper = label_text.split()[2]
new_text = f'{float(lower):,.0f} - {float(upper):,.0f}'
lbl.set_text(new_text)
plt.show()
这在很大程度上是一种 'trial and error' 方法,所以如果有更好的方法,我不会感到惊讶。尽管如此,也许这会有所帮助。
方法一:
GeoPandas 使用 PySal mapclassify。这是分位数图 (k=5) 的示例。
import matplotlib.pyplot as plt
import numpy as np
import mapclassify # 2.3.0
import geopandas as gpd # 0.8.1
# load dataset
path = gpd.datasets.get_path('naturalearth_lowres')
gdf = gpd.read_file(path)
# generate a random column
np.random.seed(0)
gdf['random_col'] = np.random.normal(100, 10, len(gdf))
# plot quantiles map
fig, ax = plt.subplots(figsize=(10, 10))
gdf.plot(column='random_col', scheme='quantiles', k=5, cmap='Blues',
legend=True, legend_kwds=dict(loc=6), ax=ax)
这给了我们:
假设我们要对图例中的数字进行四舍五入。我们可以通过mapclassify
.
.Quantiles()
函数得到class化
mapclassify.Quantiles(gdf.random_col, k=5)
函数returns一个对象mapclassify.classifiers.Quantiles
:
Quantiles
Interval Count
------------------------
[ 74.47, 91.51] | 36
( 91.51, 97.93] | 35
( 97.93, 103.83] | 35
(103.83, 109.50] | 35
(109.50, 123.83] | 36
该对象有一个属性 bins
,它 returns 一个包含所有 classes.
array([ 91.51435701, 97.92957441, 103.83406507, 109.49954895,
123.83144775])
因此,我们可以使用此函数获取 classes 的所有边界,因为较低 class 中的上限等于较高 class 中的下限。唯一缺少的是最低 class 中的下限,它等于您要在 DataFrame 中 classify 的列的最小值。
以下是将所有数字四舍五入为整数的示例:
# get all upper bounds
upper_bounds = mapclassify.Quantiles(gdf.random_col, k=5).bins
# get and format all bounds
bounds = []
for index, upper_bound in enumerate(upper_bounds):
if index == 0:
lower_bound = gdf.random_col.min()
else:
lower_bound = upper_bounds[index-1]
# format the numerical legend here
bound = f'{lower_bound:.0f} - {upper_bound:.0f}'
bounds.append(bound)
# get all the legend labels
legend_labels = ax.get_legend().get_texts()
# replace the legend labels
for bound, legend_label in zip(bounds, legend_labels):
legend_label.set_text(bound)
我们最终会得到:
方法二:
除了GeoPandas的.plot()
方法,您还可以考虑geoplot提供的.choropleth()
功能,您可以在其中轻松使用不同类型的方案和数量classes 同时传递一个 legend_labels
arg 来修改图例标签。例如,
import geopandas as gpd
import geoplot as gplt
path = gpd.datasets.get_path('naturalearth_lowres')
gdf = gpd.read_file(path)
legend_labels = ['< 2.4', '2.4 - 6', '6 - 15', '15 - 38', '38 - 140 M']
gplt.choropleth(gdf, hue='pop_est', cmap='Blues', scheme='quantiles',
legend=True, legend_labels=legend_labels)
这给了你