Python Pandas: сравнить два фрейма данных вдоль одного столбца и вернуть содержимое строк обоих фреймов в другом фрейме данных - PullRequest
0 голосов
/ 20 мая 2018
  1. Я работаю с двумя CSV-файлами и импортирую их как dataframe, df1 и df2
  2. df1 имеет 50000 строк, а df2 имеет 150000 строк.
  3. Я хочу сравнить (выполнить итерацию покаждая строка) «время» df2 с помощью df1, найдите разницу во времени и верните значения всех столбцов, соответствующих аналогичной строке, сохраните ее в df3 ( синхронизация времени )
  4. ДляНапример, 35427949712 (из 'time' в df1) ближайший или равен 35427949712 (из 'time' в df2), поэтому я хотел бы вернуть содержимое в df1 ('speed_x' и 'yaw') и df2 ('speed' и 'yawrate') и сохраните в df3
  5. . Для этого я использовал два метода, показанных в коде.
  6. Код 1 занимает очень много времени, чтобы выполнить 72 часа, что не практично, так как у меня много CSV-файлов
  7. Код 2 дает мне «ошибку памяти» и ядро ​​умирает.

Было бы замечательно, если бы я получил более надежное решение для проблемы с учетом вычислительного времени, памяти и мощности (Intel Core i7-6700HQ, 8 ГБ ОЗУ)

Вотданные образца,

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

Code1

 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]

Code2

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 голосов
/ 20 мая 2018

просто примечание (не как ответ)

    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)

(всегда избегайте циклов)

и не указывайтене называйте свои переменные со встроенным именем (min)

0 голосов
/ 20 мая 2018

Вы ищете pandas.merge_asof.Это позволяет вам комбинировать 2 DataFrame s на ключе, в данном случае 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 объединяет только последнюю отсортированную строку справа df влево df вместо создания нескольких записей для каждого точного совпадения.Если это проблема, вместо этого вы можете сначала объединить точные ключи, чтобы получить все комбинации, а затем объединить остаток с asof.

...