2013-10-15 2 views
1

У меня есть набор данных. Я анализирую в пандах, где все данные бинают ежемесячно. Данные берутся из базы данных MySQL, где все даты находятся в формате «YYYY-MM-01», так что, например, все строки в октябре 2013 года будут иметь «2013-10-01» в столбце месяца.Обработка ежемесячных данных в pandas

Я в настоящее время чтения данных в панд (через .tsv дамп таблицы MySQL) с

data = pd.read_table(filename,header=None,names=('uid','iid','artist','tag','date'),index_col=indexes, parse_dates='date') 

Это все хорошо, за исключением того, что любые последующие анализы я бегу, в котором, кроме меня ежемесячная передискретизация всегда представляет даты с использованием соглашения конца месяца (т.е. данные с октября становятся «2013-10-31» вместо «2013-10-01»), но это может привести к несогласованности, когда исходные данные имеют месяцы помечены как «YYYY-MM-01», в то время как любые данные с повторной выборкой будут иметь месяцы, обозначенные как «YYYY-MM-31» (или «-30» или «-28», если это необходимо).

Мой вопрос это: Самый простой и/или самый быстрый способ Я могу преобразовать все даты в моем фрейме данных в формат конца месяца с самого начала? Имейте в виду, что дата является одним из нескольких индексов в мультииндексе, а не в столбце. Я считаю, что лучше всего использовать модифицированный date_parser в моем вызове pd.read_table, который всегда конвертирует месяц в соглашение конца месяца, но я не уверен, как подойти к нему.

ответ

1

use replace(), чтобы изменить значение дня. и вы можете получить в последний день месяца, используя

from datetime import date 
import calendar 

d = date(2000,1,1) 
d = d.replace(day=calendar.monthrange(d.year, d.month)[1]) 

UPDATE

добавить некоторый пример для панд.

образец файла date.csv

2013-01-01, 1 
2013-02-01, 2 

IPython журнал оболочки.

In [27]: import pandas as pd 

In [28]: from datetime import datetime, date 

In [29]: import calendar 

In [30]: def parse(dt): 
      dt = datetime.strptime(dt, '%Y-%m-%d') 
      dt = dt.replace(day=calendar.monthrange(dt.year, dt.month)[1]) 
      return dt.date() 
      ....: 

In [31]: parse('2013-01-01') 
Out[31]: datetime.date(2013, 1, 31) 

In [32]: r = pd.read_csv('date.csv', header=None, names=('date', 'value'), parse_dates=['date'], date_parser=parse) 

In [33]: r 
Out[33]: 
     date value 
0 2013-01-31  1 
1 2013-02-28  2 
+0

Возможно, это полезно, но эта лань sn't сказать, как применить преобразование к индексу даты ... – moustachio

+0

@moustachio использовать пользовательский date_parser. – Curry

+0

Отлично! Спасибо за расширение объяснения, это прекрасно работает. Мой комментарий был в вашей первой версии ответа. – moustachio

3

Проверьте, пожалуйста, даты, чтобы полноценно.

Создайте тестовые данные. Я устанавливаю даты в начале месяца, но это не имеет значения.

In [39]: df = DataFrame(np.random.randn(10,2),columns=list('AB'), 
         index=date_range('20130101',periods=10,freq='MS')) 

In [40]: df 
Out[40]: 
        A   B 
2013-01-01 -0.553482 0.049128 
2013-02-01 0.337975 -0.035897 
2013-03-01 -0.394849 -1.755323 
2013-04-01 -0.555638 1.903388 
2013-05-01 -0.087752 1.551916 
2013-06-01 1.000943 -0.361248 
2013-07-01 -1.855171 -2.215276 
2013-08-01 -0.582643 1.661696 
2013-09-01 0.501061 -1.455171 
2013-10-01 1.343630 -2.008060 

Force преобразовать их в истекшим месяцем, в пространстве времени независимо от дня

In [41]: df.index = df.index.to_period().to_timestamp('M') 

In [42]: df 
Out[42]: 
        A   B 
2013-01-31 -0.553482 0.049128 
2013-02-28 0.337975 -0.035897 
2013-03-31 -0.394849 -1.755323 
2013-04-30 -0.555638 1.903388 
2013-05-31 -0.087752 1.551916 
2013-06-30 1.000943 -0.361248 
2013-07-31 -1.855171 -2.215276 
2013-08-31 -0.582643 1.661696 
2013-09-30 0.501061 -1.455171 
2013-10-31 1.343630 -2.008060 

Вернуться к началу

In [43]: df.index = df.index.to_period().to_timestamp('MS') 

In [44]: df 
Out[44]: 
        A   B 
2013-01-01 -0.553482 0.049128 
2013-02-01 0.337975 -0.035897 
2013-03-01 -0.394849 -1.755323 
2013-04-01 -0.555638 1.903388 
2013-05-01 -0.087752 1.551916 
2013-06-01 1.000943 -0.361248 
2013-07-01 -1.855171 -2.215276 
2013-08-01 -0.582643 1.661696 
2013-09-01 0.501061 -1.455171 
2013-10-01 1.343630 -2.008060 

Вы также можете работать с (и частоты дискретизации) как периоды

In [45]: df.index = df.index.to_period() 

In [46]: df 
Out[46]: 
       A   B 
2013-01 -0.553482 0.049128 
2013-02 0.337975 -0.035897 
2013-03 -0.394849 -1.755323 
2013-04 -0.555638 1.903388 
2013-05 -0.087752 1.551916 
2013-06 1.000943 -0.361248 
2013-07 -1.855171 -2.215276 
2013-08 -0.582643 1.661696 
2013-09 0.501061 -1.455171 
2013-10 1.343630 -2.008060 
+0

Это freq = 'MS' - именно то, что я искал! Если я использую это для переиндексации/наполнения, мне не нужно связываться с пользовательским параметром date_parser. – moustachio

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