gpt4 book ai didi

python - 避免在 matplotlib + geopandas 中重叠标签

转载 作者:行者123 更新时间:2023-12-04 17:29:43 24 4
gpt4 key购买 nike

我找到了很多关于如何避免 matplotlib 上的文本重叠的例子,但没有一个是我能弄清楚如何应用到我的案例中的。

我有一个数据框 (mapadf1),其中包含有关巴西市政当局的一些信息,并且我绘制了圣保罗州 (sp) 的 shapefile。

我创建了一个变量“l”,其中包含市政当局的名称和我要突出显示的数字。当数字为0时,字符串为空。

好的,所以我设法用以下代码绘制了我的 map :

# set the range for the choropleth values
vmin, vmax = 0, 1

# create figure and axes for Matplotlib
fig, ax = plt.subplots(1, figsize=(30, 10))

# remove the axis que mostra latitude e longitude
ax.axis('off')

# add a title and annotation
ax.set_title('Número leitos inaugurados: 22/03', fontdict={'fontsize': '25', 'fontweight' : '3'})
ax.annotate('Fonte: Governo do Estado de São Paulo', xy=(0.6, .05), xycoords='figure fraction', fontsize=12, color='#555555')

# empty array for the data range
sm.set_array([]) # or alternatively sm._A = []. Not sure why this step is necessary, but many recommends it

# create map
mapa_df1.plot(column='tem_leito',cmap='Paired', linewidth=0.8, ax=ax, edgecolor='0.8')

# Add Labels
mapa_df1['coords'] = mapa_df1['geometry'].apply(lambda x: x.representative_point().coords[:])
mapa_df1['coords'] = [coords[0] for coords in mapa_df1['coords']]

for idx, row in mapa_df1.iterrows():
plt.annotate(s=row['l'], xy=row['coords'])

还有我的 map :

enter image description here

如何避免文字重叠?!

提前致谢!

最佳答案

实际上,由 plt.annotate 创建的对象call 是一个 matplotlib“注释” - 它有很多方法 - 和一个边界框,可以通过调用 .get_window_extent() 来检索它在返回的对象上。

如果您没有数以万计的点——无论如何这都不适合这种绘图,您可以将这些坐标存储在一个列表中——并在添加另一个对象时线性检查碰撞。 (对于几千个对象,这变得不可行,必须使用比线性策略更好的策略)。

现在还有一个问题:如果发生碰撞怎么办?更简单的解决方案就是不显示有问题的标签 - 但您可以尝试稍微重新定位新注释,使其不重叠。这样做可能很复杂 - 但如果我们选择一个简单的天真策略,比如说,只在 y 轴上移动元素直到它不再重叠,你可以获得一个相当稀疏的 map 的好结果,即使有一些错误。

“更聪明”的策略可以收集所有附近的标签,然后尝试以紧密的方式重新定位在一起 - 这需要几个小时甚至几天的工作。

因此,由于您没有我们可以在本地重现的数据示例,我将编写“在 y 轴上向下移动后面的注释直到它适合”策略。至少您会得到一个起点。

from matplotlib.transforms import Bbox

...

text_rectangles = []

y_step = 0.05

# This will have far better results if the labels are sorted descending in the y axis -
#
mapa_df1["sort_key"] = [coord[1] for coord in mapa_df1["coords"]]
mapa_df1.sort_values("sort_key", ascending=False, inplace=True)
del mapa_df1["sort_key"]

for idx, row in mapa_df1.iterrows():
text = plt.annotate(s=row['l'], xy=row['coords'])

rect = text.get_window_extent()

for other_rect in text_rectangles():
while bbox.intersection(rect, other_rect): # overlapping
x, y = text.get_position()
text.set_position(x, y - y_step)
rect = text.get_window_extent()
text_rectangles.append(rect)

之后,您可以获取交互式创建的 Annotation 实例之一,并探索其方法和属性 - 然后甚至可以与 Pointer 进行交互,具体取决于渲染后端,例如,标签可以是以一定程度的透明度绘制,然后当鼠标指针悬停时变得完全不透明(例如,请参见 Possible to make labels appear when hovering over a point in matplotlib?)。

关于python - 避免在 matplotlib + geopandas 中重叠标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60853205/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com