2013-11-20 2 views
3

У меня есть кадр данных панд следующим образом:Суммы дней с интервалом

ID  Start  End 
1 2013-03-03 2013-04-05 
2 2013-03-03 2013-04-05 
3 2012-03-02 2012-05-05 
4 2013-03-01 2013-04-04 
5 2013-02-25 2013-06-05 
6 2012-02-26 2012-05-05 
7 2013-02-25 2013-04-27 
8 2012-02-26 2012-03-01 
9 2013-03-22 2013-03-25 
10 2013-06-27 2013-07-01 

Есть ли способ, чтобы агрегировать количество дней, которые произошли за месяц: год для каждого интервала для каждого идентификатора.

Выход, который я пытаюсь получить, - это сумма всех дней в месяц: Год, в который каждый идентификатор вносит свой вклад.

Таким образом, ID1 будет преодолевать 29 дней до марта 2013 года и 5 дней до апреля 2013 года; ID3 будет вносить 30 дней до марта 2012 года, от 30 дней до апреля 2012 года и от 5 дней до мая 2012 года. И т.д. ....

Заранее спасибо, если вы можете помочь.

+1

На этот вопрос уже поставлен предыдущий вопрос панд, посмотрим, смогу ли я его выкопать. Ах, да, этот: http://stackoverflow.com/q/18775052/1240268 –

ответ

4

Вот ужасный способ сделать это:

In [11]: df1.apply(lambda x: pd.Series(1, pd.date_range(x.loc['Start'], x.loc['End'] - pd.offsets.Day(1), freq='D')).resample('M', how='sum'), axis=1).fillna(0) 
Out[11]: 
    2012-02-29 2012-03-31 2012-04-30 2012-05-31 2013-02-28 2013-03-31 2013-04-30 2013-05-31 2013-06-30 
ID                            
1   0   0   0   0   0   29   4   0   0 
2   0   0   0   0   0   29   4   0   0 
3   0   30   30   4   0   0   0   0   0 
4   0   0   0   0   0   31   3   0   0 
5   0   0   0   0   4   31   30   31   4 
6   4   31   30   4   0   0   0   0   0 
7   0   0   0   0   4   31   26   0   0 
8   4   0   0   0   0   0   0   0   0 
9   0   0   0   0   0   3   0   0   0 
10   0   0   0   0   0   0   0   0   4 

Чтобы разорвать его, для каждой строки мы вычисляем дни в каждом месяце, создавая Серию из 1 с на каждый день между началом и концом, затем суммируя их на каждый месяц с использованием пересчета:

In [12]: x = df1.iloc[0] 

In [13]: x 
Out[13]: 
Start 2013-03-03 00:00:00 
End  2013-04-05 00:00:00 
Name: 1, dtype: datetime64[ns] 


In [14]: pd.Series(1, pd.date_range(x['Start'], x['End'] - pd.offsets.Day(1), freq='D')).resample('M', how='sum') 
Out[14]: 
2013-03-31 29 
2013-04-30  4 
Freq: M, dtype: int64 
+1

Я не думаю, что этот ужас. Другой способ - рассчитать все концы месяцев между двумя датами, разделить период на несколько периодов, а затем рассчитать разницу между этими датами, в любом случае здесь мой +1 –

+0

@ andy-hayden - думаю, это в значительной степени то, что я был после. Формат выглядит подходящим для данных, которые я должен сообщить. – John

2

Модуль datetime имеет инструменты, необходимые для ежемесячного манипулирования датами.

Вот некоторые быстрый автономный код, который может быть легко адаптирована к панды dataframe:

import datetime 
import collections 
import pprint 

data = '''\ 
1 2013-03-03 2013-04-05 
2 2013-03-03 2013-04-05 
3 2012-03-02 2012-05-05 
4 2013-03-01 2013-04-04 
5 2013-02-25 2013-06-05 
6 2012-02-26 2012-05-05 
7 2013-02-25 2013-04-27 
8 2012-02-26 2012-03-01 
9 2013-03-22 2013-03-25 
10 2013-06-27 2013-07-01 
''' 

for line in data.splitlines(): 
    idnum, startstr, endstr = line.split() 
    start = datetime.datetime.strptime(startstr, '%Y-%m-%d') 
    end = datetime.datetime.strptime(endstr, '%Y-%m-%d') 

    days_in_month = collections.Counter() 
    current = start 
    while current <= end: 
     days_in_month[current.year, current.month] += 1 
     current += datetime.timedelta(1) 
    print('Id: %s' % idnum) 
    pprint.pprint(dict(days_in_month)) 
    print('-' * 10) 
Смежные вопросы