Pandas 时间序列 - 纵览与时间戳

作者: 呆鸟的简书 | 来源:发表于2019-12-09 14:19 被阅读0次

    [TOC]

    依托 NumPy 的 datetime64timedelta64 等数据类型,pandas 可以处理各种时间序列数据,还能调用 scikits.timeseries 等 Python 支持库的时间序列功能。

    Pandas 支持以下操作:

    解析时间格式字符串np.datetime64datetime.datetime 等多种时间序列数据。

    In [1]: import datetime
    
    In [2]: dti = pd.to_datetime(['1/1/2018', np.datetime64('2018-01-01'),
       ...:                       datetime.datetime(2018, 1, 1)])
       ...: 
    
    In [3]: dti
    Out[3]: DatetimeIndex(['2018-01-01', '2018-01-01', '2018-01-01'], dtype='datetime64[ns]', freq=None)
    

    生成 DatetimeIndexTimedeltaIndexPeriodIndex 等定频日期与时间段序列。

    In [4]: dti = pd.date_range('2018-01-01', periods=3, freq='H')
    
    In [5]: dti
    Out[5]: 
    DatetimeIndex(['2018-01-01 00:00:00', '2018-01-01 01:00:00',
                   '2018-01-01 02:00:00'],
                  dtype='datetime64[ns]', freq='H')
    

    处理、转换带时区的日期时间数据。

    In [6]: dti = dti.tz_localize('UTC')
    
    In [7]: dti
    Out[7]: 
    DatetimeIndex(['2018-01-01 00:00:00+00:00', '2018-01-01 01:00:00+00:00',
                   '2018-01-01 02:00:00+00:00'],
                  dtype='datetime64[ns, UTC]', freq='H')
    
    In [8]: dti.tz_convert('US/Pacific')
    Out[8]: 
    DatetimeIndex(['2017-12-31 16:00:00-08:00', '2017-12-31 17:00:00-08:00',
                   '2017-12-31 18:00:00-08:00'],
                  dtype='datetime64[ns, US/Pacific]', freq='H')
    

    按指定频率重采样,并转换为时间序列。

    In [9]: idx = pd.date_range('2018-01-01', periods=5, freq='H')
    
    In [10]: ts = pd.Series(range(len(idx)), index=idx)
    
    In [11]: ts
    Out[11]: 
    2018-01-01 00:00:00    0
    2018-01-01 01:00:00    1
    2018-01-01 02:00:00    2
    2018-01-01 03:00:00    3
    2018-01-01 04:00:00    4
    Freq: H, dtype: int64
    
    In [12]: ts.resample('2H').mean()
    Out[12]: 
    2018-01-01 00:00:00    0.5
    2018-01-01 02:00:00    2.5
    2018-01-01 04:00:00    4.0
    Freq: 2H, dtype: float64
    

    用绝对或相对时间差计算日期与时间。

    In [13]: friday = pd.Timestamp('2018-01-05')
    
    In [14]: friday.day_name()
    Out[14]: 'Friday'
    
    # 添加 1 个日历日
    In [15]: saturday = friday + pd.Timedelta('1 day')
    
    In [16]: saturday.day_name()
    Out[16]: 'Saturday'
    
    # 添加 1 个工作日,从星期五跳到星期一
    In [17]: monday = friday + pd.offsets.BDay()
    
    In [18]: monday.day_name()
    Out[18]: 'Monday'
    

    Pandas 提供了一组精悍、实用的工具集以完成上述操作。

    时间序列纵览

    Pandas 支持 4 种常见时间概念:

    1. 日期时间(Datetime):带时区的日期时间,类似于标准库的 datetime.datetime

    2. 时间差(Timedelta):绝对时间周期,类似于标准库的 datetime.timedelta

    3. 时间段(Timespan):在某一时点以指定频率定义的时间跨度。

    4. 日期偏移(Dateoffset):与日历运算对应的时间段,类似于 dateutildateutil.relativedelta.relativedelta

    时间概念 标量类 数组类 Pandas 数据类型 主要构建方法
    Date times Timestamp DatetimeIndex datetime64[ns]datetime64[ns,tz] to_datetimedate_range
    Time deltas Timedelta TimedeltaIndex timedelta64[ns] to_timedeltatimedelta_range
    Time spans Period PeriodIndex period[freq] Periodperiod_range
    Date offsets DateOffset None None DateOffset

    一般情况下,时间序列主要是 SeriesDataFrame 的时间型索引,可以用时间元素进行操控。

    In [19]: pd.Series(range(3), index=pd.date_range('2000', freq='D', periods=3))
    Out[19]: 
    2000-01-01    0
    2000-01-02    1
    2000-01-03    2
    Freq: D, dtype: int64
    

    当然,SeriesDataFrame 也可以直接把时间序列当成数据。

    In [20]: pd.Series(pd.date_range('2000', freq='D', periods=3))
    Out[20]: 
    0   2000-01-01
    1   2000-01-02
    2   2000-01-03
    dtype: datetime64[ns]
    

    SeriesDataFrame 提供了 datetimetimedeltaPeriod 扩展类型与专有用法,不过,Dateoffset 则保存为 object

    In [21]: pd.Series(pd.period_range('1/1/2011', freq='M', periods=3))
    Out[21]: 
    0    2011-01
    1    2011-02
    2    2011-03
    dtype: period[M]
    
    In [22]: pd.Series([pd.DateOffset(1), pd.DateOffset(2)])
    Out[22]: 
    0         <DateOffset>
    1    <2 * DateOffsets>
    dtype: object
    
    In [23]: pd.Series(pd.date_range('1/1/2011', freq='M', periods=3))
    Out[23]: 
    0   2011-01-31
    1   2011-02-28
    2   2011-03-31
    dtype: datetime64[ns]
    

    Pandas 用 NaT 表示日期时间、时间差及时间段的空值,代表了缺失日期或空日期的值,类似于浮点数的 np.nan

    In [24]: pd.Timestamp(pd.NaT)
    Out[24]: NaT
    
    In [25]: pd.Timedelta(pd.NaT)
    Out[25]: NaT
    
    In [26]: pd.Period(pd.NaT)
    Out[26]: NaT
    
    # 与 np.nan 一样,pd.NaT 不等于 pd.NaT 
    In [27]: pd.NaT == pd.NaT
    Out[27]: False
    

    时间戳 vs. 时间段

    时间戳是最基本的时间序列数据,用于把数值与时点关联在一起。Pandas 对象通过时间戳调用时点数据。

    In [28]: pd.Timestamp(datetime.datetime(2012, 5, 1))
    Out[28]: Timestamp('2012-05-01 00:00:00')
    
    In [29]: pd.Timestamp('2012-05-01')
    Out[29]: Timestamp('2012-05-01 00:00:00')
    
    In [30]: pd.Timestamp(2012, 5, 1)
    Out[30]: Timestamp('2012-05-01 00:00:00')
    

    不过,大多数情况下,用时间段改变变量更自然。Period 表示的时间段更直观,还可以用日期时间格式的字符串进行推断。

    示例如下:

    In [31]: pd.Period('2011-01')
    Out[31]: Period('2011-01', 'M')
    
    In [32]: pd.Period('2012-05', freq='D')
    Out[32]: Period('2012-05-01', 'D')
    

    TimestampPeriod 可以用作索引。作为索引的 TimestampPeriod 列表则被强制转换为对应的 DatetimeIndexPeriodIndex

    In [33]: dates = [pd.Timestamp('2012-05-01'),
       ....:          pd.Timestamp('2012-05-02'),
       ....:          pd.Timestamp('2012-05-03')]
       ....: 
    
    In [34]: ts = pd.Series(np.random.randn(3), dates)
    
    In [35]: type(ts.index)
    Out[35]: pandas.core.indexes.datetimes.DatetimeIndex
    
    In [36]: ts.index
    Out[36]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
    
    In [37]: ts
    Out[37]: 
    2012-05-01    0.469112
    2012-05-02   -0.282863
    2012-05-03   -1.509059
    dtype: float64
    
    In [38]: periods = [pd.Period('2012-01'), pd.Period('2012-02'), pd.Period('2012-03')]
    
    In [39]: ts = pd.Series(np.random.randn(3), periods)
    
    In [40]: type(ts.index)
    Out[40]: pandas.core.indexes.period.PeriodIndex
    
    In [41]: ts.index
    Out[41]: PeriodIndex(['2012-01', '2012-02', '2012-03'], dtype='period[M]', freq='M')
    
    In [42]: ts
    Out[42]: 
    2012-01   -1.135632
    2012-02    1.212112
    2012-03   -0.173215
    Freq: M, dtype: float64
    

    Pandas 可以识别这两种表现形式,并在两者之间进行转化。Pandas 后台用 Timestamp 实例代表时间戳,用 DatetimeIndex 实例代表时间戳序列。pandas 用 Period 对象表示符合规律的时间段标量值,用 PeriodIndex 表示时间段序列。未来版本将支持用任意起止时间实现不规律时间间隔。

    转换时间戳

    to_datetime 函数用于转换字符串、纪元式及混合的日期 Series 或日期列表。转换的是 Series 时,返回的是具有相同的索引的 Series,日期时间列表则会被转换为 DatetimeIndex

    In [43]: pd.to_datetime(pd.Series(['Jul 31, 2009', '2010-01-10', None]))
    Out[43]: 
    0   2009-07-31
    1   2010-01-10
    2          NaT
    dtype: datetime64[ns]
    
    In [44]: pd.to_datetime(['2005/11/23', '2010.12.31'])
    Out[44]: DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)
    

    解析欧式日期(日-月-年),要用 dayfirst 关键字参数:

    In [45]: pd.to_datetime(['04-01-2012 10:00'], dayfirst=True)
    Out[45]: DatetimeIndex(['2012-01-04 10:00:00'], dtype='datetime64[ns]', freq=None)
    
    In [46]: pd.to_datetime(['14-01-2012', '01-14-2012'], dayfirst=True)
    Out[46]: DatetimeIndex(['2012-01-14', '2012-01-14'], dtype='datetime64[ns]', freq=None)
    

    警告:从上例可以看出,dayfirst 并没有那么严苛,如果不能把第一个数解析为,就会以 dayfirstFalse 进行解析。

    to_datetime 转换单个字符串时,返回的是单个 TimestampTimestamp 仅支持字符串输入,不支持 dayfirstformat 等字符串解析选项,如果要使用这些选项,就要用 to_datetime

    In [47]: pd.to_datetime('2010/11/12')
    Out[47]: Timestamp('2010-11-12 00:00:00')
    
    In [48]: pd.Timestamp('2010/11/12')
    Out[48]: Timestamp('2010-11-12 00:00:00')
    

    Pandas 还支持直接使用 DatetimeIndex 构建器:

    In [49]: pd.DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'])
    Out[49]: DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'], dtype='datetime64[ns]', freq=None)
    

    创建 DatetimeIndex 时,传递字符串 infer 即可推断索引的频率。

    In [50]: pd.DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'], freq='infer')
    Out[50]: DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'], dtype='datetime64[ns]', freq='2D')
    

    提供格式参数

    要实现精准转换,除了传递 datetime 字符串,还要指定 format 参数,指定此参数还可以加速转换速度。

    In [51]: pd.to_datetime('2010/11/12', format='%Y/%m/%d')
    Out[51]: Timestamp('2010-11-12 00:00:00')
    
    In [52]: pd.to_datetime('12-11-2010 00:00', format='%d-%m-%Y %H:%M')
    Out[52]: Timestamp('2010-11-12 00:00:00')
    

    要了解更多 format 选项,请参阅 Python 日期时间文档

    用多列组合日期时间

    0.18.1 版新增。

    Pandas 还可以把 DataFrame 里的整数或字符串列组合成 Timestamp Series

    In [53]: df = pd.DataFrame({'year': [2015, 2016],
       ....:                    'month': [2, 3],
       ....:                    'day': [4, 5],
       ....:                    'hour': [2, 3]})
       ....: 
    
    In [54]: pd.to_datetime(df)
    Out[54]: 
    0   2015-02-04 02:00:00
    1   2016-03-05 03:00:00
    dtype: datetime64[ns]
    

    只传递组合所需的列也可以。

    In [55]: pd.to_datetime(df[['year', 'month', 'day']])
    Out[55]: 
    0   2015-02-04
    1   2016-03-05
    dtype: datetime64[ns]
    

    pd.to_datetime 查找列名里日期时间组件的标准名称,包括:

    • 必填:yearmonthday
    • 可选:hourminutesecondmillisecondmicrosecondnanosecond

    无效数据

    不可解析时,默认值 errors='raise' 会触发错误:

    In [2]: pd.to_datetime(['2009/07/31', 'asd'], errors='raise')
    ValueError: Unknown string format
    

    errors='ignore' 返回原始输入:

    In [56]: pd.to_datetime(['2009/07/31', 'asd'], errors='ignore')
    Out[56]: Index(['2009/07/31', 'asd'], dtype='object')
    

    errors='coerce' 把无法解析的数据转换为 NaT,即不是时间(Not a Time):

    In [57]: pd.to_datetime(['2009/07/31', 'asd'], errors='coerce')
    Out[57]: DatetimeIndex(['2009-07-31', 'NaT'], dtype='datetime64[ns]', freq=None)
    

    纪元时间戳

    Pandas 支持把整数或浮点数纪元时间转换为 TimestampDatetimeIndex。鉴于 Timestamp 对象内部存储方式,这种转换的默认单位是纳秒。不过,一般都会用指定其它时间单位 unit 来存储纪元数据,纪元时间从 origin 参数指定的时点开始计算。

    In [58]: pd.to_datetime([1349720105, 1349806505, 1349892905,
       ....:                 1349979305, 1350065705], unit='s')
       ....: 
    Out[58]: 
    DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
                   '2012-10-10 18:15:05', '2012-10-11 18:15:05',
                   '2012-10-12 18:15:05'],
                  dtype='datetime64[ns]', freq=None)
    
    In [59]: pd.to_datetime([1349720105100, 1349720105200, 1349720105300,
       ....:                 1349720105400, 1349720105500], unit='ms')
       ....: 
    Out[59]: 
    DatetimeIndex(['2012-10-08 18:15:05.100000', '2012-10-08 18:15:05.200000',
                   '2012-10-08 18:15:05.300000', '2012-10-08 18:15:05.400000',
                   '2012-10-08 18:15:05.500000'],
                  dtype='datetime64[ns]', freq=None)
    

    用带 tz 参数的纪元时间戳创建 TimestampDatetimeIndex 时,要先把纪元时间戳转化为 UTC,然后再把结果转换为指定时区。不过这种操作方式现在已经废弃了,对于其它时区 Wall Time 里的纪元时间戳,建议先把纪元时间戳转换为无时区时间戳,然后再把时区本地化。

    In [60]: pd.Timestamp(1262347200000000000).tz_localize('US/Pacific')
    Out[60]: Timestamp('2010-01-01 12:00:00-0800', tz='US/Pacific')
    
    In [61]: pd.DatetimeIndex([1262347200000000000]).tz_localize('US/Pacific')
    Out[61]: DatetimeIndex(['2010-01-01 12:00:00-08:00'], dtype='datetime64[ns, US/Pacific]', freq=None)
    

    注意:纪元时间取整到最近的纳秒。

    警告:
    Python 浮点数只精确到 15 位小数,因此,转换浮点纪元时间可能会导致不精准或失控的结果。转换过程中,免不了会对高精度 Timestamp 取整,只有用 int64 等定宽类型才有可能实现极其精准的效果。

    In [62]: pd.to_datetime([1490195805.433, 1490195805.433502912], unit='s')
    Out[62]: DatetimeIndex(['2017-03-22 15:16:45.433000088', '2017-03-22 >15:16:45.433502913'], dtype='datetime64[ns]', freq=None)
    
    In [63]: pd.to_datetime(1490195805433502912, unit='ns')
    Out[63]: Timestamp('2017-03-22 15:16:45.433502912')
    

    参阅:应用 origin 参数

    把时间戳转换为纪元

    反转上述操作,把 Timestamp 转换为 unix 纪元:

    In [64]: stamps = pd.date_range('2012-10-08 18:15:05', periods=4, freq='D')
    
    In [65]: stamps
    Out[65]: 
    DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
                   '2012-10-10 18:15:05', '2012-10-11 18:15:05'],
                  dtype='datetime64[ns]', freq='D')
    

    首先与纪元开始时点(1970 年 1 月 1 日午夜,UTC)相减,然后以 1 秒为时间单位(unit='1s')取底整除。

    In [66]: (stamps - pd.Timestamp("1970-01-01")) // pd.Timedelta('1s')
    Out[66]: Int64Index([1349720105, 1349806505, 1349892905, 1349979305], dtype='int64')
    

    应用 origin 参数

    0.20.0 版新增。

    origin 参数可以指定 DatetimeIndex 的备选开始时点。例如,把1960-01-01 作为开始日期:

    In [67]: pd.to_datetime([1, 2, 3], unit='D', origin=pd.Timestamp('1960-01-01'))
    Out[67]: DatetimeIndex(['1960-01-02', '1960-01-03', '1960-01-04'], dtype='datetime64[ns]', freq=None)
    

    默认值为 origin='unix',即 1970-01-01 00:00:00,一般把这个时点称为 unix 纪元POSIX 时间。

    In [68]: pd.to_datetime([1, 2, 3], unit='D')
    Out[68]: DatetimeIndex(['1970-01-02', '1970-01-03', '1970-01-04'], dtype='datetime64[ns]', freq=None)
    

    生成时间戳范围

    DatetimeIndexIndex 构建器可以生成时间戳索引,此处要提供 datetime 对象列表。

    In [69]: dates = [datetime.datetime(2012, 5, 1),
       ....:          datetime.datetime(2012, 5, 2),
       ....:          datetime.datetime(2012, 5, 3)]
       ....: 
    
    # 注意频率信息
    In [70]: index = pd.DatetimeIndex(dates)
    
    In [71]: index
    Out[71]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
    
    # 自动转换为 DatetimeIndex
    In [72]: index = pd.Index(dates)
    
    In [73]: index
    Out[73]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
    

    实际工作中,经常要生成含大量时间戳的超长索引,一个个输入时间戳又枯燥,又低效。如果时间戳是定频的,用 date_range()bdate_range() 函数即可创建 DatetimeIndexdate_range 默认的频率是日历日bdate_range 的默认频率是工作日

    In [74]: start = datetime.datetime(2011, 1, 1)
    
    In [75]: end = datetime.datetime(2012, 1, 1)
    
    In [76]: index = pd.date_range(start, end)
    
    In [77]: index
    Out[77]: 
    DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04',
                   '2011-01-05', '2011-01-06', '2011-01-07', '2011-01-08',
                   '2011-01-09', '2011-01-10',
                   ...
                   '2011-12-23', '2011-12-24', '2011-12-25', '2011-12-26',
                   '2011-12-27', '2011-12-28', '2011-12-29', '2011-12-30',
                   '2011-12-31', '2012-01-01'],
                  dtype='datetime64[ns]', length=366, freq='D')
    
    In [78]: index = pd.bdate_range(start, end)
    
    In [79]: index
    Out[79]: 
    DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
                   '2011-01-07', '2011-01-10', '2011-01-11', '2011-01-12',
                   '2011-01-13', '2011-01-14',
                   ...
                   '2011-12-19', '2011-12-20', '2011-12-21', '2011-12-22',
                   '2011-12-23', '2011-12-26', '2011-12-27', '2011-12-28',
                   '2011-12-29', '2011-12-30'],
                  dtype='datetime64[ns]', length=260, freq='B')
    

    date_rangebdate_range 等便捷函数可以调用各种频率别名

    In [80]: pd.date_range(start, periods=1000, freq='M')
    Out[80]: 
    DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-30',
                   '2011-05-31', '2011-06-30', '2011-07-31', '2011-08-31',
                   '2011-09-30', '2011-10-31',
                   ...
                   '2093-07-31', '2093-08-31', '2093-09-30', '2093-10-31',
                   '2093-11-30', '2093-12-31', '2094-01-31', '2094-02-28',
                   '2094-03-31', '2094-04-30'],
                  dtype='datetime64[ns]', length=1000, freq='M')
    
    In [81]: pd.bdate_range(start, periods=250, freq='BQS')
    Out[81]: 
    DatetimeIndex(['2011-01-03', '2011-04-01', '2011-07-01', '2011-10-03',
                   '2012-01-02', '2012-04-02', '2012-07-02', '2012-10-01',
                   '2013-01-01', '2013-04-01',
                   ...
                   '2071-01-01', '2071-04-01', '2071-07-01', '2071-10-01',
                   '2072-01-01', '2072-04-01', '2072-07-01', '2072-10-03',
                   '2073-01-02', '2073-04-03'],
                  dtype='datetime64[ns]', length=250, freq='BQS-JAN')
    

    date_rangebdate_range 通过指定 startendperiodfreq 等参数,简化了生成日期范围这项工作。开始与结束日期是必填项,因此,不会生成指定范围之外的日期。

    In [82]: pd.date_range(start, end, freq='BM')
    Out[82]: 
    DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-29',
                   '2011-05-31', '2011-06-30', '2011-07-29', '2011-08-31',
                   '2011-09-30', '2011-10-31', '2011-11-30', '2011-12-30'],
                  dtype='datetime64[ns]', freq='BM')
    
    In [83]: pd.date_range(start, end, freq='W')
    Out[83]: 
    DatetimeIndex(['2011-01-02', '2011-01-09', '2011-01-16', '2011-01-23',
                   '2011-01-30', '2011-02-06', '2011-02-13', '2011-02-20',
                   '2011-02-27', '2011-03-06', '2011-03-13', '2011-03-20',
                   '2011-03-27', '2011-04-03', '2011-04-10', '2011-04-17',
                   '2011-04-24', '2011-05-01', '2011-05-08', '2011-05-15',
                   '2011-05-22', '2011-05-29', '2011-06-05', '2011-06-12',
                   '2011-06-19', '2011-06-26', '2011-07-03', '2011-07-10',
                   '2011-07-17', '2011-07-24', '2011-07-31', '2011-08-07',
                   '2011-08-14', '2011-08-21', '2011-08-28', '2011-09-04',
                   '2011-09-11', '2011-09-18', '2011-09-25', '2011-10-02',
                   '2011-10-09', '2011-10-16', '2011-10-23', '2011-10-30',
                   '2011-11-06', '2011-11-13', '2011-11-20', '2011-11-27',
                   '2011-12-04', '2011-12-11', '2011-12-18', '2011-12-25',
                   '2012-01-01'],
                  dtype='datetime64[ns]', freq='W-SUN')
    
    In [84]: pd.bdate_range(end=end, periods=20)
    Out[84]: 
    DatetimeIndex(['2011-12-05', '2011-12-06', '2011-12-07', '2011-12-08',
                   '2011-12-09', '2011-12-12', '2011-12-13', '2011-12-14',
                   '2011-12-15', '2011-12-16', '2011-12-19', '2011-12-20',
                   '2011-12-21', '2011-12-22', '2011-12-23', '2011-12-26',
                   '2011-12-27', '2011-12-28', '2011-12-29', '2011-12-30'],
                  dtype='datetime64[ns]', freq='B')
    
    In [85]: pd.bdate_range(start=start, periods=20)
    Out[85]: 
    DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
                   '2011-01-07', '2011-01-10', '2011-01-11', '2011-01-12',
                   '2011-01-13', '2011-01-14', '2011-01-17', '2011-01-18',
                   '2011-01-19', '2011-01-20', '2011-01-21', '2011-01-24',
                   '2011-01-25', '2011-01-26', '2011-01-27', '2011-01-28'],
                  dtype='datetime64[ns]', freq='B')
    

    0.23.0 版新增。

    指定 startendperiods 即可生成从 start 开始至 end 结束的等距日期范围,这个日期范围包含了 startend,生成的 DatetimeIndex 里的元素数量为 periods 的值。

    In [86]: pd.date_range('2018-01-01', '2018-01-05', periods=5)
    Out[86]: 
    DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
                   '2018-01-05'],
                  dtype='datetime64[ns]', freq=None)
    
    In [87]: pd.date_range('2018-01-01', '2018-01-05', periods=10)
    Out[87]: 
    DatetimeIndex(['2018-01-01 00:00:00', '2018-01-01 10:40:00',
                   '2018-01-01 21:20:00', '2018-01-02 08:00:00',
                   '2018-01-02 18:40:00', '2018-01-03 05:20:00',
                   '2018-01-03 16:00:00', '2018-01-04 02:40:00',
                   '2018-01-04 13:20:00', '2018-01-05 00:00:00'],
                  dtype='datetime64[ns]', freq=None)
    

    自定义频率范围

    设定 weekmaskholidays 参数,bdate_range 还可以生成自定义频率日期范围。这些参数只用于传递自定义字符串。

    In [88]: weekmask = 'Mon Wed Fri'
    
    In [89]: holidays = [datetime.datetime(2011, 1, 5), datetime.datetime(2011, 3, 14)]
    
    In [90]: pd.bdate_range(start, end, freq='C', weekmask=weekmask, holidays=holidays)
    Out[90]: 
    DatetimeIndex(['2011-01-03', '2011-01-07', '2011-01-10', '2011-01-12',
                   '2011-01-14', '2011-01-17', '2011-01-19', '2011-01-21',
                   '2011-01-24', '2011-01-26',
                   ...
                   '2011-12-09', '2011-12-12', '2011-12-14', '2011-12-16',
                   '2011-12-19', '2011-12-21', '2011-12-23', '2011-12-26',
                   '2011-12-28', '2011-12-30'],
                  dtype='datetime64[ns]', length=154, freq='C')
    
    In [91]: pd.bdate_range(start, end, freq='CBMS', weekmask=weekmask)
    Out[91]: 
    DatetimeIndex(['2011-01-03', '2011-02-02', '2011-03-02', '2011-04-01',
                   '2011-05-02', '2011-06-01', '2011-07-01', '2011-08-01',
                   '2011-09-02', '2011-10-03', '2011-11-02', '2011-12-02'],
                  dtype='datetime64[ns]', freq='CBMS')
    

    参阅:自定义工作日

    时间戳的界限

    Pandas 时间戳的最低单位为纳秒,64 位整数显示的时间跨度约为 584 年,这就是 Timestamp 的界限:

    In [92]: pd.Timestamp.min
    Out[92]: Timestamp('1677-09-21 00:12:43.145225')
    
    In [93]: pd.Timestamp.max
    Out[93]: Timestamp('2262-04-11 23:47:16.854775807')
    

    参阅:时间段越界展示

    Pandas 百问百答系列

    相关文章

      网友评论

        本文标题:Pandas 时间序列 - 纵览与时间戳

        本文链接:https://www.haomeiwen.com/subject/dazrgctx.html