Использование Groupby и удаление групп, содержащих определенные характеристики

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

У меня есть следующий фрейм данных

 import pandas as pd, numpy as np
df = pd.DataFrame({'Instrument':['AAA','BBB','BBB','BBB','BBB','BBB','CCC','CCC'], 
'Date':['2020-01-02','2020-01-02','2020-01-02','2020-01-02','2020-01-02','2020-01-02','2020-01-03','2020-01-03'],
'Time':['00:00:00.000','00:00:00.000','07:01:04.231','09:47:07.136','09:57:13.757','09:58:26.841','09:28:31.161','09:28:43.562'], 
'ID': [5939908167998967312,5958912126973154535,5958912126973154535,5958912126973154535,5969584811466071582,5969584811466071582,5970013075540072892,5970013075540072892]})
  

Я хочу сгруппировать инструмент, дату и идентификатор и удалить группу, содержащую время 00:00:000, в той же группе идентификаторов.

Желаемый результат выглядит следующим образом:

 import pandas as pd, numpy as np
df_remove_group = pd.DataFrame({'Instrument':['BBB','BBB','CCC','CCC'], 
'Date':['2020-01-02','2020-01-02','2020-01-03','2020-01-03'],
'Time':['09:57:13.757','09:58:26.841','09:28:31.161','09:28:43.562'], 
'ID': [5969584811466071582,5969584811466071582,5970013075540072892,5970013075540072892]})
  

Я могу кодировать только до этой части
df.groupby(['Instrument','Date','BidID']).apply(lambda x: x.sort_values(['Time'], ascending = True)).reset_index(drop=True)

Мой код может быть бесполезен для результата, которого я хочу достичь. Пожалуйста, помогите.

Спасибо.

Ответ №1:

  • .filter для групп, где минимальное Time значение не '00:00:00.000'
    • Этот ответ предполагает, что Time это str тип, как показано в примере данных.
    • pandas.Series.min будет правильно вычисляться '00:00:00.000' как минимальное значение, потому что '0' вычисляется как меньшее, чем другие числовые строки.
  • Также смотрите pandas: Руководство пользователя по фильтрации
 dfg = df.groupby(['Instrument', 'Date', 'ID']).filter(lambda x: x.Time.min() != '00:00:00.000')

# display(dfg)
Instrument        Date          Time                   ID
       BBB  2020-01-02  09:57:13.757  5969584811466071582
       BBB  2020-01-02  09:58:26.841  5969584811466071582
       CCC  2020-01-03  09:28:31.161  5970013075540072892
       CCC  2020-01-03  09:28:43.562  5970013075540072892
  

Ответ №2:

Использование DataFrame.groupby groupby.filter :

 df['Time'] = pd.to_timedelta(df['Time'])

s = df.groupby(['Instrument', 'Date', 'ID'])
      .filter(lambda s: ~s['Time'].eq(pd.Timedelta(0)).any())
  

Результат:

   Instrument        Date            Time                   ID
4        BBB  2020-01-02 09:57:13.757000  5969584811466071582
5        BBB  2020-01-02 09:58:26.841000  5969584811466071582
6        CCC  2020-01-03 09:28:31.161000  5970013075540072892
7        CCC  2020-01-03 09:28:43.562000  5970013075540072892
  

Ответ №3:

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

 m = df['Time'].ne('00:00:00.000').groupby([df.Instrument,df.Date,df.ID]).transform('all')

df_filter = df[m]

Out[73]:
  Instrument        Date          Time                   ID
4        BBB  2020-01-02  09:57:13.757  5969584811466071582
5        BBB  2020-01-02  09:58:26.841  5969584811466071582
6        CCC  2020-01-03  09:28:31.161  5970013075540072892
7        CCC  2020-01-03  09:28:43.562  5970013075540072892
  

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

1. Спасибо. Я попробовал это на своем большом наборе данных, и он возвращает » неправильный тип операнда для унарного ~: ‘float’ «. Могу ли я узнать, как это исправить?

2. @ShaunLim: Я изменил на ne и all без использования ~ . Проверьте мой обновленный ответ