【问题标题】:pandas groupby: TOP 3 values for each grouppandas groupby:每个组的 TOP 3 值
【发布时间】:2018-05-22 01:33:18
【问题描述】:

pandas groupby: TOP 3 values in each group and store in DataFrame 中发布了一个新的、更通用的问题,并且那里已经回答了一个可行的解决方案。

在此示例中,我创建了一个数据框df,其中包含一些间隔 5 分钟的随机数据。 我想创建一个数据框 gdfgrouped df),其中列出了每小时的 3 个最高值

即:来自这一系列值

                     VAL
TIME                    
2017-12-08 00:00:00   29
2017-12-08 00:05:00   56
2017-12-08 00:10:00   82
2017-12-08 00:15:00   13
2017-12-08 00:20:00   35
2017-12-08 00:25:00   53
2017-12-08 00:30:00   25
2017-12-08 00:35:00   23
2017-12-08 00:40:00   21
2017-12-08 00:45:00   12
2017-12-08 00:50:00   15
2017-12-08 00:55:00    9
2017-12-08 01:00:00   13
2017-12-08 01:05:00   87
2017-12-08 01:10:00    9
2017-12-08 01:15:00   63
2017-12-08 01:20:00   62
2017-12-08 01:25:00   52
2017-12-08 01:30:00   43
2017-12-08 01:35:00   77
2017-12-08 01:40:00   95
2017-12-08 01:45:00   79
2017-12-08 01:50:00   77
2017-12-08 01:55:00    5
2017-12-08 02:00:00   78
2017-12-08 02:05:00   41
2017-12-08 02:10:00   10
2017-12-08 02:15:00   10
2017-12-08 02:20:00   88

​我非常接近解决方案,但我找不到最后一步的正确语法。我现在得到的(largest3)是:

                                           VAL
TIME                  TIME                    
2017-12-08 00:00:00   2017-12-08 00:10:00   82
                      2017-12-08 00:05:00   56
                      2017-12-08 00:25:00   53
2017-12-08 01:00:00   2017-12-08 01:40:00   95
                      2017-12-08 01:05:00   87
                      2017-12-08 01:45:00   79
2017-12-08 02:00:00   2017-12-08 02:20:00   88
                      2017-12-08 02:00:00   78
                      2017-12-08 02:05:00   41

我想从中获得这个gdf(达到每个最大值的时间并不重要):

                    VAL1  VAL2  VAL3
 TIME                
2017-12-08 00:00:00   82    56    53
2017-12-08 01:00:00   95    87    79
2017-12-08 02:00:00   88    78    41

这是代码:

import pandas as pd
from datetime import *
import numpy as np

# test data
df = pd.DataFrame()
date_ref = datetime(2017,12,8,0,0,0)
days = pd.date_range(date_ref, date_ref + timedelta(0.1), freq='5min')
np.random.seed(seed=1111)
data1 = np.random.randint(1, high=100, size=len(days))
df = pd.DataFrame({'TIME': days, 'VAL': data1})
df = df.set_index('TIME')
print(df)
print("----")

# groupby
group1 = df.groupby(pd.Grouper(freq='1H'))
largest3 = pd.DataFrame(group1['VAL'].nlargest(3))
print(largest3)

gdf = pd.DataFrame()
# ???? <-------------------

提前谢谢你。

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    注意:此解决方案仅在每个组至少有 3 行时才有效

    尝试以下方法:

    In [59]: x = (df.groupby(pd.Grouper(freq='H'))['VAL']
                    .apply(lambda x: x.nlargest(3))
                    .reset_index(level=1, drop=True)
                    .to_frame('VAL'))
    
    In [60]: x
    Out[60]:
                         VAL
    TIME
    2017-12-08 00:00:00   82
    2017-12-08 00:00:00   56
    2017-12-08 00:00:00   53
    2017-12-08 01:00:00   95
    2017-12-08 01:00:00   87
    2017-12-08 01:00:00   79
    2017-12-08 02:00:00   88
    2017-12-08 02:00:00   78
    2017-12-08 02:00:00   41
    
    In [61]: x.set_index(np.arange(len(x)) % 3, append=True)['VAL'].unstack().add_prefix('VAL')
    Out[61]:
                         VAL0  VAL1  VAL2
    TIME
    2017-12-08 00:00:00    82    56    53
    2017-12-08 01:00:00    95    87    79
    2017-12-08 02:00:00    88    78    41
    

    一些解释:

    In [94]: x.set_index(np.arange(len(x)) % 3, append=True)
    Out[94]:
                           VAL
    TIME
    2017-12-08 00:00:00 0   82
                        1   56
                        2   53
    2017-12-08 01:00:00 0   95
                        1   87
                        2   79
    2017-12-08 02:00:00 0   88
                        1   78
                        2   41
    
    In [95]: x.set_index(np.arange(len(x)) % 3, append=True)['VAL'].unstack()
    Out[95]:
                          0   1   2
    TIME
    2017-12-08 00:00:00  82  56  53
    2017-12-08 01:00:00  95  87  79
    2017-12-08 02:00:00  88  78  41
    

    【讨论】:

    • MaxU,首先非常感谢您的回答。它的“复杂性”让我感到惊讶。我并不是说它是错误的,但远远超出了我正确理解它的水平和技能。我期待更简单的事情,也许是从largest3 中提取结果。
    • @AlexPoca,尝试“逐步”执行它 - 这有助于理解每一步...
    • 当然,MaxU。这就是我要做的,我会在测试后选择你的答案。我只是对如此简单的事情有这个复杂的解决方案感到惊讶。我认为我最大的 3 数据帧的转置足以解决它。问题是我找不到这个“简单”的转置。
    • 在您的解决方案中有一点需要注意:每个组必须至少有 3 个元素。 set_index 不是基于组的,并且在更改组时不会重置计数器。我在你的回答中写了这个注释。
    • MaxU,当然,我现在才看到,在我的数据中,一些组的行数少于 3 行,所以我无法应用您的解决方案(我还是投票支持它,因为它很聪明)。据您所知,是否可以像我的第一个提案那样使用largest3 并从中提取数据?或者为每个组重置set_index
    猜你喜欢
    • 1970-01-01
    • 2019-06-12
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    相关资源
    最近更新 更多