如何使用matplotlib.pyplot自定义geopandas图?

ztmd8pv5  于 2022-11-15  发布在  其他
关注(0)|答案(2)|浏览(127)

geopandas图和matplotlib图有什么区别?为什么不是所有关键字都可用?
在geopandas有标记大小,但没有标记gecolor ...
在下面的例子中,我绘制了一个带有一些样式的Pandasdf,然后将Pandasdf转换为geopandas df。简单的绘制是可行的,但没有额外的样式。
这只是一个例子。在我的geopandas图中,我想自定义标记、图例等。我如何访问相关的matplotlib对象?

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import geopandas as gpd

X = np.linspace(-6, 6, 1024)
Y = np.sinc(X)
df = pd.DataFrame(Y, X)
plt.plot(X,Y,linewidth = 3., color = 'k', markersize = 9, markeredgewidth = 1.5, markerfacecolor = '.75', markeredgecolor = 'k', marker = 'o', markevery = 32)
# alternatively:
# df.plot(linewidth = 3., color = 'k', markersize = 9, markeredgewidth = 1.5, markerfacecolor = '.75', markeredgecolor = 'k', marker = 'o', markevery = 32)
plt.show()

# create GeoDataFrame from df
df.reset_index(inplace=True)
df.rename(columns={'index': 'Y', 0: 'X'}, inplace=True)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['Y'], df['X']))
gdf.plot(linewidth = 3., color = 'k', markersize = 9) # working
gdf.plot(linewidth = 3., color = 'k', markersize = 9, markeredgecolor = 'k') # not working
plt.show()
knpiaxh1

knpiaxh11#

您可能会对两个库都将方法命名为.plot(这一事实感到困惑。在matplotlib中,该方法专门转换为mpl.lines.Line2D对象,该对象还包含标记及其样式。
Geopandas,假设你想绘制地理数据,并使用路径(mpl.collections.PathCollection)。例如,它有面和边的颜色,但没有标记。只要你的路径闭合并形成一个多边形,面的颜色就起作用了(你的例子没有,使它“只是”一条线)。
Geopandas似乎对点/标记使用了一点技巧,它似乎使用“CURVE 4”代码(三次贝塞尔曲线)绘制了一条“路径”。
如果捕捉geopandas返回的坐标轴,您就可以了解发生了什么:

ax = gdf.plot(...

使用ax.get_children()你会得到所有被添加到坐标轴的艺术家,因为这是一个简单的绘图,很容易看出PathCollection是实际的数据。其他艺术家正在绘制坐标轴/脊线等。

[<matplotlib.collections.PathCollection at 0x1c05d5879d0>,
 <matplotlib.spines.Spine at 0x1c05d43c5b0>,
 <matplotlib.spines.Spine at 0x1c05d43c4f0>,
 <matplotlib.spines.Spine at 0x1c05d43c9d0>,
 <matplotlib.spines.Spine at 0x1c05d43f1c0>,
 <matplotlib.axis.XAxis at 0x1c05d036590>,
 <matplotlib.axis.YAxis at 0x1c05d43ea10>,
 Text(0.5, 1.0, ''),
 Text(0.0, 1.0, ''),
 Text(1.0, 1.0, ''),
 <matplotlib.patches.Rectangle at 0x1c05d351b10>]

如果你减少了很多点的数量,比如用5而不是1024,检索路径的绘制显示坐标和代码使用:

pcoll = ax.get_children()[0] # the first artist is the PathCollection
path = pcoll.get_paths()[0] # it only contains 1 Path
print(path.codes) # show the codes used.

# array([ 1,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
#        4,  4,  4,  4,  4,  4,  4,  4, 79], dtype=uint8)

有关这些路径如何工作的更多信息,请访问:
https://matplotlib.org/stable/tutorials/advanced/path_tutorial.html
长话短说,您确实拥有与使用Matplotlib时相同的所有关键字,但它们是Path的关键字,而不是您可能期望的Line 2D对象的关键字。
你可以随时改变顺序,从你创建的Matplotlib图形/轴开始,当你想绘制某个东西时,把这个轴传递给Geopandas。当你(也)想在同一个轴上绘制其他东西时,这可能会使它更容易或更直观。它可能需要更多的规则来确保(空间)坐标等匹配。
我个人几乎总是这样做,因为它允许使用相同的Matplotlib API来做大部分的绘图工作。无可否认,这可能有一个稍微陡峭的学习曲线。但总的来说,我发现它比不得不处理每个包的稍微不同的解释,使用Matplotlib的引擎盖(如geopandas,seborn,xarray等)更容易。但这真的取决于你来自哪里。

nxowjjhe

nxowjjhe2#

谢谢你的详细回答。基于此,我想出了这个简化的代码从我的真实的项目。
我有一个shapefile shp和一些要绘制的点数据dfshp使用geopandas绘制,df使用matplotlib.pl绘制。无需像最初那样将点数据传输到地理数据框gdf中。

# read marker data (places with coordindates)
df = pd.read_csv("../obese_pct_by_place.csv")
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['sweref99_lng'], df['sweref99_lat']))
# read shapefile
shp = gpd.read_file("../../SWEREF_Shapefiles/KommunSweref99TM/Kommun_Sweref99TM_region.shp")

fig, ax = plt.subplots(figsize=(10, 8))
ax.set_aspect('equal')
shp.plot(ax=ax)
# plot obesity markers
# geopandas, no edgecolor here
# gdf.plot(ax=ax, marker='o', c='r', markersize=gdf['obese'] * 25)
# matplotlib.pyplot with edgecolor
plt.scatter(df['sweref99_lng'], df['sweref99_lat'], c='r', edgecolor='k', s=df['obese'] * 25)
plt.show()

相关问题