簡體   English   中英

根據列值對之間的最近匹配合並兩個數據幀

[英]Merge two dataframes based on nearest matches between pairs of column values

我正在嘗試根據列值對之間的匹配來合並兩個數據幀。 但是,從一個數據幀到下一個數據幀的列值並不准確。 這些對是使用瑞士坐標系的坐標,但從每個 df 中稍微不同的參考點測量。

這個stackoverflow線程如何在熊貓的2個不同數據幀中找到2個點之間的距離? 似乎是一個相關的查詢,但不幸的是我不完全理解響應。

我的數據示例:

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          shape
0   2669827.294     1261034.528     square
1   2669634.483     1262412.587     square
2   2669766.266     1261209.646     triangle
3   2669960.683     1262550.374     circle


df2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],
                    'CoorN': [1262413, 1261211, 1261032, 1262550],
                    'color': ['purple', 'blue', 'blue', 'yellow']})

df2
     CoorE       CoorN      color
0   2669636     1262413     purple
1   2669765     1261211     blue
2   2669827     1261032     blue
3   2669961     1262550     yellow

我有我想與兩組坐標(例如“形狀”和“顏色”)進行比較的數據。 我想要的結果與最接近匹配的列對匹配:

     CoorE       CoorN      color   shape
0   2669636     1262413     purple  square
1   2669765     1261211     blue    triangle
2   2669827     1261032     blue    square
3   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 萬個條目,我想知道這樣做的內存密集程度最低的方法是什么。

要使用庫來計算距離,您需要使用統一系統。 從谷歌我相信你正在使用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")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM