sat*_*ato 2 python matplotlib legend geopandas choropleth
我正在城市地图上绘制某个分类值。我用来绘制的代码行如下:
fig = plt.figure(figsize=(12, 12))
ax = plt.gca()
urban_data.plot(column="category", cmap="viridis", ax=ax, categorical=True, /
k=4, legend=True, linewidth=0.5, /
legend_kwds={'fontsize':'19', 'loc':'lower left'})
Run Code Online (Sandbox Code Playgroud)
其中城市数据是 geopandas 数据框,我使用 matplotlib 作为绘图库。该参数legend_kwds允许我控制图例上的次要事物,例如位置或字体大小,但我无法决定主要事物,例如图例框中条目的顺序。事实上,我的类别是按 1-2-3-4 排列的,但我总是以不同的顺序显示它们。
是否可以对图例有更多的控制权?例如在函数外部gdf.plot()调用它?而且,如果是这样,我如何将图例中的颜色与地图中的颜色相匹配,这些颜色是 viridis 颜色图的离散值(我不确切知道)?
编辑:这是一个可验证的示例。不幸的是,shapefiles需要其他文件才能工作,这里geometry需要一个(区域,而不是点)列,所以我不得不要求你下载这个美国的shpfile 。您需要的一切都在这个文件夹中。这是重现该问题的代码。输出中的绘图很糟糕,因为我不关心这里的坐标系,但重要的是图例。
import geopandas as gpd
import numpy as np
import matplotlib.pyplot as plt
gdf=gpd.read_file('.../USA_adm1.shp')
clusters=np.random.randint(0,4, size=52)
gdf['cluster']=clusters
clusdict={1: 'lower-middle', 2: 'upper-middle', 3: 'upper', 0: 'lower'}
gdf['cluster']=gdf['cluster'].map(clusdict)
fig = plt.figure(figsize=(12, 12))
ax = plt.gca()
gdf.plot(column='cluster',cmap='viridis', categorical=True, legend=True, ax=ax)
Run Code Online (Sandbox Code Playgroud)
坏消息是 geopandas 生成的图例中的类别是排序的,并且是硬编码的(请参阅此处的源代码)。
因此,一种解决方案是使用分类列,如果对其进行排序,它将对应于所需的顺序。使用整数似乎很好。一旦图例按照正确的顺序生成,就可以替换图例中的名称。
import geopandas as gpd
import numpy as np
import matplotlib.pyplot as plt
gdf=gpd.read_file('data/USA_adm/USA_adm1.shp')
clusters=np.random.randint(0,4, size=52)
gdf['cluster']=clusters
clusdict={1: 'lower-middle', 2: 'upper-middle', 3: 'upper', 0: 'lower'}
fig = plt.figure(figsize=(12, 12))
ax = plt.gca()
gdf.plot(column='cluster',cmap='viridis', categorical=True, legend=True, ax=ax)
def replace_legend_items(legend, mapping):
for txt in legend.texts:
for k,v in mapping.items():
if txt.get_text() == str(k):
txt.set_text(v)
replace_legend_items(ax.get_legend(), clusdict)
plt.show()
Run Code Online (Sandbox Code Playgroud)