尝试将多边形数据分离为X和Y坐标,但出现错误:“ 'MultiPolygon'对象没有'exterior'属性”

5
我是Python的新手,尝试将多边形数据分离成x和y坐标。我一直收到错误提示:"AttributeError:(“'MultiPolygon' object has no attribute 'exterior'”,发生在索引1处)"。据我所知,Python对象MultiPolygon不包含外部数据。但是我该如何解决这个问题以使函数正常工作?
def getPolyCoords(row, geom, coord_type):
    """Returns the coordinates ('x' or 'y') of edges of a Polygon exterior"""

    # Parse the exterior of the coordinate
    geometry = row[geom]

    if coord_type == 'x':
        # Get the x coordinates of the exterior
        return list( geometry.exterior.coords.xy[0] )
    elif coord_type == 'y':
        # Get the y coordinates of the exterior
        return list( geometry.exterior.coords.xy[1] )


# Get the Polygon x and y coordinates
grid['x'] = grid.apply(getPolyCoords, geom='geometry', coord_type='x', axis=1)
grid['y'] = grid.apply(getPolyCoords, geom='geometry', coord_type='y', axis=1)

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-73511dbae283> in <module>
      1 # Get the Polygon x and y coordinates
----> 2 grid['x'] = grid.apply(getPolyCoords, geom='geometry', coord_type='x', axis=1)
      3 grid['y'] = grid.apply(getPolyCoords, geom='geometry', coord_type='y', axis=1)

~\Anaconda3\lib\site-packages\pandas\core\frame.py in apply(self, func, axis, broadcast, raw, reduce, result_type, args, **kwds)
   6012                          args=args,
   6013                          kwds=kwds)
-> 6014         return op.get_result()
   6015 
   6016     def applymap(self, func):

~\Anaconda3\lib\site-packages\pandas\core\apply.py in get_result(self)
    140             return self.apply_raw()
    141 
--> 142         return self.apply_standard()
    143 
    144     def apply_empty_result(self):

~\Anaconda3\lib\site-packages\pandas\core\apply.py in apply_standard(self)
    246 
    247         # compute the result using the series generator
--> 248         self.apply_series_generator()
    249 
    250         # wrap results

~\Anaconda3\lib\site-packages\pandas\core\apply.py in apply_series_generator(self)
    275             try:
    276                 for i, v in enumerate(series_gen):
--> 277                     results[i] = self.f(v)
    278                     keys.append(v.name)
    279             except Exception as e:

~\Anaconda3\lib\site-packages\pandas\core\apply.py in f(x)
     72         if kwds or args and not isinstance(func, np.ufunc):
     73             def f(x):
---> 74                 return func(x, *args, **kwds)
     75         else:
     76             f = func

<ipython-input-4-8c3864d38986> in getPolyCoords(row, geom, coord_type)
      7     if coord_type == 'x':
      8         # Get the x coordinates of the exterior
----> 9         return list( geometry.exterior.coords.xy[0] )
     10     elif coord_type == 'y':
     11         # Get the y coordinates of the exterior

AttributeError: ("'MultiPolygon' object has no attribute 'exterior'", 'occurred at index 1')

2个回答

5

我已经更新了您的函数getPolyCoords(),使其能够处理其他几何类型,即MultiPolygonPointLineString。希望它对您的项目有所帮助。

def getPolyCoords(row, geom, coord_type):
    """
    Returns the coordinates ('x|y') of edges/vertices of a Polygon/others
    Args:
    - row: the row object from a geodataframe; i.e.   df.loc[1]
    - geom: the name of "geometry" column, usually "geometry"
    - coord_type: 'x', or 'y'
    ...
    Valid geometrie types 'Polygon', 'Point', 'LineString', 'MultiLineString', 'MultiPolygon'
    """

    # Parse the geometries and grab the coordinate
    geometry = row[geom]
    #print(geometry.type)

    if geometry.type=='Polygon':
        if coord_type == 'x':
            # Get the x coordinates of the exterior
            # Interior is more complex: xxx.interiors[0].coords.xy[0]
            return list( geometry.exterior.coords.xy[0] )
        elif coord_type == 'y':
            # Get the y coordinates of the exterior
            return list( geometry.exterior.coords.xy[1] )

    if geometry.type in ['Point', 'LineString']:
        if coord_type == 'x':
            return list( geometry.xy[0] )
        elif coord_type == 'y':
            return list( geometry.xy[1] )

    if geometry.type=='MultiLineString':
        all_xy = []
        # updated code, using .geoms
        for ea in geometry.geoms:
            if coord_type == 'x':
                all_xy.append(list( ea.xy[0] ))
            elif coord_type == 'y':
                all_xy.append(list( ea.xy[1] ))
        return all_xy

    if geometry.type=='MultiPolygon':
        all_xy = []
        for ea in geometry.geoms:
            if coord_type == 'x':
                all_xy.append(list( ea.exterior.coords.xy[0] ))
            elif coord_type == 'y':
                all_xy.append(list( ea.exterior.coords.xy[1] ))
        return all_xy

    else:
        # Finally, return empty list for unknown geometries
        return []

处理MultiPolygon几何图形的代码部分有一个循环,对所有成员Polygon进行迭代并处理每个

Polygon的处理代码在此处被重复使用。

使用该函数的示例代码

import geopandas as gpd
from shapely.geometry import Polygon, LineString, MultiLineString

# Create a sample geodataframe

a = LineString([(0, 0), (0, 0.4), (1, 0.4), (1, 0)])
b = MultiLineString([[(0, 1.6), (0.5, 2.4), (1.2, 2.6), (1.3, 1.7)], [(0, 1.5), (1, 1.3), (1.5, 1.6)]])
c = Polygon([(1.4, 0), (1.5, .75), (2, 1), (2.1, 0)])
df = gpd.GeoDataFrame({"ID": ["a", "b", "c"], "geometry": [a, b, c]})

样例1

使用该函数的示例代码:

r0 = df.loc[0]  # lower-left LineString
r1 = df.loc[1]  # upper-left MultiLineString
r2 = df.loc[2]  # lower-right Polygon
print( getPolyCoords(r0, "geometry", "x"))  #[0.0, 0.0, 1.0, 1.0]
print( getPolyCoords(r1, "geometry", "y"))  #[[1.6, 2.4, 2.6, 1.7], [1.5, 1.3, 1.6]]
print( getPolyCoords(r2, "geometry", "x"))  #[1.4, 1.5, 2.0, 2.1, 1.4]

1

请参阅关于多边形的精美文档。

多边形是一系列多边形,它是具有外部属性的多边形对象。您需要遍历多边形并获取每个多边形的exterior.coords

实际上,您可能希望GeoDataFrame中的几何图形是多边形,而不是多重多边形,但它们不是。您可能希望将具有多重多边形的行拆分为多个行,每个行都有一个多边形(或根据您的用例而定)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接