【问题标题】:Python Pandas : compare two data-frames along one column and return content of rows of both data frames in another data framePython Pandas:沿一列比较两个数据帧,并在另一个数据帧中返回两个数据帧的行内容
【发布时间】:2018-10-30 05:50:24
【问题描述】:
  1. 我正在处理两个 csv 文件并导入为数据框 df1 和 df2
  2. df1 有 50000 行,df2 有 150000 行。
  3. 我想比较(遍历每一行)df2 的“时间”与 df1,求时间差并返回所有列的值 对应类似的行,保存在df3中(时间同步
  4. 例如,35427949712(df1 中的“时间”)最接近或等于 35427949712(df2中的“时间”),所以我想返回 df1 ('velocity_x' and 'yaw') 和 df2 ('velocity' and 'yawrate') 并保存在 df3 中
  5. 为此,我使用了两种技术,如代码所示。
  6. 代码 1 需要很长时间才能执行 72 小时,这不是实践,因为我有很多 csv 文件
  7. 代码 2 出现“内存错误”并且内核死机。

如果考虑到计算时间、内存和功率(英特尔酷睿 i7-6700HQ,8 GB 内存),如果我能找到一个更强大的解决方案来解决这个问题,那就太好了

这是样本数据,

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']]

【问题讨论】:

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


    【解决方案1】:

    只是一个旁注(不是答案)

        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)
    

    (总是避免 for 循环)

    并且不要使用内置名称 (min) 调用您的变量

    【讨论】:

      【解决方案2】:

      您正在寻找 pandas.merge_asof。它允许您在一个键上组合 2 个 DataFrames,在本例中为 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 作为左框架或右框架,因为这会改变结果。在这种情况下,我选择df1 中的time,它与df2 中的time 绝对距离最近。

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

      【讨论】:

        猜你喜欢
        • 2019-01-23
        • 2019-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-24
        • 2017-04-25
        • 1970-01-01
        相关资源
        最近更新 更多