pandas groupby:每组中的前3个值并存储在DataFrame中

时间:2017-12-08 12:12:19

标签: python pandas

这是pandas groupby: TOP 3 values for each group的后续内容 如果每组中的行数至少为3,那么在那里描述的解决方案是完美的,但如果至少有一个组不足够大,则它会失败。

我在这里提出一个需要另一种解决方案的新数据集。

有些数据是随机保存的,我需要找到每小时最高的3个值:

                     VAL
TIME                    
2017-12-08 00:55:00   29
2017-12-08 01:10:00   56
2017-12-08 01:25:00   82
2017-12-08 01:40:00   13
2017-12-08 01:55:00   35
2017-12-08 02:10:00   53
2017-12-08 02:25:00   25
2017-12-08 02:40:00   23
2017-12-08 02:55:00   21
2017-12-08 03:10:00   12
2017-12-08 03:25:00   15

它应该返回此DataFrame,而不是检测到max的时间:

                     VAL1  VAL2  VAL3
TIME 
2017-12-08 00:00:00   29   None  None
2017-12-08 01:00:00   82    56    35
2017-12-08 02:00:00   53    25    23
2017-12-08 03:00:00   15    12   None

None属于少于3行的小组。

生成数据集的代码是:

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

df = pd.DataFrame()

date_ref = datetime(2017,12,8,0,55,0)
days = pd.date_range(date_ref, date_ref + timedelta(0.11), freq='15min')

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')

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

我的问题是如何将这些值保存到新的DataFrame中,也许可以从largest3获取它们:

                                         VAL
TIME                TIME                    
2017-12-08 00:00:00 2017-12-08 00:55:00   29
2017-12-08 01:00:00 2017-12-08 01:25:00   82
                    2017-12-08 01:10:00   56
                    2017-12-08 01:55:00   35
2017-12-08 02:00:00 2017-12-08 02:10:00   53
                    2017-12-08 02:25:00   25
                    2017-12-08 02:40:00   23
2017-12-08 03:00:00 2017-12-08 03:25:00   15
                    2017-12-08 03:10:00   12

编辑:添加了reset_index

largest3 = pd.DataFrame(group1["VAL"].nlargest(3)).reset_index(level=1, drop=True)

返回更好的概述,但我不知道如何继续前进:

                     VAL
TIME                    
2017-12-08 00:00:00   29
2017-12-08 01:00:00   82
2017-12-08 01:00:00   56
2017-12-08 01:00:00   35
2017-12-08 02:00:00   53
2017-12-08 02:00:00   25
2017-12-08 02:00:00   23
2017-12-08 03:00:00   15
2017-12-08 03:00:00   12

1 个答案:

答案 0 :(得分:2)

诀窍是创建一个不基于set_index +模数的索引,cumcount在组内提供渐进式计数器:

largest3 = (pd.DataFrame(group1["VAL"]
    .nlargest(3))
    .reset_index(level=1, drop=True))

largest3['index'] = largest3.groupby('TIME').cumcount()  # temporary index

largest3 = (largest3.set_index("index", append=True)['VAL']
    .unstack()
    .add_prefix('VAL'))

结果是,按要求:

index                VAL0  VAL1  VAL2
TIME                                 
2017-12-08 00:00:00  29.0   NaN   NaN
2017-12-08 01:00:00  82.0  56.0  35.0
2017-12-08 02:00:00  53.0  25.0  23.0
2017-12-08 03:00:00  15.0  12.0   NaN