Циклический просмотр 2-х панд данных и передача значений строк в функцию, вычисляющую расстояние - PullRequest
0 голосов
/ 02 октября 2018
import pandas as pd
dict = {'Origin Region': [1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 5.0],
        'Origin Latitude': [-36.45875, -36.24879, -36.789456, -38.14789, -36.15963, -36.159455, -36.2345, -36.12745],
        'Origin Longitude': [145.14563, 145.15987, 145.87456, 146.75314, 145.75483, 145.78458, 145.123654, 145.11111]}

df = pd.DataFrame(dict)

centres_dict = {'Origin Region': [1.0, 2.0, 3.0, 4.0, 5.0],
        'Origin Latitude': [-36.25361, -36.78541, -36.74859, -38.74123, -36.14538],
        'Origin Longitude': [145.12345, 145.36241, 145.12365, 146.75314, 145.75483]}

centres_df = pd.DataFrame(centres_dict)

grouped_region = df.groupby('Origin Region')
for region, region_group in grouped_region:
    outliers = region_group[['Origin Latitude', 'Origin Longitude']].where((region_group['Origin Latitude'] < -36.15))
    outliers.dropna(inplace=True)
    print(outliers)
    if(~outliers.empty):
        for index, outlier_value in outliers.iterrows():
            for another_index, centre_value in centres_df.iterrows():
                a = outlier_value['Origin Longitude']
                b = outlier_value['Origin Latitude']
                c = centres_df['Origin Longitude']
                d = centres_df['Origin Latitude']
                #find distance using the above and then find minimum distance

Я пытаюсь перебрать каждую группу кадра данных (df), затем отфильтровать значения в каждой группе на основе некоторого условия и выполнить вычисление расстояния между каждым из этих отфильтрованных значений (выбросов) и всеми значениями вдругой фрейм данных (centres_df).

У меня есть данные в фреймах данных, должен ли я преобразовать их в массивы, а затем использовать scipy cdist для вычисления расстояний?или просто использовать цикл и использовать мою собственную функцию расчета расстояния?Я не уверен, что это лучший способ сделать это.Или, может быть, использовать применить и вызвать мою собственную функцию расстояния?

1 Ответ

0 голосов
/ 03 октября 2018

Нет необходимости во вложенных циклах.Просто join сгруппированные выбросы в центры фрейм данных внутри группы по циклам.Затем рассчитайте расстояние между столбцами.Затем в конце свяжите все выпадающие кадры из словаря объектов фреймов данных.

Однако для векторизации вашего процесса эта Python Haversine Formula с использованием встроенной библиотеки math будет иметьбыть тупым

Numpy версия формулы haversine (получение массивов / рядов, а не скаляров в качестве входных данных)

def haversine_np(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
    c = 2 * np.arcsin(np.sqrt(a)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles

    return c * r

Панды процесс

# SET ORIGIN REGION AS INDEX (FOR LATER JOIN)
centres_df = centres_df.set_index('Origin Region')

df_dict = {}
grouped_region = df.sort_values('Origin Region').groupby('Origin Region')

for region, region_group in grouped_region:   
    # BUILD OUTLIER DF WITH Origin_Region as INDEX 
    outliers = region_group[['Origin Latitude', 'Origin Longitude']]\
                     .where((region_group['Origin Latitude'] < -36.15))\
                     .dropna()\
                     .assign(Origin_Region = region)\
                     .set_index('Origin_Region')

    # JOIN OUTLIERS WITH CENTRES DF, KEEPING ONLY MATCHED ROWS
    outliers = outliers.join(centres_df, how='inner', lsuffix='', rsuffix='_')

    # RUN CALCULATION (SEE NUMPY-IFIED haversine())
    outliers['Distance_km'] = haversine_np(outliers['Origin Longitude'], outliers['Origin Latitude'],
                                           outliers['Origin Longitude_'], outliers['Origin Latitude_'])

    outliers['Origin Region'] = region

    # ASSIGN TO DICTIONARY, RE-ORDERING COLUMNS
    df_dict[region] = outliers.reindex(outliers.columns[[5,0,1,2,3,4]], axis='columns')

# CONCATENATE OUTSIDE LOOP FOR SINGLE OBJECT
final_df = pd.concat(df_dict, ignore_index=True)

Выход

print(final_df)

#    Origin Region  Origin Latitude  Origin Longitude  Origin Latitude_  Origin Longitude_  Distance_km
# 0            1.0       -36.458750        145.145630         -36.25361          145.12345    22.896839
# 1            1.0       -36.159455        145.784580         -36.25361          145.12345    60.234887
# 2            2.0       -36.248790        145.159870         -36.78541          145.36241    62.354177
# 3            2.0       -36.234500        145.123654         -36.78541          145.36241    64.868402
# 4            3.0       -36.789456        145.874560         -36.74859          145.12365    67.040011
# 5            4.0       -38.147890        146.753140         -38.74123          146.75314    65.976398
# 6            5.0       -36.159630        145.754830         -36.14538          145.75483     1.584528
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...