Переиндексация и заполнение недостающих дат

#python #date #pandas #dataframe

#python #Дата #pandas #фрейм данных

Вопрос:

У меня есть фрейм данных, который находится в этом формате.

        country_txt  multiple  success  nkill  nwound  property      dates  
1970Q1       Italy         0        1    0.0     0.0         0 1970-01-01   
1970Q1       Italy         0        0    0.0     0.0         1 1970-01-01   
1970Q4       Italy         0        0    0.0     0.0         1 1970-04-01   
1971Q1       Italy         0        1    0.0     0.0         1 1971-01-01   
1971Q3       Italy         0        1    0.0     0.0         1 1971-03-01 
  

Индекс этого фрейма данных — это год, за которым следует квартал, который я создал с помощью PeriodIndex . dates Столбец также символизирует год и квартал, день месяца не имеет значения. Я хочу суммировать все остальные столбцы за каждый квартал. Обычно это не проблема, поскольку я могу просто сделать italy.groupby('dates').sum() . Однако результат, который я получаю, таков

             multiple  success  nkill  nwound  property  
dates                                                             
1970-01-01         0        1    0.0     0.0         1           
1970-04-01         0        0    0.0     0.0         1           
1971-01-01         0        1    0.0     0.0         1   
  

Проблема в том, что теперь я хочу заполнить недостающие значения для каждого квартала, который не отображается, чтобы результат выглядел примерно так,

                 multiple  success  nkill  nwound  property  
dates                                                             
1970-01-01         0        1    0.0     0.0         1 
1970-02-01         0        0    0.0     0.0         0
1970-03-01         0        0    0.0     0.0         0
1970-04-01         0        0    0.0     0.0         1           
1971-01-01         0        1    0.0     0.0         1 
  

Я просмотрел предыдущие вопросы и обнаружил, что люди рекомендуют мне делать это df.reindex(pd.date_range("1970-01-01", "2015-12-31"), fill_value = 0) . Проблема в том, что это даст моим данным много дополнительных строк, поскольку у меня будут данные на ежедневной основе, что тогда будет означать, что мне придется заново суммировать данные по кварталам. Итак, как бы я достиг этой цели, не создавая все эти ежедневные 0 и не находя способ снова суммировать все по кварталам?

Для справки, dates столбец был создан путем первого изменения исходного столбца месяцев на значение от 1 до 4 (для обозначения квартала), а затем преобразован в формат timedelta, выполнив это

 df['dates'] = df.iyear.astype(str).str.cat(df.imonth.astype(str))
df['dates'] = pd.to_datetime(df['dates'], format = '%Y%m')
  

Ответ №1:

ОБНОВЛЕНИЕ: анализ реальных дат из строкового индекса. Это должно работать и для более старых версий Pandas:

 In [212]: df.set_index(pd.to_datetime(df.index)).resample('QS').sum().fillna(0)
Out[212]:
            multiple  success  nkill  nwound  property
idx
1970-01-01       0.0      1.0    0.0     0.0       1.0
1970-04-01       0.0      0.0    0.0     0.0       0.0
1970-07-01       0.0      0.0    0.0     0.0       0.0
1970-10-01       0.0      0.0    0.0     0.0       1.0
1971-01-01       0.0      1.0    0.0     0.0       1.0
1971-04-01       0.0      0.0    0.0     0.0       0.0
1971-07-01       0.0      1.0    0.0     0.0       1.0
  

СТАРЫЙ ответ: (предполагая, что dates столбец содержит реальные даты). Он использует новую функцию Pandas 0.19.0: .resample(..., on='column_name') :

попробуйте это:

 In [205]: df.resample('QS', on='dates').sum().fillna(0)
Out[205]:
            multiple  success  nkill  nwound  property
dates
1970-01-01       0.0      1.0    0.0     0.0       1.0
1970-04-01       0.0      0.0    0.0     0.0       1.0
1970-07-01       0.0      0.0    0.0     0.0       0.0
1970-10-01       0.0      0.0    0.0     0.0       0.0
1971-01-01       0.0      2.0    0.0     0.0       2.0
  

или повторная выборка «ежемесячно»:

 In [207]: df.resample('QS', on='dates').sum().resample('MS').sum().fillna(0)
Out[207]:
            multiple  success  nkill  nwound  property
dates
1970-01-01       0.0      1.0    0.0     0.0       1.0
1970-02-01       0.0      0.0    0.0     0.0       0.0
1970-03-01       0.0      0.0    0.0     0.0       0.0
1970-04-01       0.0      0.0    0.0     0.0       1.0
1970-05-01       0.0      0.0    0.0     0.0       0.0
1970-06-01       0.0      0.0    0.0     0.0       0.0
1970-07-01       0.0      0.0    0.0     0.0       0.0
1970-08-01       0.0      0.0    0.0     0.0       0.0
1970-09-01       0.0      0.0    0.0     0.0       0.0
1970-10-01       0.0      0.0    0.0     0.0       0.0
1970-11-01       0.0      0.0    0.0     0.0       0.0
1970-12-01       0.0      0.0    0.0     0.0       0.0
1971-01-01       0.0      2.0    0.0     0.0       2.0
  

Комментарии:

1. Я получаю эту ошибку TypeError: resample() got an unexpected keyword argument 'on' . И просто для ясности, я выполняю эту команду для фрейма данных, для которого я уже использовал groupby функцию, это правильно?

2. Я использую новую версию Pandas: 0.19.0. resample(on='col_name') — это новая функция Pandas 0.19.0

3. Новых функций 1.. что ж, 1 за хороший ответ и ура! новые возможности.

4. Я смог использовать ваше решение, изменив on на axis = 0 . Спасибо за вашу помощь!

5. Я полагаю, что из-за проблем с совместимостью другой библиотеки, которую я использую, которая находится на стадии разработки, моя версия Pandas должна оставаться старой из-за проблем со стабильностью.