pandas GroupBy: как группировать и агрегировать данные, чтобы отображать только три верхних значения поля по количеству - PullRequest
2 голосов
/ 19 января 2020

Это мой первый вопрос по StackOverflow, поэтому я постарался быть максимально четким и лаконичным. Большое спасибо за ваше терпение заранее.

Справочная информация

У меня есть набор данных о поездах с 17 атрибутами, в том числе: origin_station_code, origin_station, destination_station_code, destination_station, route_code, start_time, end_time, fleet_number, station_code, station, station_type, platform, sch_arr_time, sch_dep_time, act_arr_time , act_dep_time, date.

Из этих атрибутов меня интересуют только: date, origin_station, destination_station и start_time.

Этот набор данных состоит из 61 отдельных CSV-файлов, которые были объединены в один DataFrame из более чем миллиона строк с использованием функции glob и др. oop.

Каждая строка DataFrame представляет отдельную остановку поездки на поезде. Полный маршрут состоит из нескольких остановок, на следующем снимке экрана показан пример маршрута, состоящего из 19 остановок, Sugar Wave to Attempt Pin: here .

Новый атрибут с именем complete_route name был создан путем объединения атрибутов origin_station и destination_station. Это может идентифицировать все маршруты, из которых существует 81 уникальная запись.

Задача

Моя задача состоит в том, чтобы создать подмножество DataFrame, используя pandas, так что набор данных показывает 3 самых популярных маршрута, на дату. Этот подмножество DataFrame должно показывать date, complete_route name и количество раз, которое этот маршрут проходил каждый день. Количество уникальных раз, когда маршрут проходил, можно определить, применив метод nunique к атрибуту start_time (тип даты / времени).

Мой текущий прогресс

В настоящее время мой код GroupBy и Aggregate может показывать, сколько раз каждый маршрут выполнялся в день, следующим образом:

df_grouped = df.groupby(
   ['date', 'complete_route_name']
).agg(
    {
         'start_time': 'nunique'    # count the number of unique routes by using the 'nunique' of the start_times
    }
).reset_index()

Теперь я хочу взять свой существующий код, чтобы он отображал только 3 уникальных маршрута по количеству в день, например,

date           complete_route_name                                   count
2015-08-01     Attempt Pin to Roll Test                              101
               Suit Treatment Turnback to Spiders Toothbrush         93       
               Concourse Village to Port Morris                      87
2015-08-02     Bridge Bottle to Ants Attempt                         119
               North Riverdale to Eastchester                        117
               Wakefield to Kingsbridge                              101

......

2015-09-30     Castleton Corners to Dongan Hills                     121
               Eltingville to Graniteville                           119
               Great Kills to Castleton                              117

Любая помощь с этим будет принята с благодарностью!

Дополнительные ресурсы

Исходный набор данных и мою рабочую книгу в ее текущем состоянии можно найти на моем GitHub , если это имеет какое-либо значение / интерес. Статистическую книгу c можно также просмотреть здесь .

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 19 января 2020

Я продолжу с того места, где вы ушли

df_agg = df.groupby(['date', 'route_name']).agg({'start_time':'nunique'}).reset_index()

Тогда я бы сделал следующее, чтобы найти то, о чем вы просили

df_sorted_by_group = df_agg.groupby(['date']).apply(
      lambda x: x.sort_values(['start_time'],ascending = False)
      ).reset_index(drop = True)

Последний шаг

df_final = df_sorted_by_group.groupby(['date']).head(3)

Пример кода

import pandas as pd
routes = {'route_name': [ 'A to B', 'A to B',  'B to C',   'B to C',   'C to D', 'C to D',  'C to D', 'C to D',  'D to E',
                        'A to Z', 'A to Z',  'B to Z',   'B to Z',   'C to Z', 'C to Z',  'C to Z', 'C to Z',  'D to Z'],
'date': ['01/01/2015','01/01/2015','01/01/2015','01/01/2015','01/01/2015','01/01/2015','01/01/2015','01/01/2015','01/01/2015',
        '02/01/2015','02/01/2015','02/01/2015','02/01/2015','02/01/2015','02/01/2015','02/01/2015','02/01/2015','02/01/2015'],
'start_time': ['A1','A2','A3','A4','A5','A6','A7','A8','A9','A10','A11','A12','A13','A14','A15','A16','A17','A18']

         }

df = pd.DataFrame(routes)
df['date'] = pd.to_datetime(df['date'],format ='%d/%m/%Y')
df

    route_name  date    start_time
0   A to B  2015-01-01  A1
1   A to B  2015-01-01  A2
2   B to C  2015-01-01  A3
3   B to C  2015-01-01  A4
4   C to D  2015-01-01  A5
5   C to D  2015-01-01  A6
6   C to D  2015-01-01  A7
7   C to D  2015-01-01  A8
8   D to E  2015-01-01  A9
9   A to Z  2015-01-02  A10
10  A to Z  2015-01-02  A11
11  B to Z  2015-01-02  A12
12  B to Z  2015-01-02  A13
13  C to Z  2015-01-02  A14
14  C to Z  2015-01-02  A15
15  C to Z  2015-01-02  A16
16  C to Z  2015-01-02  A17
17  D to Z  2015-01-02  A18

После применения сценария, приведенного выше, вы получите следующие результаты

 df_final
     date   route_name  start_time
0   2015-01-01  C to D  4
1   2015-01-01  A to B  2
2   2015-01-01  B to C  2
4   2015-01-02  C to Z  4
5   2015-01-02  A to Z  2
6   2015-01-02  B to Z  2
1 голос
/ 15 апреля 2020
df_sorted_by_group = df_grouped.groupby(['Date']).apply(
      lambda x: x.sort_values(['Count'],ascending = False)
      ).reset_index(drop = True)

df_grouped_top16 = df_sorted_by_group.groupby(['Date']).head(16)
0 голосов
/ 19 января 2020

Хорошо, поэтому, начиная с вашей рабочей части, я переписал бы ее следующим образом:

df_grouped = df.groupby(
   ['date', 'complete_route_name'], as_index=False
)['start_time'].nunique()

Далее IIU C вы можете сделать:

df2=df_grouped.groupby("date").rank().le(3)
df_grouped.loc[df2.loc[df2].index]
...