如何使用 GEOPANDAS 和 matplotlib 按条件添加阴影线
How to add hatching by condition with GEOPANDAS and matplotlib
我尝试绘制一张地图,其中一个值应定义每个多边形的阴影线类型。
我设法得到了整个情节的孵化器,但不是基于条件。
有没有办法用 geopandas 做到这一点?
我的代码:
import matplotlib as mpl
import matplotlib.pyplot as plt
import geopandas as gpd
from matplotlib.colors import Normalize
project_data = 'XXX'
border = gpd.read_file(f'{project_data}GIS/border.json')
data = gpd.read_file(f'{project_data}GIS/shape.json')
def marker(row, field):
m = ''
if (row[field] <= 0):
m = ''
elif (row[field] <= 0.5):
m = '--'
elif (row[field] <= 1):
m = '/////'
elif (row[field] <= 1.6):
m = 'x'
return m
data['UI_P45_M'] = data.apply(marker, field='UI_P45', axis=1)
field1 = 'AL_CUR_I'
hatch1 = 'UI_P45_M'
cmap = mpl.cm.get_cmap('pink_r')
fig, ax = plt.subplots(1)
ax.axis('off')
border.plot(facecolor="none", edgecolor="black",
ax=ax, zorder=2, linewidth=0.5)
data.plot(
column=field1, linewidth=0, norm=Normalize(0, 1.2),
cmap=cmap, ax=ax, hatch=hatch1, zorder=1
)
fig = plt.gcf()
plt.savefig(f'{project_data}results/hatched.pdf')
plt.close(fig)
我也试过在我做阴影的地方放一层:
border.plot(facecolor="none", edgecolor="black",
ax=ax, zorder=3, linewidth=0.5)
data.plot(
column=field1, linewidth=0,norm=Normalize(0,1.2),
cmap=cmap, ax=ax, zorder=1
)
data.plot(
column=field1, linewidth=0, hatch=hatch1,
facecolor='none',
ax=ax, zorder=2
)
...但它仍然没有出现。
我得到的图片是这样的:
我做错了什么?
- 问题标签是 geopandas 所以已经使用 folium 生成 choropleth
- 可以在此处找到方法的详细信息https://python-visualization.github.io/folium/plugins.html
- 已使用标准自然地球数据集制作 MWE
import geopandas as gpd
import folium
from folium.plugins import StripePattern
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")).loc[
lambda d: (d["continent"] == "Europe") & (~d["iso_a3"].isin(["-99", "RUS"]))
]
# classify countries into 4 with a label
gdf["fill_cat"] = pd.qcut(gdf["pop_est"], 4, labels=list("abcd"))
m = folium.Map(
location=(gdf.total_bounds[[1, 3]].mean(), gdf.total_bounds[[0, 2]].mean()),
height=300,
width=500,
)
m.fit_bounds([gdf.total_bounds[[1, 0]].tolist(), gdf.total_bounds[[3, 2]].tolist()])
# category config
hatch_style = {
"a": {"angle": 0, "color": "grey"},
"b": {"angle": 45, "color": "red"},
"c": {"angle": 90, "color": "green"},
"d": {"angle": 135, "color": "blue"},
}
folium.GeoJson(
gdf.__geo_interface__,
tooltip=gpd.explore._tooltip_popup("tooltip", True, gdf),
style_function=lambda p: {
"color": hatch_style[p["properties"]["fill_cat"]]["color"],
"weight": 1,
"fillPattern": StripePattern(**hatch_style[p["properties"]["fill_cat"]]),
},
).add_to(m)
m
绘制具有多边形几何的地理数据框利用了 matplotlib 的 Polygon artists,因此 hatch
关键字参数被传递到那里。
从多边形文档中,您可以看到 hatch 关键字本身由 matplotlib.patches.Patch.set_hatch
解释。来自这些文档:
set_hatch
(hatch)
Set the hatching pattern.
hatch can be one of:
/ - diagonal hatching
\ - back diagonal
| - vertical
- - horizontal
+ - crossed
x - crossed diagonal
o - small circle
O - large circle
. - dots
* - stars
Letters can be combined, in which case all the specified hatchings are done. If same letter repeats, it increases the density of hatching of that pattern.
所以问题实际上是您不能将列名指定为影线指示符。取而代之的是,对每种舱口类型的数据进行子集化,然后选择一个有效的舱口,例如:
data.loc[some_criteria_1].plot(..., hatch='/')
data.loc[some_criteria_2].plot(..., hatch='|')
# etc
我尝试绘制一张地图,其中一个值应定义每个多边形的阴影线类型。 我设法得到了整个情节的孵化器,但不是基于条件。 有没有办法用 geopandas 做到这一点? 我的代码:
import matplotlib as mpl
import matplotlib.pyplot as plt
import geopandas as gpd
from matplotlib.colors import Normalize
project_data = 'XXX'
border = gpd.read_file(f'{project_data}GIS/border.json')
data = gpd.read_file(f'{project_data}GIS/shape.json')
def marker(row, field):
m = ''
if (row[field] <= 0):
m = ''
elif (row[field] <= 0.5):
m = '--'
elif (row[field] <= 1):
m = '/////'
elif (row[field] <= 1.6):
m = 'x'
return m
data['UI_P45_M'] = data.apply(marker, field='UI_P45', axis=1)
field1 = 'AL_CUR_I'
hatch1 = 'UI_P45_M'
cmap = mpl.cm.get_cmap('pink_r')
fig, ax = plt.subplots(1)
ax.axis('off')
border.plot(facecolor="none", edgecolor="black",
ax=ax, zorder=2, linewidth=0.5)
data.plot(
column=field1, linewidth=0, norm=Normalize(0, 1.2),
cmap=cmap, ax=ax, hatch=hatch1, zorder=1
)
fig = plt.gcf()
plt.savefig(f'{project_data}results/hatched.pdf')
plt.close(fig)
我也试过在我做阴影的地方放一层:
border.plot(facecolor="none", edgecolor="black",
ax=ax, zorder=3, linewidth=0.5)
data.plot(
column=field1, linewidth=0,norm=Normalize(0,1.2),
cmap=cmap, ax=ax, zorder=1
)
data.plot(
column=field1, linewidth=0, hatch=hatch1,
facecolor='none',
ax=ax, zorder=2
)
...但它仍然没有出现。
我得到的图片是这样的:
我做错了什么?
- 问题标签是 geopandas 所以已经使用 folium 生成 choropleth
- 可以在此处找到方法的详细信息https://python-visualization.github.io/folium/plugins.html
- 已使用标准自然地球数据集制作 MWE
import geopandas as gpd
import folium
from folium.plugins import StripePattern
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")).loc[
lambda d: (d["continent"] == "Europe") & (~d["iso_a3"].isin(["-99", "RUS"]))
]
# classify countries into 4 with a label
gdf["fill_cat"] = pd.qcut(gdf["pop_est"], 4, labels=list("abcd"))
m = folium.Map(
location=(gdf.total_bounds[[1, 3]].mean(), gdf.total_bounds[[0, 2]].mean()),
height=300,
width=500,
)
m.fit_bounds([gdf.total_bounds[[1, 0]].tolist(), gdf.total_bounds[[3, 2]].tolist()])
# category config
hatch_style = {
"a": {"angle": 0, "color": "grey"},
"b": {"angle": 45, "color": "red"},
"c": {"angle": 90, "color": "green"},
"d": {"angle": 135, "color": "blue"},
}
folium.GeoJson(
gdf.__geo_interface__,
tooltip=gpd.explore._tooltip_popup("tooltip", True, gdf),
style_function=lambda p: {
"color": hatch_style[p["properties"]["fill_cat"]]["color"],
"weight": 1,
"fillPattern": StripePattern(**hatch_style[p["properties"]["fill_cat"]]),
},
).add_to(m)
m
绘制具有多边形几何的地理数据框利用了 matplotlib 的 Polygon artists,因此 hatch
关键字参数被传递到那里。
从多边形文档中,您可以看到 hatch 关键字本身由 matplotlib.patches.Patch.set_hatch
解释。来自这些文档:
set_hatch
(hatch)Set the hatching pattern.
hatch can be one of:
/ - diagonal hatching \ - back diagonal | - vertical - - horizontal + - crossed x - crossed diagonal o - small circle O - large circle . - dots * - stars
Letters can be combined, in which case all the specified hatchings are done. If same letter repeats, it increases the density of hatching of that pattern.
所以问题实际上是您不能将列名指定为影线指示符。取而代之的是,对每种舱口类型的数据进行子集化,然后选择一个有效的舱口,例如:
data.loc[some_criteria_1].plot(..., hatch='/')
data.loc[some_criteria_2].plot(..., hatch='|')
# etc