如何将切片应用于数据框?

时间:2017-02-15 10:16:30

标签: python pandas

我的数据框中有大约500,000个条目,我想对这些数据应用某种平滑,以便显着减少条目数量。

这是一个示例数据框df

EVENT   GRADE   SERVICE_TIME   QUEUE_TIME   HOLD_TIME
AAA     3       170            20           12
AAA     4       165            15           10
AAA     3       172            24           12
AAA     3       105            5            10
BBB     5       40             10           10
BBB     5       60             10           8

目标是降低SERVICE_TIMEQUEUE_TIMEHOLD_TIME的粒度。

为此,我想按EVENTGRADE对参赛作品进行分组,并为60秒的切片窗口估算SERVICE_TIME的平均值(即[0; 60] ,[61; 120],[121; 180],[181; 240],依此类推,直至SERVICE_TIME的最大值。切片窗口的大小可以灵活地从60变为任何其他值,这一点很重要。 因此,切片应该应用于SERVICE_TIME,而其他列QUEUE_TIMEQUEUE_TIME应该相应地进行平均。

示例结果:

EVENT   GRADE   SERVICE_TIME   QUEUE_TIME   HOLD_TIME
AAA     3       171            22           12
AAA     3       105            5            10
AAA     4       165            15           10
BBB     5       50             10           9

因此,合并了SERVICE_TIME,170和172这两个值,因为它们都属于切片窗口[121; 180]。因此,我计算了平均值171,然后我只计算QUEUE_TIMEHOLD_TIME的相应值。

我该怎么做切片?

如果我不得不计算一个平均值(没有切片),那么我会这样做。

result = df.groupby(['EVENT','GRADE']).agg({'SERVICE_TIME': 'mean', 
                                            'QUEUE_TIME': 'mean', 
                                            'HOLD_TIME': 'mean'}).reset_index() 

2 个答案:

答案 0 :(得分:2)

你基本上有正确的想法,除了['EVENT','GRADE']而不是仅按SERVICE_GROUP进行分组,你还想要df['SERVICE_GROUP'] = (df['SERVICE_TIME']-1)//60 分组:

import numpy as np
import pandas as pd

df = pd.DataFrame({'EVENT': ['AAA', 'AAA', 'AAA', 'AAA', 'BBB', 'BBB'],
 'GRADE': [3, 4, 3, 3, 5, 5],
 'HOLD_TIME': [12, 10, 12, 10, 10, 8],
 'QUEUE_TIME': [20, 15, 24, 5, 10, 10],
 'SERVICE_TIME': [170, 165, 172, 105, 40, 60]})

df['SERVICE_GROUP'] = (df['SERVICE_TIME']-1)//60

result = (df.groupby(['EVENT','GRADE', 'SERVICE_GROUP'])
          .agg({'SERVICE_TIME': 'mean', 
                'QUEUE_TIME': 'mean', 
                'HOLD_TIME': 'mean'}).reset_index())
result = result.drop('SERVICE_GROUP', axis=1)
print(result)
  EVENT  GRADE  QUEUE_TIME  SERVICE_TIME  HOLD_TIME
0   AAA      3           5           105         10
1   AAA      3          22           171         12
2   AAA      4          15           165         10
3   BBB      5          10            50          9

打印

(df['SERVICE_TIME']-1)//60

SERVICE_GROUP中的-1代表SERVICE_TIMES 0的60分。 否则,df['SERVICE_GROUP'] = (df['SERVICE_TIME']-1)//60 40和60将不会组合在一起。

因此SERVICE_TIME导致了 (1, 60], (60, 120], (120, 180], ... 组为半开区间

list

答案 1 :(得分:1)

您可以生成一个基于窗口划分的新列(此处为'SERVICE_TIME_GROUP')。然后使用这个新专栏进行分组。分组后你可以放弃它。

WINDOW = 60
df['SERVICE_TIME_GROUP'] = df['SERVICE_TIME'].apply(lambda x : 1 if x==0 else math.ceil(x/(WINDOW*1.0));

result = df.groupby(['EVENT','GRADE','SERVICE_TIME_GROUP']).agg({'SERVICE_TIME': 'mean', 
                                            'QUEUE_TIME': 'mean', 
                                            'HOLD_TIME': 'mean'}).reset_index() 

result = result.drop('SERVICE_TIME_GROUP', 1)

对于[0; 60],[61; 120],[121; 180],[181; 240],ceil函数将起作用。一个特殊情况是0,需要单独处理。否则只需按窗口大小划分并将其细化,即可得到一组。
0 => 1
1-60 => 1
61-120 => 2
121-180 => 3
...