为了账号安全,请及时绑定邮箱和手机立即绑定

根据列值对之间的最近匹配合并两个数据帧

根据列值对之间的最近匹配合并两个数据帧

摇曳的蔷薇 2023-06-20 14:28:42
我正在尝试根据列值对之间的匹配项合并两个数据框。但是,从一个数据帧到下一个数据帧的列值并不准确。这些对是使用瑞士坐标系的坐标,但在每个 df 中从略微不同的参考点测量。我的数据示例:df1 = pd.DataFrame({'Ecode': [2669827.294, 2669634.483, 2669766.266, 2669960.683],                    'Ncode': [1261034.528, 1262412.587, 1261209.646, 1262550.374],                    'shape': ['square', 'square', 'triangle', 'circle']})df1     Ecode            Ncode          shape0   2669827.294     1261034.528     square1   2669634.483     1262412.587     square2   2669766.266     1261209.646     triangle3   2669960.683     1262550.374     circledf2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],                    'CoorN': [1262413, 1261211, 1261032, 1262550],                    'color': ['purple', 'blue', 'blue', 'yellow']})df2     CoorE       CoorN      color0   2669636     1262413     purple1   2669765     1261211     blue2   2669827     1261032     blue3   2669961     1262550     yellow我有我想比较的数据,位于两组坐标(例如“形状”和“颜色”)。我想要的结果与最接近匹配的列对匹配:     CoorE       CoorN      color   shape0   2669636     1262413     purple  square1   2669765     1261211     blue    triangle2   2669827     1261032     blue    square3   2669961     1262550     yellow  circle有没有办法做到这一点?我曾尝试使用 merge_asof 但意识到它不能键控两个变量。我还看到线程根据纬度和经度计算这个。我可以编写一个函数,将 CoorE/CoorN 和 Ecode/Ncode 视为 x/y 坐标,并计算一对坐标之间的距离(可能有更好的方法,但我是新手):import math  def calculateDistance(x1,y1,x2,y2):       dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)       return dist  print calculateDistance(x1, y1, x2, y2)或类似的东西,但无法弄清楚如何使用这种函数根据最小距离比较和匹配来自两个独立数据帧的坐标对。真实的数据集也有大约 300 万个条目,我想知道执行此操作的内存占用最少的方法是什么。
查看完整描述

1 回答

?
慕勒3428872

TA贡献1848条经验 获得超6个赞

要使用库来计算距离,您需要在统一系统上。来自谷歌,我相信你正在使用epsg:21781

  1. 首先使用标准化坐标系pyproj

  2. 做颜色形状的笛卡尔积

  3. 使用计算这些之间的距离geopy

  4. 您现在可以选择您想要的结果行。举个例子,我在按颜色形状分组时采取了最近的做法

import pyproj, geopy.distance

df1 = pd.DataFrame({'Ecode': [2669827.294, 2669634.483, 2669766.266, 2669960.683],

                    'Ncode': [1261034.528, 1262412.587, 1261209.646, 1262550.374],

                    'shape': ['square', 'square', 'triangle', 'circle']})

df2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],

                    'CoorN': [1262413, 1261211, 1261032, 1262550],

                    'color': ['purple', 'blue', 'blue', 'yellow']})



# assuming this co-ord system https://epsg.io/21781 then mapping to https://epsg.io/4326

sc = pyproj.Proj("epsg:21781")

dc = pyproj.Proj("epsg:4326")


df1 = df1.assign(

    shape_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["Ecode"], r["Ncode"]), axis=1)

)

df2 = df2.assign(

    color_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["CoorE"], r["CoorN"]), axis=1)

)


(df1

     .assign(foo=1)

     .merge(df2.assign(foo=1), on="foo")

     .assign(distance=lambda x: x.apply(lambda r: 

                                        geopy.distance.geodesic(r["color_gps"], r["shape_gps"]).km, axis=1))

     .sort_values("distance")

 .groupby(["color","shape"]).agg({"distance":"first","CoorE":"first","CoorN":"first"})

)

为最近的合并更新

如果你选择一个参考点来计算距离,你会得到你想要的。


import pyproj, geopy.distance

df1 = pd.DataFrame({'Ecode': [2669827.294, 2669634.483, 2669766.266, 2669960.683],

                    'Ncode': [1261034.528, 1262412.587, 1261209.646, 1262550.374],

                    'shape': ['square', 'square', 'triangle', 'circle']})

df2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],

                    'CoorN': [1262413, 1261211, 1261032, 1262550],

                    'color': ['purple', 'blue', 'blue', 'yellow']})



# assuming this co-ord system https://epsg.io/21781 then mapping to https://epsg.io/4326

sc = pyproj.Proj("epsg:21781")

dc = pyproj.Proj("epsg:4326")

# pick a reference point for use in diatnace calcs

refpoint = pyproj.transform(sc, dc, df1.loc[0,["Ecode"]][0], df1.loc[0,["Ncode"]][0])


df1 = df1.assign(

    shape_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["Ecode"], r["Ncode"]), axis=1),

    distance=lambda x: x.apply(lambda r: geopy.distance.geodesic(refpoint, r["shape_gps"]).km, axis=1),

).sort_values("distance")

df2 = df2.assign(

    color_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["CoorE"], r["CoorN"]), axis=1),

    distance=lambda x: x.apply(lambda r: geopy.distance.geodesic(refpoint, r["color_gps"]).km, axis=1),

).sort_values("distance")


# no cleanup of columns but this works

pd.merge_asof(df1, df2, on="distance", direction="nearest")


查看完整回答
反对 回复 2023-06-20
  • 1 回答
  • 0 关注
  • 160 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号