【问题标题】:Drawing map with geopandas library for a continent, but the data points contains whole world用 geopandas 库为一个大陆绘制地图,但数据点包含整个世界
【发布时间】:2022-01-27 09:03:00
【问题描述】:

我有一些陨石的数据集,这些陨石包含经纬度信息。我几乎拥有来自世界各地的 30,000 个数据点。但我想使用 geopandas 库仅绘制一个大陆的地图,例如“南美洲”。

我正在使用“naturalearth_lowres”的 geopandas 默认地图。从那张世界地图上,我过滤了南美洲。我的数据称为 mod_data_geo 包含几何类型数据 Point(longitute, latitude)。

数据集是这样的:

我的代码:

mod_data_geo = gpd.GeoDataFrame(mod_data, geometry = gpd.points_from_xy(mod_data['long'], mod_data['lat']))

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))

countries = world[world['continent'] == "South America"]

axis = countries.plot(color = 'Lightblue', edgecolor = 'black', figsize=(15,15))

mod_data_geo.plot(ax=axis, markersize = 1, color  = 'purple' )

我绘制的地图:

如何使用 Geopandas 库或任何其他工具过滤 mod_data_geo 数据框中的陨石数据,以便仅查看在南非大陆上发现的陨石?

提前谢谢你!

【问题讨论】:

  • 请不要将数据、代码、错误信息作为图片发布。将文本直接粘贴到 SO 上。
  • 欢迎来到 Stack Overflow! T先生的评论引用了堆栈溢出policy against posting images of code, data, or errors。相反,请尝试创建一个minimal reproducible example。您快到了 - 帮助我们编写重现 shapefile 的代码真是太棒了!用几个点构建一个新数据集,例如mod_data_geo = gpd.GeoDataFrame({'name': ['a', 'b', 'c']}, geometry=gpd.points_from_xy([-10, 60, -120], [-40, 10, 45])) 会带你去那里的大部分时间:)

标签: pandas matplotlib data-visualization geospatial geopandas


【解决方案1】:

三种方法 - 裁剪图像,使用边界框过滤点,或通过检查它们是否在国家形状内来过滤点。

裁剪图像

如果您希望点延伸到图像的边缘,但只是为了限制图像范围,您可以简单地在 matplotlib 轴上设置 x 和 y 限制:

axis = countries.plot(color = 'Lightblue', edgecolor = 'black', figsize=(15,15))
orig_extent = axis.get_extent()
mod_data_geo.plot(ax=axis, markersize = 1, color  = 'purple' )
axis.set_extent(*orig_extent)

过滤到边界框

第一种方法很好,因为它保留了所有适合您的绘图的数据。但这并不是超级高效,因为 matplotlib 必须根据数据是否会出现在图像中为您过滤数据。更快的方法可以先过滤数据;请注意,数据将不再移动到图像的边缘。

首先在国家周围找到一个边界框:

In [6]: bounds = countries.bounds.agg({'minx': 'min', 'miny': 'min', 'maxx': 'max', 'maxy': 'max'})

In [7]: bounds
Out[7]:
minx   -81.410943
miny   -55.611830
maxx   -34.729993
maxy    12.437303
dtype: float64

然后您可以根据这些界限过滤数据:

In [8]: mod_data_filtered = mod_data_geo[(
   ...:     (mod_data_geo.lat >= bounds.miny)
   ...:     (mod_data_geo.lat <= bounds.maxy)
   ...:     (mod_data_geo.long >= bounds.minx)
   ...:     (mod_data_geo.long <= bounds.maxx)
   ...: )]

现在您可以使用mod_data_filtered 进行绘图。

请注意,您可以将绘图的范围设置为边界框,但这会有点紧。

按国家/地区形状过滤

如果您想将数据过滤到某个国家/地区内,而不是将数据裁剪到边界框,您可以使用geopandas.GeoSeries.contains

首先,分解数据以获得南美洲的单一形状:


In [8]: south_america = countries.dissolve()

In [9]: south_america
Out[9]:
                                            geometry   pop_est      continent       name iso_a3  gdp_md_est
0  MULTIPOLYGON (((-57.75000 -51.55000, -58.05000...  44293293  South America  Argentina    ARG    879400.0

然后,将点过滤到形状内的点:

In [10]: mod_data_filtered = mod_data_geo[south_america.contains(mod_data_geo)]

【讨论】:

  • 迈克尔,谢谢你的解释。我不明白如何将这些值导入边界:minx = -81.410943,miny = -55.611830,maxx -34.729993,maxy 12.437303。你能再解释一下吗?边界内的国家也等于大陆?
  • bounds 命令应该直接在您正在使用的countries GeoDataFrame 上工作。 bounds 是一个 geopandas 空间指令,它将获取每个国家/地区的边界框,然后我将其与 min/max 聚合。看起来我也可以使用countries.total_bounds
  • 哦,也许您对In [7]: boundsOut[7]: ... 部分感到困惑?这只是一个 ipython 提示。您可以忽略Out 输出字段,只使用赋值语句。我只是向你展示了每一步会发生什么。
  • 我收到此错误:“AttributeError: '-81.410943' 不是 'Series' 对象的有效函数”。 bounds = countries.bounds.agg({'minx': '-81.410943', 'miny': '-55.611830', 'maxx': '-34.729993', 'maxy': '12.437303'}) mod_data_filtered = mod_data_geo[( (mod_data_geo.lat >= bounds.miny), (mod_data_geo.lat = bounds.minx), (mod_data_geo.long
  • 哦,是的,在 [7] 中,我很困惑。这就是为什么在 Colab 上出现错误的原因。正如我上面写的。
猜你喜欢
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多