【问题标题】:pandas GroupBy: How to GroupBy and Aggregate data to show only the top 3 values of a field by countpandas GroupBy:如何分组和聚合数据以仅按计数显示字段的前 3 个值
【发布时间】:2020-01-18 22:30:39
【问题描述】:

这是我在 StackOverflow 上的第一个问题,所以我尽量做到简洁明了。非常感谢您提前的耐心等待。

背景

我有一个包含 17 个属性的训练数据集,其中包括:origin_station_codeorigin_stationdestination_station_codedestination_stationroute_codestart_timeend_timefleet_number、@ 987654332@、stationstation_typeplatformsch_arr_timesch_dep_timeact_arr_timeact_dep_timedate

在这些属性中,我只关心:dateorigin_stationdestination_stationstart_time

该数据集由 61 个单独的 CSV 文件组成,这些文件使用 glob 函数和一个循环组合在一起形成一个超过一百万行的 DataFrame。

DataFrame 的每一行代表火车旅程的一个单独站点。一条完整的路线由多个站点组成,包含 19 个站点的路线示例(Sugar Wave 到 Attempt Pin)如下图所示:here

通过连接origin_stationdestination_station 属性创建了一个名为complete_route name 的新属性。这可以识别所有的路由,其中​​有 81 个唯一条目。

任务

我的任务是使用 pandas 对 DataFrame 进行子集化,以便数据集按日期显示 3 条最受欢迎的路线。这个子集 DataFrame 应该显示datecomplete_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 上找到原始数据集和我当前状态的工作簿。静态工作簿也可以查看here

非常感谢!

【问题讨论】:

    标签: python python-3.x pandas pandas-groupby


    【解决方案1】:

    我会从你离开的地方继续

    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
    

    【讨论】:

    • 完美运行!感谢您抽出宝贵时间回复!
    【解决方案2】:
    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)
    

    【讨论】:

      【解决方案3】:

      好的,所以从你的工作部分开始,我会将它重写为:

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

      接下来你可以做的 IIUC:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-22
        • 2020-02-26
        • 1970-01-01
        • 2021-07-17
        • 2017-10-20
        • 2014-02-27
        • 2016-09-18
        相关资源
        最近更新 更多