Самый питонский способ группировки и фильтрации Pandas DataFrame с помощью set_index (), уже выполненный на самом внешнем уровне группировки? - PullRequest
0 голосов
/ 18 мая 2018

По разным причинам я хочу обработать Pandas DataFrame, который имеет такую ​​общую структуру:

import pandas
exampledf = pandas.DataFrame([
    {'PersonId':'123','Interest':'Basketball','SubmittedDate':datetime.datetime.strptime('2018-04-18 13:00:08', '%Y-%m-%d %H:%M:%S'),'Question':'Cake or death?'},
    {'PersonId':'123','Interest':'Baseball','SubmittedDate':datetime.datetime.strptime('1999-01-01 09:00:00', '%Y-%m-%d %H:%M:%S'),'Question':'Swallow speed?'},
    {'PersonId':'456','Interest':'Swimming','SubmittedDate':datetime.datetime.strptime('2011-02-27 23:00:00', '%Y-%m-%d %H:%M:%S'),'Question':'Answer to life, universe, everything?'},
    {'PersonId':'123','Interest':'Basketball','SubmittedDate':datetime.datetime.strptime('2018-04-18 13:00:00', '%Y-%m-%d %H:%M:%S'),'Question':'N/A'},
    {'PersonId':'789','Interest':'Racquetball','SubmittedDate':datetime.datetime.strptime('2018-05-02 12:00:00', '%Y-%m-%d %H:%M:%S'),'Question':'Will there be food?'},
    {'PersonId':'789','Interest':'Racquetball','SubmittedDate':datetime.datetime.strptime('2002-05-28 02:00:00', '%Y-%m-%d %H:%M:%S'),'Question':'Swag?'},
    {'PersonId':'789','Interest':'Racquetball','SubmittedDate':datetime.datetime.strptime('2018-05-02 12:00:00', '%Y-%m-%d %H:%M:%S'),'Question':'Good, thanks.'}
    ])
exampledf.set_index(['PersonId','Interest'], inplace=True)
print(exampledf)

Следовательно, выглядит так:

                                                   Question       SubmittedDate
PersonId Interest                                                              
123      Basketball                          Cake or death? 2018-04-18 13:00:08
         Baseball                            Swallow speed? 1999-01-01 09:00:00
456      Swimming     Answer to life, universe, everything? 2011-02-27 23:00:00
123      Basketball                                     N/A 2018-04-18 13:00:00
789      Racquetball                    Will there be food? 2018-05-02 12:00:00
         Racquetball                                  Swag? 2002-05-28 02:00:00
         Racquetball                          Good, thanks. 2018-05-02 12:00:00

Я хочу сохранить свой вывод вта же структура, что и у моего ввода, но за исключением любых строк, которые не имеют последней SubmittedDate, произвольно разрывая связи (первая найденная строка в порядке).

Я нашел много способов сделать это вообще (все виды дополнительного удаления и повторного добавления индексов) .Например:

  • Я могу сделать exampledf.reset_index() перед выполнением .groupby(), а затем просто .set_index() снова после того, как я закончу, но это кажется неудобным

Но я изо всех сил пытаюсь сделать это элегантно.Например:

  • Я могу .groupby(level=[0,1]), который добавляет избыточные уровни "PersonId" и "Interest", и это не вызывает проблемы для ".max ()", и который возвращаетсяк общему виду и ощущению просто отлично с .reset_index(level=[0,1], drop=True), но когда я пытаюсь втиснуть drop_duplicates() в «PersonId», «Interest» и «SubmittedDate» где-то во всем этом, я не могу получить егоработать так, чтобы не требовалось больше группировки и сброса.

Например, это дает мне ошибку KeyError: 'PersonId':

lastsubmittedperlookuptiesbrokendf = exampledf.groupby(level=[0,1]).apply(lambda x: x[x['SubmittedDate'] == x['SubmittedDate'].max()]).reset_index(level=[0,1], drop=True, inplace=False).drop_duplicates(subset=['PersonId','Interest','SubmittedDate'])

Как это происходит:

lastsubmittedperlookuptiesbrokendf = exampledf.groupby(level=[0,1]).apply(lambda x: x[x['SubmittedDate'] == x['SubmittedDate'].max()]).drop_duplicates(subset=['PersonId','Interest','SubmittedDate']).reset_index(level=[0,1], drop=True, inplace=False)

Какой самый Pythonic способ получить следующий вывод?

                                                   Question       SubmittedDate
PersonId Interest                                                              
123      Baseball                            Swallow speed? 1999-01-01 09:00:00
         Basketball                          Cake or death? 2018-04-18 13:00:08
456      Swimming     Answer to life, universe, everything? 2011-02-27 23:00:00
789      Racquetball                    Will there be food? 2018-05-02 12:00:00

(Обратите внимание, что моя текущая неуклюжая реализация пересортировала интересы, но мне все равно, в каком порядке онисортировать.)

1 Ответ

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

Поскольку сортировка быстрая, достаточно быстрая, не стоит слишком беспокоиться о выполнении дополнительной работы, превышающей max, одним из способов будет просто отсортировать SubmittedDate и затем взять последнюю после groupby:

In [11]: exampledf.sort_values("SubmittedDate").groupby(level=[0,1]).last()
Out[11]: 
                                                   Question       SubmittedDate
PersonId Interest                                                              
123      Baseball                            Swallow speed? 1999-01-01 09:00:00
         Basketball                          Cake or death? 2018-04-18 13:00:08
456      Swimming     Answer to life, universe, everything? 2011-02-27 23:00:00
789      Racquetball                          Good, thanks. 2018-05-02 12:00:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...