Объединение 2 кадров данных по столбцу даты (без предвзятого отношения)

#python #pandas #dataframe #date

Вопрос:

Я пытаюсь создать функцию python, которая принимает 2 кадра данных (dfA, dfB) и объединяет их на основе столбца даты. При объединении B ищет ближайшую дату в A, которая либо равна данной дате, либо предшествует ей. Это делается для того, чтобы данные в dfAB не заглядывали в будущее (именно поэтому dfAB.iloc[4][‘дата’] = 1/4/21, а не 1/9/21)

dfA

       date  i
0   1/1/21  0
1   1/3/21  0
2   1/4/21  0
3  1/10/21  0
 

dfB

      date  j  k
0  1/1/21  0  0
1  1/2/21  0  0
2  1/3/21  0  0
3  1/9/21  0  0
4  1/12/21 0  0
 

dfAB (обратите внимание, что для каждой строки dfB существует строка dfAB)

      date  j  k  i
0  1/1/21  0  0  0
1  1/1/21  0  0  0
2  1/3/21  0  0  0
3  1/4/21  0  0  0
4  1/10/21 0  0  0
 

Значения в столбцах i, j, k являются просто произвольными значениями

Комментарии:

1. pandas.pydata.org/docs/reference/api/…

2. Суть вашего результата несколько сбивает с толку. Таким образом, для каждой строки B должна быть строка AB, но с датой, перенесенной назад, чтобы соответствовать какой-то дате в A? Кроме того, я думаю, что то, что вы хотите, было бы более понятным, если бы вы поместили разные числа в строки i, j и k, чтобы мы могли лучше видеть, как сопоставляются данные. Тем не менее, это звучит так , как будто это должно быть выполнимо pd.merge_asof , но похоже, что вы делаете некоторые дополнительные искажения.

Ответ №1:

Итак, чтобы сделать это, мы можем использовать pd.merge_asof и немного хитрости, чтобы переместить date столбец dfB обратно в date столбец с dfA

 # a.csv
date  i
1/1/21  0
1/3/21  0
1/4/21  0
1/10/21  0
 
 # b.csv
date  j  k
1/1/21  0  0
1/2/21  0  0
1/3/21  0  0
1/9/21  0  0
1/12/21 0  0
 
 # merge_ab.py
import pandas as pd

dfA = pd.read_csv(
    'a.csv',
    delim_whitespace=True,
    parse_dates=['date'],
    dayfirst=True,
)

dfB = pd.read_csv(
    'b.csv',
    delim_whitespace=True,
    parse_dates=['date'],
    dayfirst=True,
)

dfA['new_date'] = dfA['date']
dfAB = pd.merge_asof(dfB, dfA, on='date', direction='backward')
dfAB['date'] = dfAB['new_date']
dfAB = dfAB.drop(columns=['new_date'])

print(dfAB)
#         date  j  k  i
# 0 2021-01-01  0  0  0
# 1 2021-01-01  0  0  0
# 2 2021-03-01  0  0  0
# 3 2021-04-01  0  0  0
# 4 2021-10-01  0  0  0
 

Здесь pd.merge_asof делается тяжелая работа. Мы объединяем строки «Дата dfB dfA with the rows of . This should make it so the data in any row of dfAB only has data from equal to or before the corresponding row in dfB . We do a little song and dance to copy the Дата column in dfA and then copy that over to the column in dfAB», чтобы получить желаемый результат.

Мне не на 100% ясно , чего вы хотите direction='backward' , так как все ваши примеры данных таковы 0 , но если они выглядят неправильно, вы всегда можете переключиться на direction='forward' .