同时在Point几何和其他列上合并GeoDataFrames

时间:2018-09-17 16:16:13

标签: python pandas shapely geopandas

如何将GeoDataFrame几何和任意其他列上的两个Point合并在一起?我意识到此任务对于除Point之外的所有其他几何图形都是模棱两可的,因为对于线和面,“等式”的定义不是很好,但是仍然如此。

如果我只是尝试gdf2.merge(gdf),并且正确地抱怨

,则以下MWE会引发错误
  

不可散列的类型:“点”。

如何解决这个问题?

import geopandas as gpd
import pandas as pd
from io import StringIO
import shapely

df = pd.read_csv(StringIO('''
Name Value x y
'a' 1.5 0. 0.
'b' 22  0. 1.
'c' 0.2 0. 1.
'''),sep=r"\s*",engine='python')

df2 = pd.read_csv(StringIO('''
Name OtherValue x y
'a' 9.9 0. 0.
'b' 4.5 0. 1.
'c' 2e3 1. 1.
'''),sep=r"\s*",engine='python')

def dataframe_to_geodataframe(df):
    geometry = [shapely.geometry.Point(xy) for xy in zip(df.x, df.y)]
    df = df.drop(['x','y'], axis=1)
    gdf = gpd.GeoDataFrame(df, geometry=geometry)
    return gdf

gdf = dataframe_to_geodataframe(df)
gdf2 = dataframe_to_geodataframe(df2)

gdf.merge(gdf2,how='left')

理想情况下,输出将类似于

  Name  Value     geometry OtherValue
0  'a'    1.5  POINT (0 0)        9.9
1  'b'   22.0  POINT (0 1)        4.5
2  'c'    0.2  POINT (0 1)        NaN

(当然取决于how关键字)。

(我确实意识到,在转换回普通的熊猫DataFrame之后,可以很容易地做到这一点,但是我认为应该有一种无需反复转换的方法。)

1 个答案:

答案 0 :(得分:2)

一种(可能是肮脏的)方式是通过扩展类Point使shapely.geometry.Point成为可哈希的:

class HPoint(shapely.geometry.Point):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def __hash__(self):
       return hash(tuple(self.coords))

这是基于以下事实:Point的相等运算符(通过父类BaseGeometry提供)仅compares个坐标元组。

然后您可以将此类用作:

def dataframe_to_geodataframe(df):
    geometry = [HPoint(xy) for xy in zip(df.x, df.y)]
    df = df.drop(['x','y'], axis=1)
    gdf = gpd.GeoDataFrame(df, geometry=geometry)
    return gdf

gdf = dataframe_to_geodataframe(df)
gdf2 = dataframe_to_geodataframe(df2)

print(gdf2.merge(gdf, how='right'))

产生:

  Name  OtherValue     geometry  Value
0  'a'         9.9  POINT (0 0)    1.5
1  'b'         4.5  POINT (0 1)   22.0
2  'c'         NaN  POINT (0 1)    0.2