【问题标题】:Looping through 2 Pandas Dataframes and passing row values to a function calculating distance循环遍历 2 个 Pandas 数据帧并将行值传递给计算距离的函数
【发布时间】:2018-10-04 22:09:33
【问题描述】:
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) 的每一组,然后根据某些条件过滤每组中的值,并在每个过滤后的值(异常值)与另一个数据帧中的所有值之间执行距离计算(中心_df)。

我有数据帧中的数据,我应该将它们转换为数组,然后使用 scipy cdist 计算距离吗?还是简单地使用循环并使用我自己的距离计算功能?我不确定这样做的最佳方法是什么。或者也许使用 apply 并调用我自己的距离函数?

【问题讨论】:

  • 当您在 groupby 循环中运行时,似乎没有单个 Outlier Dataframe
  • 我想计算 grouped_region 中每个组的异常值。以及这些组中每个异常值与中心数据框中所有点的距离。
  • 请发布minimal reproducible example,包括示例数据、可编译代码以及所有需要的import 行和haversine() 之类的赋值,我们可以在空的Python 环境中运行,以及所需的输出。另请参阅How to make good reproducible pandas examples
  • 嗨,Parafait,尽我所能提出最少且可重现的代码。

标签: python python-3.x pandas dataframe


【解决方案1】:

不需要嵌套循环。只需 join 将分组的 outliers 到 group by 循环内的 centres 数据框。然后计算跨列的距离。最后,从数据框对象的字典中将所有异常帧绑定在一起。

但是,要使用内置的 math 库对您的流程进行矢量化,此 Python Haversine Formula 必须是 numpy 化的。

Numpy 版本的半正弦公式(接收数组/序列而不是标量作为输入)

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

【讨论】:

  • 我需要的是没有。异常值的次数没有。每个组的每个组的 center_df 中的点数。如果没有。第 1 组的异常值是 2 分,没有。 centered_df(固定)中的点数为 5,我需要 2x5 = 10 距离
  • 查看编辑以调整 outliers 构建内部循环并使用 haversine() 的 numpy 化版本。
猜你喜欢
  • 2019-05-25
  • 2016-10-02
  • 1970-01-01
  • 2021-11-18
  • 2021-05-16
  • 2019-03-20
  • 2019-01-01
  • 1970-01-01
  • 2019-03-06
相关资源
最近更新 更多