2015-11-10 1 views
1

У меня есть данные временного ряда, которые не имеют некоторых данных и имеют разбросанные значения NaN по другим причинам. Мне нужно объединить данные в квартальные и годовые серии, но я не хочу сообщать данные за четверть/год с отсутствующими данными. Например, в приведенных ниже данных я не хочу сообщать данные за 1 квартал 2014 года, потому что я отсутствую в январе этого года.Pandas Grouper по частоте с требованием полноты

import pandas as pd, numpy as np 

df = pd.DataFrame([ 
    ('Monthly','2014-02-1', 529.1), 
    ('Monthly','2014-03-1', 67.1), 
    ('Monthly','2014-04-1', np.nan), 
    ('Monthly','2014-05-1', 146.8), 
    ('Monthly','2014-06-1', 469.7), 
    ('Monthly','2014-07-1', 82.9), 
    ('Monthly','2014-08-1', 636.9), 
    ('Monthly','2014-09-1', 520.9), 
    ('Monthly','2014-10-1', 217.4), 
    ('Monthly','2014-11-1', 776.6), 
    ('Monthly','2014-12-1', 18.4), 
    ('Monthly','2015-01-1', 376.7), 
    ('Monthly','2015-02-1', 266.5), 
    ('Monthly','2015-03-1', np.nan), 
    ('Monthly','2015-04-1', 144.1), 
    ('Monthly','2015-05-1', 385.0), 
    ('Monthly','2015-06-1', 527.1), 
    ('Monthly','2015-07-1', 748.5), 
    ('Monthly','2015-08-1', 518.2)], 
    columns=['Frequency','Date','Value']) 

df['Date'] = pd.to_datetime(df['Date']) 
df.set_index(['Frequency','Date'],inplace=True) 
df 

         Value 
Frequency Date 
      2014-02-01 529.1 
      2014-03-01 67.1 
      2014-04-01 NaN 
      2014-05-01 146.8 
      2014-06-01 469.7 
      2014-07-01 82.9 
      2014-08-01 636.9 
      2014-09-01 520.9 
      2014-10-01 217.4 
      2014-11-01 776.6 
      2014-12-01 18.4 
      2015-01-01 376.7 
      2015-02-01 266.5 
      2015-03-01 NaN 
      2015-04-01 144.1 
      2015-05-01 385.0 
      2015-06-01 527.1 
      2015-07-01 748.5 
      2015-08-01 518.2 

Я попытался с помощью функции Группировщика, но GroupBy игнорирует значения NaN и утилита окуня не навязывает временные ряды полноты, насколько я могу сказать:

df.groupby(pd.Grouper(level='Date', freq='Q')).sum() 

      Value 
Date 
2014-03-31 1571.2 
2014-06-30 616.5 
2014-09-30 1240.7 
2014-12-31 1012.4 
2015-03-31 643.2 
2015-06-30 1056.2 
2015-09-30 1266.7 

То, что я хотел бы видеть заключается в следующем:

   Value 
Date 
2014-03-31  NaN # Because of missing 2014-01-01 
2014-06-30  NaN # Because of NaN in 2014-04-01 
2014-09-30 1240.7 
2014-12-31 1012.4 
2015-03-31  NaN # Because of NaN in 2015-03-01 
2015-06-30 1056.2 
2015-09-30  NaN # Because of missing 2015-09-01 

Каков хороший способ сделать это?

ответ

1

Вы можете написать свою собственную функцию aggergate, 1, если есть nan, возвращают nan; 2, если период слишком короткий, также возвратите nan; 3, в противном случае вернуть сумму:

In [43]: 

gpy = df.groupby(pd.Grouper(level='Date', freq='Q')) 

print gpy.agg(lambda x: np.nan if (np.isnan(x).any() or len(x)<3) else x.sum()) 

      Value 
Date    
2014-03-31  NaN 
2014-06-30  NaN 
2014-09-30 1240.7 
2014-12-31 1012.4 
2015-03-31  NaN 
2015-06-30 1056.2 
2015-09-30  NaN 
1

Вы можете создать булеву маску, которая Правда для каждой группы, которая имеет ровно 3 элемента:

mask = (df.groupby(pd.Grouper(level='Date', freq='Q'))['Value'].count() != 3).values 

, а затем просто установить соответствующие строки в NaN.

grouped = df.groupby(pd.Grouper(level='Date', freq='Q')) 
result = grouped.sum() 
mask = (grouped['Value'].count() != 3).values 
result.loc[mask, 'Value'] = np.nan 

дает

   Value 
Date    
2014-03-31  NaN 
2014-06-30  NaN 
2014-09-30 1240.7 
2014-12-31 1012.4 
2015-03-31  NaN 
2015-06-30 1056.2 
2015-09-30  NaN 
Смежные вопросы