Проще говоря, я пытаюсь сравнить значения из 2 столбцов первого DataFrame
с теми же столбцами в другом DataFrame
.Индексы совпавших строк сохраняются в виде нового столбца в первом DataFrame
.
Позвольте мне объяснить : я работаю с географическими объектами (широта / долгота) и основным DataFrame
- называется df
- имеет что-то вроде 55M наблюдений, которые выглядят примерно так:
![enter image description here](https://i.stack.imgur.com/TFF5H.png)
Как видите,Есть только две строки с данными, которые выглядят корректно (индексы 2 и 4).
Второй DataFrame
- называемый legit_df
- намного меньше и содержит все географические данные, которые я считаю законными:
![enter image description here](https://i.stack.imgur.com/21AlB.png)
Не вдаваясь в WHY, основная задача заключается в сравнении каждого наблюдения широты / долготы с df
с данными legit_df
.При успешном совпадении индекс legit_df
копируется в новый столбец df
, в результате чего df
выглядит следующим образом:
![enter image description here](https://i.stack.imgur.com/cTwYn.png)
Значение -1
используется, чтобы показать, когда не было успешного совпадения.В приведенном выше примере единственными действительными наблюдениями были наблюдения по индексам 2 и 4, которые нашли свои совпадения по индексам 1 и 2 в legit_df
.
В моем нынешнем подходе к решению этой проблемы используется .apply()
.Да, это медленно, но я не смог найти способ векторизации функции ниже или использовать Cython для ускорения:
def getLegitLocationIndex(lat, long):
idx = legit_df.index[(legit_df['pickup_latitude'] == lat) & (legit_df['pickup_longitude'] == long)].tolist()
if (not idx):
return -1
return idx[0]
df['legit'] = df.apply(lambda row: getLegitLocationIndex(row['pickup_latitude'], row['pickup_longitude']), axis=1)
Поскольку этот код заметно медленен на DataFrame
с 55M наблюдениями, мой вопрос : есть ли более быстрый способ решения этой проблемы?
Я делюсь Short, Self Contained, Correct (Compilable), Примером to help-you-help-me предлагает более быструю альтернативу:
import pandas as pd
import numpy as np
data1 = { 'pickup_latitude' : [41.366138, 40.190564, 40.769413],
'pickup_longitude' : [-73.137393, -74.689831, -73.863300]
}
legit_df = pd.DataFrame(data1)
display(legit_df)
####################################################################################
observations = 10000
lat_numbers = [41.366138, 40.190564, 40.769413, 10, 20, 30, 50, 60, 80, 90, 100]
lon_numbers = [-73.137393, -74.689831, -73.863300, 11, 21, 31, 51, 61, 81, 91, 101]
# Generate 10000 random integers between 0 and 10
random_idx = np.random.randint(low=0, high=len(lat_numbers)-1, size=observations)
lat_data = []
lon_data = []
# Create a Dataframe to store 10000 pairs of geographical coordinates
for i in range(observations):
lat_data.append(lat_numbers[random_idx[i]])
lon_data.append(lon_numbers[random_idx[i]])
df = pd.DataFrame({ 'pickup_latitude' : lat_data, 'pickup_longitude': lon_data })
display(df.head())
####################################################################################
def getLegitLocationIndex(lat, long):
idx = legit_df.index[(legit_df['pickup_latitude'] == lat) & (legit_df['pickup_longitude'] == long)].tolist()
if (not idx):
return -1
return idx[0]
df['legit'] = df.apply(lambda row: getLegitLocationIndex(row['pickup_latitude'], row['pickup_longitude']), axis=1)
display(df.head())
В приведенном выше примере создается df
всего с 10k observations
, что занимает около 7 секунд для запуска в моеммашина.При 100k observations
запуск занимает ~ 67 секунд.Теперь представьте мои страдания, когда мне нужно обработать 55 миллионов строк ...