缺失和空几何#

GeoPandas支持,就像在pandas中一样,缺失值(NA或空值)的概念。但对于几何值,还有一个额外的空几何的概念:

  • 空几何 是实际的几何对象,但没有坐标 (因此也没有面积,例如)。例如,它们可以来源于 两个没有重叠的多边形的交集。 标量对象(在访问 GeoSeries 的单个元素时)仍然是 一个 Shapely 几何对象。

  • 缺失的几何形状 是 GeoSeries 中的未知值。它们通常会在操作中传播(例如,在面积或交集的计算中),或在诸如 union_all() 的缩减中被忽略。当访问 GeoSeries 的单个元素时,标量对象是 Python None 对象。

警告

从GeoPandas v0.6.0开始,这两个概念的区分更加一致。有关与早期版本相比发生了什么变化的更多细节,请参见下方

考虑以下示例 GeoSeries,其中包含一个多边形,一个缺失值和一个空的多边形:

In [1]: from shapely.geometry import Polygon

In [2]: s = geopandas.GeoSeries([Polygon([(0, 0), (1, 1), (0, 1)]), None, Polygon([])])

In [3]: s
Out[3]: 
0    POLYGON ((0 0, 1 1, 0 1, 0 0))
1                              None
2                     POLYGON EMPTY
dtype: geometry

在空间操作中,缺失的几何形状通常会传播(在结果中也会缺失),而空几何形状被视为一种几何形状,结果将取决于操作:

In [4]: s.area
Out[4]: 
0    0.5
1    NaN
2    0.0
dtype: float64

In [5]: s.union(Polygon([(0, 0), (0, 1), (1, 1), (1, 0)]))
Out[5]: 
0                  POLYGON ((1 1, 1 0, 0 0, 0 1, 1 1))
1                                                 None
2    MULTIPOLYGON (EMPTY, ((0 0, 0 1, 1 1, 1 0, 0 0)))
dtype: geometry

In [6]: s.intersection(Polygon([(0, 0), (0, 1), (1, 1), (1, 0)]))
Out[6]: 
0    POLYGON ((0 0, 0 1, 1 1, 0 0))
1                              None
2                     POLYGON EMPTY
dtype: geometry

方法 GeoSeries.isna() 将仅检查缺失值,而不检查空几何对象:

In [7]: s.isna()
Out[7]: 
0    False
1     True
2    False
dtype: bool

另一方面,如果你想知道哪些值是空几何体, 你可以使用 GeoSeries.is_empty 属性:

In [8]: s.is_empty
Out[8]: 
0    False
1    False
2     True
dtype: bool

要获取既不缺失也不为空的实际几何对象,您可以使用两者的组合:

In [9]: s.is_empty | s.isna()
Out[9]: 
0    False
1     True
2     True
dtype: bool

In [10]: s[~(s.is_empty | s.isna())]
Out[10]: 
0    POLYGON ((0 0, 1 1, 0 1, 0 0))
dtype: geometry

自 GeoPandas v0.6.0 以来的更改#

在GeoPandas v0.6.0中,缺失数据处理进行了重构,并在整个库中变得更加一致。

从历史上看,GeoSeries 中的缺失 (“NA”) 值除了可以由空几何对象表示外,还可以通过标准表示,例如 Nonenp.nan。至少,在 GeoSeries.isna() 中是这样的,或者当 GeoSeries 在地理空间操作中对齐时也是如此。但是,其他方法如 dropna()fillna() 并没有遵循这种方法,也没有将空几何体视为缺失。

在GeoPandas v0.6.0中,最重要的变化是 GeoSeries.isna() 不再将空值视为缺失:

  • 使用上面的简单示例,旧的行为将空值作为“缺失”的几何体处理为“缺失”:

    >>> s
    0    POLYGON ((0 0, 1 1, 0 1, 0 0))
    1                              None
    2          GEOMETRYCOLLECTION EMPTY
    dtype: object
    
    >>> s.isna()
    0    False
    1     True
    2     True
    dtype: bool
    
  • 从 GeoPandas v0.6.0 开始,它现在只会将实际缺失的值视为缺失:

    In [11]: s.isna()
    Out[11]: 
    0    False
    1     True
    2    False
    dtype: bool
    

    现在,当在具有空几何的 GeoSeries 上调用 isna() 时,会引发警告,以提醒用户已更改的行为,并指示如何解决此问题。

此外,GeoSeries.align() 的行为改变为使用缺失值而不是空几何体来填充不匹配的索引。考虑以下小示例:

In [12]: from shapely.geometry import Point

In [13]: s1 = geopandas.GeoSeries([Point(0, 0), Point(1, 1)], index=[0, 1])

In [14]: s2 = geopandas.GeoSeries([Point(1, 1), Point(2, 2)], index=[1, 2])

In [15]: s1
Out[15]: 
0    POINT (0 0)
1    POINT (1 1)
dtype: geometry

In [16]: s2
Out[16]: 
1    POINT (1 1)
2    POINT (2 2)
dtype: geometry
  • 之前,align 方法会使用空几何来填充值:

    >>> s1_aligned, s2_aligned = s1.align(s2)
    
    >>> s1_aligned
    0                 POINT (0 0)
    1                 POINT (1 1)
    2    GEOMETRYCOLLECTION EMPTY
    dtype: object
    
    >>> s2_aligned
    0    GEOMETRYCOLLECTION EMPTY
    1                 POINT (1 1)
    2                 POINT (2 2)
    dtype: object
    

    当对不对齐的 GeoSeries 对象执行空间操作时,将在后台使用此方法:

    >>> s1.intersection(s2)
    0    GEOMETRYCOLLECTION EMPTY
    1                 POINT (1 1)
    2    GEOMETRYCOLLECTION EMPTY
    dtype: object
    
  • 从 GeoPandas v0.6.0 开始, GeoSeries.align() 将使用缺失值来填充未对齐的索引,以保持与 pandas 的行为一致:

    在 [17]: s1_aligned, s2_aligned = s1.align(s2)
    
    在 [18]: s1_aligned
    输出 [18]: 
    0    POINT (0 0)
    1    POINT (1 1)
    2           None
    dtype: geometry
    
    在 [19]: s2_aligned
    输出 [19]: 
    0           None
    1    POINT (1 1)
    2    POINT (2 2)
    dtype: geometry
    

    这导致空间操作也将使用缺失值而不是空几何,这可能会根据空间操作的不同而表现出不同的行为:

    在 [20]: s1.intersection(s2)
    输出 [20]: 
    0           None
    1    POINT (1 1)
    2           None
    dtype: geometry