Создайте col на основе сопоставления исторических записей с другого фрейма данных - PullRequest
1 голос
/ 28 апреля 2020

У меня есть два кадра данных, df_a и df_b:

df_a = pd.DataFrame({
    'date_a': [
        datetime.datetime(2020,1,9,1,1,1,1),
        datetime.datetime(2020,1,4,1,1,1,1),
        datetime.datetime(2020,1,1,1,1,1,1),
        datetime.datetime(2020,1,6,1,1,1,1)
    ],
    'ID': ['a', 'a', 'c', 'a']
})

df_b = pd.DataFrame({
    'date_b': [
        datetime.datetime(2020,1,8,1,1,1,1),
        datetime.datetime(2020,1,5,1,1,1,1),
        datetime.datetime(2020,1,5,1,1,1,1)
    ],
    'ID_1': ['a', 'b', 'f'],
    'ID_2': ['d', 'a', 'c']
})

И я хочу создать новый столбец (V) в df_a, то есть True, если есть запись в df_b, где df_b.ID_1 или df_b.ID_2 соответствует df_a.ID AND df_b.date_b, меньше или равна df_a.date_a. Результат будет выглядеть следующим образом:

df_a
    date_a                      ID  V
0   2020-01-09 01:01:01.000001  a   True
1   2020-01-04 01:01:01.000001  a   False
2   2020-01-01 01:01:01.000001  c   False
3   2020-01-06 01:01:01.000001  a   True

По сути, я хочу проверить для каждой строки в df_a, есть ли историческая запись для этого ID. Надеюсь, что вопрос имеет смысл!

1 Ответ

1 голос
/ 28 апреля 2020

Один из способов - растопить df_b, затем выполнить перекрестное слияние на ID и запросить:

unique_id = (df_b.melt('date_b', value_name='ID')
                .drop('variable',axis=1)
                .sort_values('date_b')
                .drop_duplicates('ID'))

(df_a.merge(unique_id,
           on='ID',
           how='left'
          )
     .assign(V=lambda x: x.date_b <= x.date_a)
     .drop('date_b',axis=1)
)

Вывод:

                      date_a ID      V
0 2020-01-09 01:01:01.000001  a   True
1 2020-01-04 01:01:01.000001  a  False
2 2020-01-01 01:01:01.000001  c  False
3 2020-01-06 01:01:01.000001  a   True

Другой способ - использовать merge_asof, но сначала вам также нужно отфильтровать df_b для минимальной даты в каждом идентификаторе:

# unique_id as above
(pd.merge_asof(df_a.sort_values('date_a'), 
              unique_id, 
              left_on='date_a',
              right_on='date_b', 
              by='ID')
   .assign(V=lambda x: x.date_b.notnull())
   .drop('date_b', axis=1)
)

Вывод:

                      date_a ID      V
0 2020-01-01 01:01:01.000001  c  False
1 2020-01-04 01:01:01.000001  a  False
2 2020-01-06 01:01:01.000001  a   True
3 2020-01-09 01:01:01.000001  a   True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...