Как выполнить условное соединение (например, SQL where join) фреймов данных в Python - PullRequest
3 голосов
/ 19 июня 2020

У меня есть два фрейма данных, как показано ниже

df1

visit_counts SG_lat   SG_long
0   3222.0  33.13623    -91.942026
1   6243.0  33.241981   -92.668384
2   5225.0  33.27683    -93.212498
3   6107.0  33.461784   -94.039191
4   3712.0  33.567683   -92.83685799999999

df2

num_transactions lat_dgr    long_dgr
0   45433   35.293364   -93.716224
1   41172   35.293364   -93.716224
2   41909   35.293364   -93.716224
3   37979   35.293364   -93.716224
4   43546   35.293364   -93.716224

Я хочу внутреннее объединить эти фреймы данных, если географическое расстояние между двумя координатами меньше 100 м, как показано ниже псевдокодом т.е.

## pseudo code
coords_1 = (df1.SG_lat, df1.SG_long)
coords_2 = (df2.lat_dgr, df2.long_dgr)
geopy.distance.vincenty(coords_1, coords_2).m < 100

В SQL мы можем сделать это с условием where, как показано ниже

ST_DISTANCE(ST_GEOGPOINT(long_dgr,lat_dgr), ST_GEOGPOINT( sg_long,sg_lat)) <= 100

pandas функция слияния не допускает условия where. Есть ли другой способ объединить эти два фрейма данных. У меня нет других ключевых столбцов для объединения, а затем фильтрации с использованием lo c.

1 Ответ

0 голосов
/ 19 июня 2020

Если вы используете sh для вычисления расстояния для всех комбинаций строк в таблицах, вы можете: 1) создать декартово произведение таблиц, 2) вычислить расстояние, 3) отфильтровать пороговое значение. Это неэффективно с памятью, поскольку вы расширяете все комбинации строк, но, по крайней мере, просто вычислить:

import pandas as pd
from geopy.distance import geodesic

# create a dummy key to join all rows from df1 to df2:
df1["dummy_key"] = 0
df2["dummy_key"] = 0

# create cartesian product table
df3 = pd.merge(left=df1, right=df2, on="dummy_key").drop(columns=["dummy_key"])

# apply geodesic (newer version of geopy.distance.vincenty) to get the distance in meters for each row
dist = df3.apply(lambda row: geodesic((row["SG_lat"], row["SG_long"]), (row["lat_dgr"], row["long_dgr"])).m, axis=1) 

# filter for rows that you desire:
df3 = df3[dist < 100]
...