文档中示例的 GeoPandas .clip() 抛出 TypeError

GeoPandas .clip() on example from the docs throws TypeError

我无法从 GeoPandas docs 中无误地重现 .clip() 示例。我怀疑这与我的设置有关,因为几个月前同样的事情在不同的环境中起作用,而且我还没有发现其他人发生这种情况的报告。但是我不知道问题出在哪里--我希望这里有人有想法。

将示例代码复制并粘贴到我的 jupyter 笔记本中看起来像这样:

import geopandas
from shapely.geometry import Polygon

# get a set of points
capitals = geopandas.read_file(geopandas.datasets.get_path("naturalearth_cities"))

# Create a custom polygon
polygon = Polygon([(0, 0), (0, 90), (180, 90), (180, 0), (0, 0)])

# Attempt to clip points by polygon
capitals_clipped = capitals.clip(polygon)

运行 它给了我以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [7], in <cell line: 1>()
----> 1 capitals_clipped = capitals.clip(polygon)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/util/_decorators.py:311, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs)
    305 if len(args) > num_allow_args:
    306     warnings.warn(
    307         msg.format(arguments=arguments),
    308         FutureWarning,
    309         stacklevel=stacklevel,
    310     )
--> 311 return func(*args, **kwargs)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/frame.py:10917, in DataFrame.clip(self, lower, upper, axis, inplace, *args, **kwargs)
  10905 @deprecate_nonkeyword_arguments(
  10906     version=None, allowed_args=["self", "lower", "upper"]
  10907 )
   (...)
  10915     **kwargs,
  10916 ) -> DataFrame | None:
> 10917     return super().clip(lower, upper, axis, inplace, *args, **kwargs)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/generic.py:7569, in NDFrame.clip(self, lower, upper, axis, inplace, *args, **kwargs)
   7567 result = self
   7568 if lower is not None:
-> 7569     result = result._clip_with_one_bound(
   7570         lower, method=self.ge, axis=axis, inplace=inplace
   7571     )
   7572 if upper is not None:
   7573     if inplace:

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/generic.py:7417, in NDFrame._clip_with_one_bound(self, threshold, method, axis, inplace)
   7414 else:
   7415     threshold_inf = threshold
-> 7417 subset = method(threshold_inf, axis=axis) | isna(self)
   7419 # GH 40420
   7420 return self.where(subset, threshold, axis=axis, inplace=inplace)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/ops/__init__.py:470, in flex_comp_method_FRAME.<locals>.f(self, other, axis, level)
    466 axis = self._get_axis_number(axis) if axis is not None else 1
    468 self, other = align_method_FRAME(self, other, axis, flex=True, level=level)
--> 470 new_data = self._dispatch_frame_op(other, op, axis=axis)
    471 return self._construct_result(new_data)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/frame.py:6973, in DataFrame._dispatch_frame_op(self, right, func, axis)
   6970 if not is_list_like(right):
   6971     # i.e. scalar, faster than checking np.ndim(right) == 0
   6972     with np.errstate(all="ignore"):
-> 6973         bm = self._mgr.apply(array_op, right=right)
   6974     return self._constructor(bm)
   6976 elif isinstance(right, DataFrame):

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/internals/managers.py:302, in BaseBlockManager.apply(self, f, align_keys, ignore_failures, **kwargs)
    300 try:
    301     if callable(f):
--> 302         applied = b.apply(f, **kwargs)
    303     else:
    304         applied = getattr(b, f)(**kwargs)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/internals/blocks.py:402, in Block.apply(self, func, **kwargs)
    396 @final
    397 def apply(self, func, **kwargs) -> list[Block]:
    398     """
    399     apply the function to my values; return a block if we are not
    400     one
    401     """
--> 402     result = func(self.values, **kwargs)
    404     return self._split_op_result(result)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/ops/array_ops.py:283, in comparison_op(left, right, op)
    280     return invalid_comparison(lvalues, rvalues, op)
    282 elif is_object_dtype(lvalues.dtype) or isinstance(rvalues, str):
--> 283     res_values = comp_method_OBJECT_ARRAY(op, lvalues, rvalues)
    285 else:
    286     res_values = _na_arithmetic_op(lvalues, rvalues, op, is_cmp=True)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/core/ops/array_ops.py:73, in comp_method_OBJECT_ARRAY(op, x, y)
     71     result = libops.vec_compare(x.ravel(), y.ravel(), op)
     72 else:
---> 73     result = libops.scalar_compare(x.ravel(), y, op)
     74 return result.reshape(x.shape)

File ~/.conda/envs/test-env/lib/python3.8/site-packages/pandas/_libs/ops.pyx:107, in pandas._libs.ops.scalar_compare()

TypeError: '>=' not supported between instances of 'str' and 'Polygon'

到目前为止,我已经尝试在像这样获得的干净的 conda 环境中重复此操作:

conda create -n test-env
conda activate test-env
conda install ipykernel geopandas
ipython kernel install --user --name=test_ipython
conda deactivate test-env

根据 conda,运行 python 3.7.11 和 geopandas 0.9.0。即使使用这个新的 test_ipython-Kernel,当我尝试裁剪股票世界地图时,我也会得到相同的 TypeError

我目前不认为这是一个错误,并假设我只是无知。

这是 geopandas 版本的问题。

事实证明,geopandas.GeoDataFrame.clip() 在 v0.9.0 中的工作方式不同。检查 geopandas 的适当版本的文档表明,当时 clip 不是 GeoDataFrame 方法,而是一个独立的方法,使解决方案变得简单

capitals_clipped = geopandas.clip(capitals, polygon)