Python Pandas:比较一列中的两个数据帧,并返回另一个数据帧中两个数据帧的行内容

时间:2018-05-20 11:04:50

标签: python python-3.x algorithm pandas data-science

  1. 我正在使用两个csv文件并导入为dataframe,df1和df2
  2. df1有50000行,df2有150000行。
  3. 我想比较(遍历每一行)df2的'time' df1,找到时间差并返回所有列的值 对应于类似的行,将其保存在df3(时间同步
  4. 例如,35427949712(df1中的'time')最接近或等于 35427949712(df2中的'时间'),所以我想回复 内容为df1('velocity_x'和'yaw')和df2('velocity'和 'yawrate')并保存在df3
  5. 为此,我使用了两种技术,如代码所示。
  6. 代码1需要很长时间才能执行72小时,这不是练习,因为我有很多csv文件
  7. 代码2给了我“内存错误”并且内核死了。
  8. 如果考虑到计算时间,内存和功耗(英特尔酷睿i7-6700HQ,8 GB Ram),我会得到一个更强大的问题解决方案

    以下是示例数据

    import pandas as pd
    df1 = pd.DataFrame({'time': [35427889701, 35427909854, 35427929709,35427949712, 35428009860], 
                        'velocity_x':[12.5451, 12.5401,12.5351,12.5401,12.5251],
                       'yaw' : [-0.0787806, -0.0784749, -0.0794889,-0.0795915,-0.0795472]})
    
    df2 = pd.DataFrame({'time': [35427929709, 35427949712, 35427009860,35427029728, 35427049705], 
                        'velocity':[12.6583, 12.6556,12.6556,12.6556,12.6444],
                        'yawrate' : [-0.0750492, -0.0750492, -0.074351,-0.074351,-0.074351]})
    
    df3 = pd.DataFrame(columns=['time','velocity_x','yaw','velocity','yawrate'])
    

    代码1

     for index, row in df1.iterrows():
        min=100000
        for indexer, rows in df2.iterrows():
            if abs(float(row['time'])-float(rows['time']))<min:
                min = abs(float(row['time'])-float(rows['time']))
                #storing the position 
                pos = indexer
        df3.loc[index,'time'] = df1['time'][pos]
        df3.loc[index,'velocity_x'] = df1['velocity_x'][pos]
        df3.loc[index,'yaw'] = df1['yaw'][pos]
        df3.loc[index,'velocity'] = df2['velocity'][pos]
        df3.loc[index,'yawrate'] = df2['yawrate'][pos]
    

    代码2

    df1['key'] = 1
    df2['key'] = 1
    df1.rename(index=str, columns ={'time' : 'time_x'}, inplace=True)
    
    df = df2.merge(df1, on='key', how ='left').reset_index()
    df['diff'] = df.apply(lambda x: abs(x['time']  - x['time_x']), axis=1)
    df.sort_values(by=['time', 'diff'], inplace=True)
    
    df=df.groupby(['time']).first().reset_index()[['time', 'velocity_x', 'yaw', 'velocity', 'yawrate']]
    

2 个答案:

答案 0 :(得分:5)

您正在寻找 pandas.merge_asof 。它允许您将2 DataFrame组合在一个键上,在本例中为time,而不要求它们完全匹配。您可以选择direction来确定匹配的优先顺序,但在这种情况下,显然您需要nearest

  

“最近”搜索选择右侧DataFrame中的行,其中“on”键与左侧键的绝对距离最近。

需要注意的是,您需要对merge_asof的内容进行排序才能正常工作。

import pandas as pd

pd.merge_asof(df2.sort_values('time'), df1.sort_values('time'), on='time', direction='nearest')
#          time  velocity   yawrate  velocity_x       yaw
#0  35427009860   12.6556 -0.074351     12.5451 -0.078781
#1  35427029728   12.6556 -0.074351     12.5451 -0.078781
#2  35427049705   12.6444 -0.074351     12.5451 -0.078781
#3  35427929709   12.6583 -0.075049     12.5351 -0.079489
#4  35427949712   12.6556 -0.075049     12.5401 -0.079591

请注意您选择哪个DataFrame作为左框架或右框架,因为这会更改结果。在这种情况下,我选择time中距df1 time绝对距离最近的df2

如果右侧on中有重复的df密钥,您还需要小心,因为对于完全匹配,merge_asof仅合并右侧{{1}的最后一个排序行}向左df,而不是为每个完全匹配创建多个条目。如果这是一个问题,您可以先将精确键合并以获得所有组合,然后将余数与asof合并。

答案 1 :(得分:3)

只是旁注(不是答案)

size

可以写成

    min_delta=100000
    for indexer, rows in df2.iterrows():
        if abs(float(row['time'])-float(rows['time']))<min_delta:
            min_delta = abs(float(row['time'])-float(rows['time']))
            #storing the position
            pos = indexer

(总是避免循环)

并且不要使用内置名称( diff = np.abs(row['time'] - df2['time']) pos = np.argmin(diff) )调用您的变种