2017-02-15 5 views
0

У меня около 500 000 записей в моем фреймворке данных, и я хотел бы применить какое-то сглаживание к этим данным, чтобы значительно уменьшить количество записей.Как применить нарезку к DataFrame?

Это образец dataframe 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_TIME, QUEUE_TIME и HOLD_TIME.

Чтобы сделать это, я хочу, чтобы записи группы по EVENT и GRADE, и оценить средние значения SERVICE_TIME для окна среза 60 секунд (то есть [0; 60], [61; 120], [121; 180 ], [181; 240] и т. Д. До максимального значения SERVICE_TIME). Важно, чтобы размер окна резки был гибко изменен с 60 на любое другое значение. Итак, нарезка должна применяться к SERVICE_TIME, в то время как другие столбцы QUEUE_TIME и QUEUE_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_TIME и HOLD_TIME.

Как это сделать?

Если бы мне пришлось просто вычислить среднее (без разрезания), то я сделал бы это так.

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

ответ

2

Вы в основном имеют правильную идею, за исключением того, что вместо группировки лишь на ['EVENT','GRADE'], вы также хотите GroupBy 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 

-1 в (df['SERVICE_TIME']-1)//60 составляет 60 часть SERVICE_GROUP 0. В противном случае SERVICE_TIMES 40 и 60 не были бы сгруппированы.

Таким образом df['SERVICE_GROUP'] = (df['SERVICE_TIME']-1)//60 вызывает SERVICE_TIME группы, чтобы быть полуоткрытые интервалы

(1, 60], (60, 120], (120, 180], ... 
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
...

Смежные вопросы