Pandas 将自定义日期(月年)循环到(月年+N)以进行绘图

Posted

技术标签:

【中文标题】Pandas 将自定义日期(月年)循环到(月年+N)以进行绘图【英文标题】:Pandas loop over custom dates (month year) to (month year+N) for plotting 【发布时间】:2017-05-06 15:04:49 【问题描述】:

我一直在分析运行了几个月的数据,然后每月生成并保存一个数字。到目前为止,当这些都在同一日历年内时,这非常有效,但我不知道当数据跨越到下一年时如何指示循环工作。

示例代码:

import pandas as pd
import datetime as datetime
import matplotlib as plt

df = pd.read_csv("file.csv")
df.index = df.Datetime

for month in range(4,12): #Data starts in April in this example
    fig, axes = plt.subplots(nrows=2,ncols=1, sharex=True, figsize =(18,10))
    startDate = datetime.date(2016,month,1)
    stopDate = datetime.date(2016,month+1,1)
    date_val = startDate.strftime("%B %Y")

    k=0
    df.PRe[startDate:stopDate].plot(ax=axes[k])
    #ylim, xlim, title etc
    k=1
    df.PRp[startDate:stopDate].plot(ax=axes[k])

    plt.savefig("PRe and PRp in %s.png"%date_val,bbox_inches="tight")

This SO question 接近了,尽管他们使用 pandas datetime 对象而不是我使用的 datetime.date 对象。我是否应该修改我的代码以适应解决方案,如果是,如何? 否则,一旦我们超过 2016 年,是否有一种 pandas/pythonic 的方法可以让它工作 - 无论是对于已知的开始和结束日期,还是更好,对于任何开始和结束日期?

【问题讨论】:

【参考方案1】:

你可以使用dateoffset:

month = 4
startDate = datetime.date(2016,month,1)
print (startDate)
stopDate = (startDate + pd.offsets.MonthBegin()).date()
print (stopDate)
2016-04-01
2016-05-01

month = 4
startDate = datetime.date(2016,month,1)
print (startDate)
stopDate = (startDate + pd.offsets.DateOffset(months=1)).date()
print (stopDate)
2016-04-01
2016-05-01

另一个解决方案是datetimeindex partial string indexing,如果需要选择yearmonth

df.PRe['2016-4'].plot(ax=axes[k])

df.PRe[str(2016)+'-'+str(month)].plot(ax=axes[k])

如果需要在datetimeindex 中循环的解决方案按唯一的年份和月份按唯一的month 周期按DatetimeIndex.to_period

start = pd.to_datetime('2015-10-24')
rng = pd.date_range(start, periods=10, freq='3W')

df = pd.DataFrame('PRe': np.random.randint(10, size=10), index=rng)  
print (df)
            PRe
2015-10-25    2
2015-11-15    3
2015-12-06    3
2015-12-27    1
2016-01-17    8
2016-02-07    4
2016-02-28    2
2016-03-20    6
2016-04-10    8
2016-05-01    0
2015-10-25    2
for date in df.index.to_period('m').unique():
    print (df.PRe[str(date)])

Freq: 3W-SUN, Name: PRe, dtype: int32
2015-11-15    3
Freq: 3W-SUN, Name: PRe, dtype: int32
2015-12-06    3
2015-12-27    1
Freq: 3W-SUN, Name: PRe, dtype: int32
2016-01-17    8
Freq: 3W-SUN, Name: PRe, dtype: int32
2016-02-07    4
2016-02-28    2
Freq: 3W-SUN, Name: PRe, dtype: int32
2016-03-20    6
Freq: 3W-SUN, Name: PRe, dtype: int32
2016-04-10    8
Freq: 3W-SUN, Name: PRe, dtype: int32
2016-05-01    0
Freq: 3W-SUN, Name: PRe, dtype: int32

【讨论】:

请问DatetimeIndex.to_period(DatetimeIndex.to_pydatetime) 函数是否适用于my question?谢谢【参考方案2】:

@jezrael 的回答解决了这个问题;以下是后代的解决方案。

import pandas as pd
import matplotlib as plt

df = pd.read_csv("file.csv")
df.index = df.Datetime

startDate = df.index[0] #seed the while loop, format Timestamp
while (startDate >= df.index[0]) & (startDate < df.index[-1]): 
    fig, axes = plt.subplots(nrows=2,ncols=1, sharex=True, figsize =(18,10))

    stopDate = (startDate + pd.offsets.MonthBegin())#stopDate also Timestamp
    date_val = startDate.strftime("%B %Y")#Date as Month Year string

    k=0
    df.PRe[startDate:stopDate].plot(ax=axes[k])
    #ylim, xlim, title etc
    k=1
    df.PRp[startDate:stopDate].plot(ax=axes[k])
    #ylim, xlim, title etc
    plt.savefig("PRe and PRp in %s.png"%date_val,bbox_inches="tight")
    startDate = stopDate

【讨论】:

以上是关于Pandas 将自定义日期(月年)循环到(月年+N)以进行绘图的主要内容,如果未能解决你的问题,请参考以下文章

创建批处理文件以将日志分类到各自的月年文件夹中......?

SQL周日月年数据统计

计算两个时间之间相差几天月年

Sql获取周月年的首尾时间。

记录js 获取周月年的开始及结束时间

获取选择的当前天周月年的时间段