Фильтрация фрейма данных в pandas на основе критериев из другого фрейма данных

#python #pandas

#python #pandas

Вопрос:

У меня есть два фрейма данных, один с миллионами строк данных, а другой с несколькими сотнями записей, и мне нужно отфильтровать первый фрейм данных по трем столбцам из второго.

Итак, в основном мне нужно выполнить итерацию по каждой строке в df2 и посмотреть, есть ли какие-либо строки в df1 с одинаковыми тикерами и датами между начальной и конечной датой. К сожалению, я понятия не имею, как выполнить это с помощью python.

Итак, мои фреймы данных похожи на следующие

      Ticker    date
1    AA       2013-12-31 
3    AA       2015-02-28 
4    AA       2016-03-31 
5    AA       2016-04-30 
6    BB       2014-05-31 
7    BB       2014-06-30 
8    BB       2017-07-31 
9    CC       2014-08-31 
10   CC       2017-09-30 
11   CC       2018-10-31 
12   CC       2018-11-30 
13   DD       2018-11-30 
14   DD       2018-12-21
  

Второй:

      Ticker    StartDate   EndDate
1    AA       2016-01-01   2017-01-01
2    BB       2014-01-01   2015-01-01
3    CC       2018-01-01   2019-01-01
4    AA       2013-01-01   2014-01-01
  

Мой ожидаемый результат — отфильтрованный первый фрейм данных со всеми записями для всех тикеров в df2 между датами начала и окончания:

    Ticker     date
1    AA       2013-12-31  
2    AA       2016-03-31 
3    AA       2016-04-30 
4    BB       2014-05-31 
5    BB       2014-06-30  
6    CC       2018-11-30 
  

UPD

Итак, я попробовал следующее:

 df4 = pd.DataFrame()
###create empty dataframe
for index, row in df2.iterrows():
    df3 =df1.loc[(df1['DATE']>=row['StartDate'])amp;(df1['DATE']<=row['EndDate'])amp;(df1['Ticker'] ==row['Ticker'])]
###Go through rows of dataframe2, for every row i look if there any rows in df1 that falls under criteria 
    df4 = df4.append(df3)
### append filtered results of one row to empty dataframe 
  

Это работает, но на это уходит много времени — я пытался отфильтровать 2% своих данных, и это заняло около 25 минут

Есть ли какой-нибудь способ ускорить это?

Ответ №1:

Попробуйте это:

 df3 = df1.merge(df2)
df3 =df3.loc[(df3['date']>=df3['StartDate'])amp;(df3['date']<=df3['EndDate'])]
df3.drop(['date'], axis = 1)
  

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

1. Я пробовал аналогичный подход, и он не сработал. Насколько я понимаю, слияние работает аналогично объединению баз данных, и это мне здесь не помогло бы. Второй фрейм данных содержит разные строки с одинаковыми ресурсами, поэтому я не могу присоединиться к ресурсам, а позже просто фильтровать строки, где дата не находится в границах даты окончания / начала

Ответ №2:

Похоже, вы можете использовать group by из create диапазоны дат для каждого тикера

 data = pd.read_clipboard()
flt_df = pd.read_clipboard()
  

данные

    Ticker        date
1      AA  2013-12-31
3      AA  2015-02-28
4      AA  2016-03-31
5      AA  2016-04-30
6      BB  2014-05-31
7      BB  2014-06-30
8      BB  2017-07-31
9      CC  2014-08-31
10     CC  2017-09-30
11     CC  2018-10-31
12     CC  2018-11-30
13     DD  2018-11-30
14     DD  2018-12-21
  

fl_df

   Ticker   StartDate     EndDate
1     AA  2016-01-01  2017-01-01
2     BB  2014-01-01  2015-01-01
3     CC  2018-01-01  2019-01-01
4     AA  2013-01-01  2014-01-01

grouped_df = flt_df.groupby('Ticker').agg({'StartDate':'min','EndDate':'max'})
merged = data.set_index('Ticker').join(grouped_df)
merged = merged[(merged.date>=merged.StartDate)amp;(merged.date<=merged.EndDate)]
merged.drop(['StartDate','EndDate'],axis=1,inplace=True)
  

объединенный

               date
Ticker            
AA      2013-12-31
AA      2015-02-28
AA      2016-03-31
AA      2016-04-30
BB      2014-05-31
BB      2014-06-30
CC      2018-10-31
CC      2018-11-30