欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Pandas】Pandas的时间与日期

程序员文章站 2024-01-21 22:41:28
...

注意:重要且关键章节已标星

目录

概述

时间戳与时间跨度

转换为时间戳

提供格式参数(指定时间格式)*

从多个DataFrame列组装日期时间

无效数据

纪元时间戳

从时间戳到纪元

使用origin参数

生成时间戳范围

自定义频率范围

时间戳限制

索引

部分字符串索引

切片与精确匹配

精确索引

截断和花式索引

时间/日期组件

DateOffset对象(时间量偏移方法)*

参数偏移

使用偏移量 Series / DatetimeIndex

定制营业日

营业时间

自定义营业时间

偏移别名

组合别名

锚定偏移

锚定偏移语义

假期/假日日历

时间序列相关实例方法

移位/滞后

频率转换

向前/向后填充

转换为Python日期时间

重新采样

基础知识

上采样

稀疏重采样

聚合

时间跨度表示

周期(时间移动步长)*

PeriodIndex和period_range 

Period Dtypes

PeriodIndex部分字符串索引

使用PeriodIndex进行频率转换和重采样

在表示之间转换(时间格式变换)*

表示超出范围的跨度

时区处理


 

事实证明,熊猫作为处理时间序列数据的工具非常成功,特别是在财务数据分析领域。使用NumPy datetime64timedelta64dtypes,我们整合了其他Python库中的大量功能,scikits.timeseries并创建了大量用于处理时间序列数据的新功能。

在处理时间序列数据时,我们会经常寻求:

  • 生成固定频率日期和时间跨度的序列
  • 使时间序列符合或转换为特定频率
  • 根据各种非标准时间增量计算“相对”日期(例如,在一年的最后一个工作日之前的5个工作日),或向前或向后“滚动”日期

pandas提供了一套相对紧凑且独立的工具,用于执行上述任务。

创建一系列日期:

In [1]: rng = pd.date_range('1/1/2011', periods=72, freq='H')

In [2]: rng[:5]
Out[2]: 
DatetimeIndex(['2011-01-01 00:00:00', '2011-01-01 01:00:00',
               '2011-01-01 02:00:00', '2011-01-01 03:00:00',
               '2011-01-01 04:00:00'],
              dtype='datetime64[ns]', freq='H')

带有日期的索引pandas对象:

In [3]: ts = pd.Series(np.random.randn(len(rng)), index=rng)

In [4]: ts.head()
Out[4]: 
2011-01-01 00:00:00    0.469112
2011-01-01 01:00:00   -0.282863
2011-01-01 02:00:00   -1.509059
2011-01-01 03:00:00   -1.135632
2011-01-01 04:00:00    1.212112
Freq: H, dtype: float64

改变频率和填补空白:

# 到45分钟的频率和前向填充
In [5]: converted = ts.asfreq('45Min', method='pad')

In [6]: converted.head()
Out[6]: 
2011-01-01 00:00:00    0.469112
2011-01-01 00:45:00    0.469112
2011-01-01 01:30:00   -0.282863
2011-01-01 02:15:00   -1.509059
2011-01-01 03:00:00   -1.135632
Freq: 45T, dtype: float64

将系列重新采样到每日频率:

# 日平均
In [7]: ts.resample('D').mean()
Out[7]: 
2011-01-01   -0.319569
2011-01-02   -0.337703
2011-01-03    0.117258
Freq: D, dtype: float64

 

概述

下表显示了pandas可以处理的与时间相关的类的类型以及如何创建它们。

备注 如何创造
Timestamp 表示单个时间戳 to_datetime, Timestamp
DatetimeIndex 指数 Timestamp to_datetimedate_rangebdate_rangeDatetimeIndex
Period 表示单个时间跨度 Period
PeriodIndex 指数 Period period_range, PeriodIndex

 

时间戳与时间跨度

带时间戳的数据是将值与时间点相关联的最基本类型的时间序列数据。对于pandas对象,它意味着使用时间点。

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

In [9]: pd.Timestamp('2012-05-01')
Out[9]: Timestamp('2012-05-01 00:00:00')

In [10]: pd.Timestamp(2012, 5, 1)
Out[10]: Timestamp('2012-05-01 00:00:00')

但是,在许多情况下,将变量变量与时间跨度相关联更为自然。表示的范围Period可以显式指定,也可以从日期时间字符串格式推断。

例如:

In [11]: pd.Period('2011-01')
Out[11]: Period('2011-01', 'M')

In [12]: pd.Period('2012-05', freq='D')
Out[12]: Period('2012-05-01', 'D')

TimestampPeriod可以作为索引。名单 TimestampPeriod被自动强制转换DatetimeIndex 和PeriodIndex分别。

In [13]: dates = [pd.Timestamp('2012-05-01'), pd.Timestamp('2012-05-02'), pd.Timestamp('2012-05-03')]

In [14]: ts = pd.Series(np.random.randn(3), dates)

In [15]: type(ts.index)
Out[15]: pandas.core.indexes.datetimes.DatetimeIndex

In [16]: ts.index
Out[16]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)

In [17]: ts
Out[17]: 
2012-05-01   -0.410001
2012-05-02   -0.078638
2012-05-03    0.545952
dtype: float64

In [18]: periods = [pd.Period('2012-01'), pd.Period('2012-02'), pd.Period('2012-03')]

In [19]: ts = pd.Series(np.random.randn(3), periods)

In [20]: type(ts.index)
Out[20]: pandas.core.indexes.period.PeriodIndex

In [21]: ts.index
Out[21]: PeriodIndex(['2012-01', '2012-02', '2012-03'], dtype='period[M]', freq='M')

In [22]: ts
Out[22]: 
2012-01   -1.219217
2012-02   -1.226825
2012-03    0.769804
Freq: M, dtype: float64

pandas允许您捕获两个表示并在它们之间进行转换。在引擎盖下,pandas表示使用实例的时间戳的实例Timestamp和时间戳的时间戳 DatetimeIndex。对于常规时间跨度,pandas使用Period对象作为标量值和PeriodIndex跨度序列。在未来的版本中,对具有任意起点和终点的不规则间隔的更好支持将会出现。

 

转换为时间戳

要转换Series类似日期的对象或类似列表的对象,例如字符串,纪元或混合,您可以使用该to_datetime函数。当传递a时Series,它返回一个Series(具有相同的索引),而类似列表的转换为DatetimeIndex

In [23]: pd.to_datetime(pd.Series(['Jul 31, 2009', '2010-01-10', None]))
Out[23]: 
0   2009-07-31
1   2010-01-10
2          NaT
dtype: datetime64[ns]

In [24]: pd.to_datetime(['2005/11/23', '2010.12.31'])
Out[24]: DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)

如果您使用从第一天开始的日期(即欧洲风格),您可以传递dayfirst旗帜:

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

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

警告:您在上面的示例中看到dayfirst的并不严格,因此如果无法在第一天解析日期,则会将其解析为dayfirstFalse。

如果传递单个字符串to_datetime,则返回单个字符串Timestamp。 Timestamp也可以接受字符串输入,但是它不接受像dayfirstformat那样的字符串解析选项,所以to_datetime如果需要这些选项则使用。

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

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

 

提供格式参数(指定时间格式)*

除了所需的日期时间字符串之外,format还可以传递参数以确保特定的解析。这也可能大大加快转换速度。

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

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

有关指定format 选项时可用选项的更多信息,请参阅Python datetime文档

 

从多个DataFrame列组装日期时间

您也可以通过一个DataFrame整数或字符串列组装成SeriesTimestamps

In [31]: df = pd.DataFrame({'year': [2015, 2016],
   ....:                    'month': [2, 3],
   ....:                    'day': [4, 5],
   ....:                    'hour': [2, 3]})
   ....: 

In [32]: pd.to_datetime(df)
Out[32]: 
0   2015-02-04 02:00:00
1   2016-03-05 03:00:00
dtype: datetime64[ns]

您只能传递需要组装的列。

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

pd.to_datetime 在列名中查找datetime组件的标准名称,包括:

  • 要求:yearmonthday
  • 可选:hourminutesecondmillisecondmicrosecondnanosecond

 

无效数据

默认行为errors='raise'是在不可解析时引发:

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

传递errors='ignore'以在不可解析时返回原始输入:

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

传递errors='coerce'将不可解析的数据转换为NaT(不是时间):

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

 

纪元时间戳

pandas支持将整数或浮点时间转换为Timestamp和 DatetimeIndex。默认单位是纳秒,因为这是Timestamp 对象在内部存储的方式。但是,时期通常存储在另一个unit 可以指定的时期。这些是从origin参数指定的起始点计算的 。

In [36]: pd.to_datetime([1349720105, 1349806505, 1349892905,
   ....:                 1349979305, 1350065705], unit='s')
   ....: 
Out[36]: 
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 [37]: pd.to_datetime([1349720105100, 1349720105200, 1349720105300,
   ....:                 1349720105400, 1349720105500 ], unit='ms')
   ....: 
Out[37]: 
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)

注意:*时间将四舍五入到最接近的纳秒。

警告:

浮动纪元时间的转换可能导致不准确和意外的结果。 Python浮点数的十进制精度约为15位。从浮动到高精度的转换过程中的舍入Timestamp是不可避免的。实现精确精度的唯一方法是使用固定宽度类型(例如int64)。

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

In [39]: pd.to_datetime(1490195805433502912, unit='ns')
Out[39]: Timestamp('2017-03-22 15:16:45.433502912')

 

 

从时间戳到纪元

要从上面反转操作,即从a转换Timestamp为'unix'时代:

In [40]: stamps = pd.date_range('2012-10-08 18:15:05', periods=4, freq='D')

In [41]: stamps
Out[41]: 
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')

我们减去时期(UT​​C时间1970年1月1日午夜),然后除以“单位”(1秒)。

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

 

使用origin参数

使用该origin参数,可以指定创建a的替代起点DatetimeIndex。例如,要使用1960-01-01作为开始日期:

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

默认设置为origin='unix',默认为。俗称'unix epoch'或POSIX时间。1970-01-01 00:00:00

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

 

生成时间戳范围

要生成带时间戳的索引,可以使用DatetimeIndex或 Index构造函数并传入datetime对象列表:

In [45]: dates = [datetime(2012, 5, 1), datetime(2012, 5, 2), datetime(2012, 5, 3)]

# Note the frequency information
In [46]: index = pd.DatetimeIndex(dates)

In [47]: index
Out[47]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)

# Automatically converted to DatetimeIndex
In [48]: index = pd.Index(dates)

In [49]: index
Out[49]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)

在实践中,这变得非常麻烦,因为我们经常需要具有大量时间戳的非常长的索引。如果我们需要常规频率的时间戳,我们可以使用date_range()bdate_range()函数来创建一个DatetimeIndex。对于默认频率date_range为一个 日历日,而默认bdate_range工作日

In [50]: start = datetime(2011, 1, 1)

In [51]: end = datetime(2012, 1, 1)

In [52]: index = pd.date_range(start, end)

In [53]: index
Out[53]: 
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 [54]: index = pd.bdate_range(start, end)

In [55]: index
Out[55]: 
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 [56]: pd.date_range(start, periods=1000, freq='M')
Out[56]: 
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 [57]: pd.bdate_range(start, periods=250, freq='BQS')
Out[57]: 
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_range并且bdate_range可以很容易地使用的参数的各种组合等生成日期的范围startendperiods,和freq。开始日期和结束日期是严格包含的,因此不会生成指定日期之外的日期:

In [58]: pd.date_range(start, end, freq='BM')
Out[58]: 
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 [59]: pd.date_range(start, end, freq='W')
Out[59]: 
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 [60]: pd.bdate_range(end=end, periods=20)
Out[60]: 
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 [61]: pd.bdate_range(start=start, periods=20)
Out[61]: 
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包含,结果中包含periods多个元素DatetimeIndex

In [62]: pd.date_range('2018-01-01', '2018-01-05', periods=5)
Out[62]: 
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
               '2018-01-05'],
              dtype='datetime64[ns]', freq=None)

In [63]: pd.date_range('2018-01-01', '2018-01-05', periods=10)
Out[63]: 
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)

 

自定义频率范围

警告:此功能最初是独占的cdate_range,从版本0.21.0开始不赞成使用bdate_range。请注意, cdate_range仅在自定义工作日“C”作为频率字符串传递时才使用weekmaskholidays参数。支持已经扩展,bdate_range可以使用任何自定义频率字符串。

版本0.21.0中的新功能。

bdate_range还可以使用weekmaskholidays参数生成一系列自定义频率日期。仅在传递自定义频率字符串时才使用这些参数。

In [64]: weekmask = 'Mon Wed Fri'

In [65]: holidays = [datetime(2011, 1, 5), datetime(2011, 3, 14)]

In [66]: pd.bdate_range(start, end, freq='C', weekmask=weekmask, holidays=holidays)
Out[66]: 
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 [67]: pd.bdate_range(start, end, freq='CBMS', weekmask=weekmask)
Out[67]: 
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年:

In [68]: pd.Timestamp.min
Out[68]: Timestamp('1677-09-21 00:12:43.145225')

In [69]: pd.Timestamp.max
Out[69]: Timestamp('2262-04-11 23:47:16.854775807')

 

索引

其中一个主要用途DatetimeIndex是作为pandas对象的索引。本DatetimeIndex类包含许多时间序列相关的优化:

  • 各种偏移的大范围日期被预先计算并缓存在引擎盖下,以便非常快地生成后续日期范围(只需抓取一个切片)。
  • 使用pandas对象上的shiftand tshift方法快速移动。
  • DatetimeIndex具有相同频率的重叠对象的联合非常快(对于快速数据对齐很重要)。
  • 通过性能,如快速访问日期字段yearmonth等等。
  • 正则化功能snap和非常快速的asof逻辑。

DatetimeIndex对象具有常规Index 对象的所有基本功能,以及高级时间序列特定方法的大杂烩,便于频率处理。

注意:虽然pandas不会强制您使用已排序的日期索引,但如果日期未排序,则某些方法可能会出现意外或不正确的行为。

DatetimeIndex 可以像常规索引一样使用,并提供所有智能功能,如选择,切片等。

In [70]: rng = pd.date_range(start, end, freq='BM')

In [71]: ts = pd.Series(np.random.randn(len(rng)), index=rng)

In [72]: ts.index
Out[72]: 
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 [73]: ts[:5].index
Out[73]: 
DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-29',
               '2011-05-31'],
              dtype='datetime64[ns]', freq='BM')

In [74]: ts[::2].index
Out[74]: 
DatetimeIndex(['2011-01-31', '2011-03-31', '2011-05-31', '2011-07-29',
               '2011-09-30', '2011-11-30'],
              dtype='datetime64[ns]', freq='2BM')

部分字符串索引

解析为时间戳的日期和字符串可以作为索引参数传递:

In [75]: ts['1/31/2011']
Out[75]: -1.2812473076599531

In [76]: ts[datetime(2011, 12, 25):]
Out[76]: 
2011-12-30    0.687738
Freq: BM, dtype: float64

In [77]: ts['10/31/2011':'12/31/2011']
Out[77]: 
2011-10-31    0.149748
2011-11-30   -0.732339
2011-12-30    0.687738
Freq: BM, dtype: float64

为了方便访问更长的时间序列,您还可以将年份或年份和月份作为字符串传递:

In [78]: ts['2011']
Out[78]: 
2011-01-31   -1.281247
2011-02-28   -0.727707
2011-03-31   -0.121306
2011-04-29   -0.097883
2011-05-31    0.695775
2011-06-30    0.341734
2011-07-29    0.959726
2011-08-31   -1.110336
2011-09-30   -0.619976
2011-10-31    0.149748
2011-11-30   -0.732339
2011-12-30    0.687738
Freq: BM, dtype: float64

In [79]: ts['2011-6']
Out[79]: 
2011-06-30    0.341734
Freq: BM, dtype: float64

这种类型的切片将在一个工作DataFrameDatetimeIndex为好。由于部分字符串选择是标签切片的一种形式,因此包括端点。这将包括在包含日期的匹配时间:

In [80]: dft = pd.DataFrame(randn(100000,1),
   ....:                    columns=['A'],
   ....:                    index=pd.date_range('20130101',periods=100000,freq='T'))
   ....: 

In [81]: dft
Out[81]: 
                            A
2013-01-01 00:00:00  0.176444
2013-01-01 00:01:00  0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00  0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
...                       ...
2013-03-11 10:33:00 -0.293083
2013-03-11 10:34:00 -0.059881
2013-03-11 10:35:00  1.252450
2013-03-11 10:36:00  0.046611
2013-03-11 10:37:00  0.059478
2013-03-11 10:38:00 -0.286539
2013-03-11 10:39:00  0.841669

[100000 rows x 1 columns]

In [82]: dft['2013']
Out[82]: 
                            A
2013-01-01 00:00:00  0.176444
2013-01-01 00:01:00  0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00  0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
...                       ...
2013-03-11 10:33:00 -0.293083
2013-03-11 10:34:00 -0.059881
2013-03-11 10:35:00  1.252450
2013-03-11 10:36:00  0.046611
2013-03-11 10:37:00  0.059478
2013-03-11 10:38:00 -0.286539
2013-03-11 10:39:00  0.841669

[100000 rows x 1 columns]

这是在本月的第一次开始,包括该月的最后日期和时间:

In [83]: dft['2013-1':'2013-2']
Out[83]: 
                            A
2013-01-01 00:00:00  0.176444
2013-01-01 00:01:00  0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00  0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
...                       ...
2013-02-28 23:53:00  0.103114
2013-02-28 23:54:00 -1.303422
2013-02-28 23:55:00  0.451943
2013-02-28 23:56:00  0.220534
2013-02-28 23:57:00 -1.624220
2013-02-28 23:58:00  0.093915
2013-02-28 23:59:00 -1.087454

[84960 rows x 1 columns]

这指定了包含最后一天所有时间的停止时间:

In [84]: dft['2013-1':'2013-2-28']
Out[84]: 
                            A
2013-01-01 00:00:00  0.176444
2013-01-01 00:01:00  0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00  0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
...                       ...
2013-02-28 23:53:00  0.103114
2013-02-28 23:54:00 -1.303422
2013-02-28 23:55:00  0.451943
2013-02-28 23:56:00  0.220534
2013-02-28 23:57:00 -1.624220
2013-02-28 23:58:00  0.093915
2013-02-28 23:59:00 -1.087454

[84960 rows x 1 columns]

这指定了确切的停止时间(并且与上面的不同):

In [85]: dft['2013-1':'2013-2-28 00:00:00']
Out[85]: 
                            A
2013-01-01 00:00:00  0.176444
2013-01-01 00:01:00  0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00  0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
...                       ...
2013-02-27 23:54:00  0.897051
2013-02-27 23:55:00 -0.309230
2013-02-27 23:56:00  1.944713
2013-02-27 23:57:00  0.369265
2013-02-27 23:58:00  0.053071
2013-02-27 23:59:00 -0.019734
2013-02-28 00:00:00  1.388189

[83521 rows x 1 columns]

我们正在停止包含的终点,因为它是索引的一部分:

In [86]: dft['2013-1-15':'2013-1-15 12:30:00']
Out[86]: 
                            A
2013-01-15 00:00:00  0.501288
2013-01-15 00:01:00 -0.605198
2013-01-15 00:02:00  0.215146
2013-01-15 00:03:00  0.924732
2013-01-15 00:04:00 -2.228519
2013-01-15 00:05:00  1.517331
2013-01-15 00:06:00 -1.188774
...                       ...
2013-01-15 12:24:00  1.358314
2013-01-15 12:25:00 -0.737727
2013-01-15 12:26:00  1.838323
2013-01-15 12:27:00 -0.774090
2013-01-15 12:28:00  0.622261
2013-01-15 12:29:00 -0.631649
2013-01-15 12:30:00  0.193284

[751 rows x 1 columns]

版本0.18.0中的新功能。

DatetimeIndex部分字符串索引也适用于DataFrameMultiIndex

In [87]: dft2 = pd.DataFrame(np.random.randn(20, 1),
   ....:                     columns=['A'],
   ....:                     index=pd.MultiIndex.from_product([pd.date_range('20130101',
   ....:                                                                     periods=10,
   ....:                                                                     freq='12H'),
   ....:                                                      ['a', 'b']]))
   ....: 

In [88]: dft2
Out[88]: 
                              A
2013-01-01 00:00:00 a -0.659574
                    b  1.494522
2013-01-01 12:00:00 a -0.778425
                    b -0.253355
2013-01-02 00:00:00 a -2.816159
                    b -1.210929
2013-01-02 12:00:00 a  0.144669
...                         ...
2013-01-04 00:00:00 b -1.624463
2013-01-04 12:00:00 a  0.056912
                    b  0.149867
2013-01-05 00:00:00 a -1.256173
                    b  2.324544
2013-01-05 12:00:00 a -1.067396
                    b -0.660996

[20 rows x 1 columns]

In [89]: dft2.loc['2013-01-05']
Out[89]: 
                              A
2013-01-05 00:00:00 a -1.256173
                    b  2.324544
2013-01-05 12:00:00 a -1.067396
                    b -0.660996

In [90]: idx = pd.IndexSlice

In [91]: dft2 = dft2.swaplevel(0, 1).sort_index()

In [92]: dft2.loc[idx[:, '2013-01-05'], :]
Out[92]: 
                              A
a 2013-01-05 00:00:00 -1.256173
  2013-01-05 12:00:00 -1.067396
b 2013-01-05 00:00:00  2.324544
  2013-01-05 12:00:00 -0.660996

 

切片与精确匹配

版本0.20.0已更改。

用作索引参数的相同字符串可以被视为切片或完全匹配,具体取决于索引的分辨率。如果字符串不如索引准确,则将其视为切片,否则视为完全匹配。

考虑Series具有分钟分辨率索引的对象:

In [93]: series_minute = pd.Series([1, 2, 3],
   ....:                           pd.DatetimeIndex(['2011-12-31 23:59:00',
   ....:                                             '2012-01-01 00:00:00',
   ....:                                             '2012-01-01 00:02:00']))
   ....: 

In [94]: series_minute.index.resolution
Out[94]: 'minute'

时间戳字符串不如一分钟准确给出一个Series对象。

In [95]: series_minute['2011-12-31 23']
Out[95]: 
2011-12-31 23:59:00    1
dtype: int64

具有分钟分辨率(或更准确)的时间戳字符串,而是给出标量,即它不会转换为切片。

In [96]: series_minute['2011-12-31 23:59']
Out[96]: 1

In [97]: series_minute['2011-12-31 23:59:00']
Out[97]: 1

如果索引分辨率是秒,那么分钟准确的时间戳给出了 Series

In [98]: series_second = pd.Series([1, 2, 3],
   ....:                           pd.DatetimeIndex(['2011-12-31 23:59:59',
   ....:                                             '2012-01-01 00:00:00',
   ....:                                             '2012-01-01 00:00:01']))
   ....: 

In [99]: series_second.index.resolution
Out[99]: 'second'

In [100]: series_second['2011-12-31 23:59']
Out[100]: 
2011-12-31 23:59:59    1
dtype: int64

如果时间戳字符串作为一个切片进行处理,它可被用于索引DataFrame[]为好。

In [101]: dft_minute = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]},
   .....:                            index=series_minute.index)
   .....: 

In [102]: dft_minute['2011-12-31 23']
Out[102]: 
                     a  b
2011-12-31 23:59:00  1  4

 

警告:但是,如果将字符串视为完全匹配,则DataFrames中的选择[]将按列而不是按行进行,请参阅索引基础知识。例如将提高为具有相同的分辨率指标,有这样的名字没有列:dft_minute['2011-12-31 23:59']KeyError'2012-12-31 23:59'

始终具有明确的选择,无论该行是被视为切片还是单个选择,请使用.loc

In [103]: dft_minute.loc['2011-12-31 23:59']
Out[103]: 
a    1
b    4
Name: 2011-12-31 23:59:00, dtype: int64

 

还要注意,DatetimeIndex分辨率不能比白天精确。

In [104]: series_monthly = pd.Series([1, 2, 3],
   .....:                           pd.DatetimeIndex(['2011-12',
   .....:                                             '2012-01',
   .....:                                             '2012-02']))
   .....: 

In [105]: series_monthly.index.resolution
Out[105]: 'day'

In [106]: series_monthly['2011-12'] # returns Series
Out[106]: 
2011-12-01    1
dtype: int64

 

精确索引

如前一节所述DatetimeIndex,使用部分字符串索引a 取决于句点的“准确性”,换句话说,间隔与索引的分辨率有何关联。相比之下,使用Timestampdatetime对象进行索引是准确的,因为对象具有确切的含义。这些也遵循包含两个端点的语义。

这些Timestampdatetime对象有确切的和,即使他们没有明确规定(他们是)。hours, minutes,seconds0

In [107]: dft[datetime(2013, 1, 1):datetime(2013,2,28)]
Out[107]: 
                            A
2013-01-01 00:00:00  0.176444
2013-01-01 00:01:00  0.403310
2013-01-01 00:02:00 -0.154951
2013-01-01 00:03:00  0.301624
2013-01-01 00:04:00 -2.179861
2013-01-01 00:05:00 -1.369849
2013-01-01 00:06:00 -0.954208
...                       ...
2013-02-27 23:54:00  0.897051
2013-02-27 23:55:00 -0.309230
2013-02-27 23:56:00  1.944713
2013-02-27 23:57:00  0.369265
2013-02-27 23:58:00  0.053071
2013-02-27 23:59:00 -0.019734
2013-02-28 00:00:00  1.388189

[83521 rows x 1 columns]

没有默认值。

In [108]: dft[datetime(2013, 1, 1, 10, 12, 0):datetime(2013, 2, 28, 10, 12, 0)]
Out[108]: 
                            A
2013-01-01 10:12:00 -0.246733
2013-01-01 10:13:00 -1.429225
2013-01-01 10:14:00 -1.265339
2013-01-01 10:15:00  0.710986
2013-01-01 10:16:00 -0.818200
2013-01-01 10:17:00  0.543542
2013-01-01 10:18:00  1.577713
...                       ...
2013-02-28 10:06:00  0.311249
2013-02-28 10:07:00  2.366080
2013-02-28 10:08:00 -0.490372
2013-02-28 10:09:00  0.373340
2013-02-28 10:10:00  0.638442
2013-02-28 10:11:00  1.330135
2013-02-28 10:12:00 -0.945450

[83521 rows x 1 columns]

截断和花式索引

truncate()提供方便的功能类似于切片。请注意,truncate对于任何未指定的日期组件,假设为0 DatetimeIndex,与切片相反,返回任何部分匹配的日期:

In [109]: rng2 = pd.date_range('2011-01-01', '2012-01-01', freq='W')

In [110]: ts2 = pd.Series(np.random.randn(len(rng2)), index=rng2)

In [111]: ts2.truncate(before='2011-11', after='2011-12')
Out[111]: 
2011-11-06   -0.773743
2011-11-13    0.247216
2011-11-20    0.591308
2011-11-27    2.228500
Freq: W-SUN, dtype: float64

In [112]: ts2['2011-11':'2011-12']
Out[112]: 
2011-11-06   -0.773743
2011-11-13    0.247216
2011-11-20    0.591308
2011-11-27    2.228500
2011-12-04    0.838769
2011-12-11    0.658538
2011-12-18    0.567353
2011-12-25   -1.076735
Freq: W-SUN, dtype: float64

即使复杂的花式索引打破了DatetimeIndex频率规律也会导致a DatetimeIndex,虽然频率会丢失:

In [113]: ts2[[0, 2, 6]].index
Out[113]: DatetimeIndex(['2011-01-02', '2011-01-16', '2011-02-13'], dtype='datetime64[ns]', freq=None)

 

时间/日期组件

有一些时间/日期属性可供人们访问,Timestamp或者有一组时间戳,如a DatetimeIndex

属性 描述
year 日期时间
month 日期时间的月份
day 日期时间的日子
hour 日期时间的小时
minute 日期时间的分钟
second 日期时间的秒数
ms 日期时间的微秒
ns 日期时间的纳秒
date 返回datetime.date(不包含时区信息)
time 返回datetime.time(不包含时区信息)
DAYOFYEAR 一年中的序数日
WEEKOFYEAR 一年中的一周序数
week 一年中的一周序数
dayofweek 星期一= 0,星期日= 6的星期几
weekday 星期一= 0,星期日= 6的星期几
weekday_name 一周中的一天的名字(例如:星期五)
quarter 日期的四分之一:Jan-Mar = 1,Apr-Jun = 2等
days_in_month 日期时间的月份天数
is_month_start 逻辑指示是否每月的第一天(由频率定义)
is_month_end 逻辑指示是否每月的最后一天(由频率定义)
is_quarter_start 逻辑指示季度的第一天(由频率定义)
is_quarter_end 逻辑指示是否是季度的最后一天(由频率定义)
is_year_start 逻辑指示年份的第一天(由频率定义)
is_year_end 逻辑指示年份的最后一天(由频率定义)
is_leap_year 逻辑指示日期是否属于闰年

此外,如果您具有Seriesdatetimelike值,则可以通过访问器访问这些属性.dt,详见.dt访问器一节。

 

DateOffset对象(时间量偏移方法)*

在前面的例子中,我们DatetimeIndex通过将 诸如“M”,“W”和“BM”的频率字符串传递给freq关键字来创建各种频率的对象。在引擎盖下,这些频率字符串被转换为实例DateOffset,其表示常规频率增量。“月”,“营业日”或“一小时”等特定偏移逻辑在其各个子类中表示。

类别名称 描述
DateOffset 通用偏移类,默认为1个日历日
BDAY 营业日(工作日)
CDay 自定义工作日
Week 一周,任选地固定在一周的一天
WeekOfMonth 每个月的第y周的第x天
LastWeekOfMonth 每个月最后一周的第x天
MonthEnd 日历月结束
MonthBegin 日历月开始
BMonthEnd 营业月末
BMonthBegin 营业月开始
CBMonthEnd 定制业务月末
CBMonthBegin 自定义营业月开始
SemiMonthEnd 15日(或其他日__月)和日历月结束
SemiMonthBegin 15日(或其他日__月)和日历月开始
QuarterEnd 日历季结束
QuarterBegin 日历季开始
BQuarterEnd 业务季结束
BQuarterBegin 营业季开始
FY5253Quarter 零售(又名52-53周)季度
YearEnd 日历年结束
YearBegin 日历年开始
BYearEnd 业务年度结束
BYearBegin 营业年开始
FY5253 零售(又名52-53周)年
BusinessHour 营业时间
CustomBusinessHour 定制营业时间
Hour 一小时
Minute 一分钟
Second 一秒
Milli 一毫秒
Micro 一微秒
Nano 一纳秒

基本DateOffset采用相同的参数 dateutil.relativedelta,其工作方式如下:

In [114]: d = datetime(2008, 8, 18, 9, 0)

In [115]: d + relativedelta(months=4, days=5)
Out[115]: datetime.datetime(2008, 12, 23, 9, 0)

我们可以做同样的事情DateOffset

In [116]: from pandas.tseries.offsets import *

In [117]: d + DateOffset(months=4, days=5)
Out[117]: Timestamp('2008-12-23 09:00:00')

DateOffset对象的主要特征是:

  • 可以向/从日期时间对象添加/减去它以获得移位日期。
  • 它可以乘以整数(正数或负数),以便多次应用增量。
  • 它具有rollforward()和 rollback()用于向前或向后移动日期下一首或上“抵消日期”的方法。

DateOffset定义指定apply自定义日期增量逻辑的函数的子类,例如添加工作日:

class BDay(DateOffset):
    """工作日之间的DateOffset递增"""
    def apply(self, other):
        ...
In [118]: d - 5 * BDay()
Out[118]: Timestamp('2008-08-11 09:00:00')

In [119]: d + BMonthEnd()
Out[119]: Timestamp('2008-08-29 09:00:00')

rollforwardrollback方法做的正是你所期待的:

In [120]: d
Out[120]: datetime.datetime(2008, 8, 18, 9, 0)

In [121]: offset = BMonthEnd()

In [122]: offset.rollforward(d)
Out[122]: Timestamp('2008-08-29 09:00:00')

In [123]: offset.rollback(d)
Out[123]: Timestamp('2008-07-31 09:00:00')

绝对值得探索pandas.tseries.offsets模块和类的各种docstrings。

这些操作(applyrollforwardrollback)保存时间(小时,分钟等)的默认信息。要重置时间,请normalize=True 在创建偏移实例时使用。如果normalize=True,则在应用函数后对结果进行归一化。

In [124]: day = Day()

In [125]: day.apply(pd.Timestamp('2014-01-01 09:00'))
Out[125]: Timestamp('2014-01-02 09:00:00')

In [126]: day = Day(normalize=True)

In [127]: day.apply(pd.Timestamp('2014-01-01 09:00'))
Out[127]: Timestamp('2014-01-02 00:00:00')

In [128]: hour = Hour()

In [129]: hour.apply(pd.Timestamp('2014-01-01 22:00'))
Out[129]: Timestamp('2014-01-01 23:00:00')

In [130]: hour = Hour(normalize=True)

In [131]: hour.apply(pd.Timestamp('2014-01-01 22:00'))
Out[131]: Timestamp('2014-01-01 00:00:00')

In [132]: hour.apply(pd.Timestamp('2014-01-01 23:00'))
Out[132]: Timestamp('2014-01-02 00:00:00')

参数偏移

创建时,某些偏移可以“参数化”以产生不同的行为。例如,Week生成每周数据的偏移量接受一个weekday参数,该 参数导致生成的日期始终位于一周中的特定日期:

In [133]: d
Out[133]: datetime.datetime(2008, 8, 18, 9, 0)

In [134]: d + Week()
Out[134]: Timestamp('2008-08-25 09:00:00')

In [135]: d + Week(weekday=4)
Out[135]: Timestamp('2008-08-22 09:00:00')

In [136]: (d + Week(weekday=4)).weekday()
Out[136]: 4

In [137]: d - Week()
Out[137]: Timestamp('2008-08-11 09:00:00')

normalize选项对加法和减法有效。

In [138]: d + Week(normalize=True)
Out[138]: Timestamp('2008-08-25 00:00:00')

In [139]: d - Week(normalize=True)
Out[139]: Timestamp('2008-08-11 00:00:00')

另一个例子是YearEnd使用特定的结束月份进行参数化:

In [140]: d + YearEnd()
Out[140]: Timestamp('2008-12-31 09:00:00')

In [141]: d + YearEnd(month=6)
Out[141]: Timestamp('2009-06-30 09:00:00')

使用偏移量 Series / DatetimeIndex

偏移可与被用在SeriesDatetimeIndex施加的偏移量的每个元素。

In [142]: rng = pd.date_range('2012-01-01', '2012-01-03')

In [143]: s = pd.Series(rng)

In [144]: rng
Out[144]: DatetimeIndex(['2012-01-01', '2012-01-02', '2012-01-03'], dtype='datetime64[ns]', freq='D')

In [145]: rng + DateOffset(months=2)
Out[145]: DatetimeIndex(['2012-03-01', '2012-03-02', '2012-03-03'], dtype='datetime64[ns]', freq='D')

In [146]: s + DateOffset(months=2)
Out[146]: 
0   2012-03-01
1   2012-03-02
2   2012-03-03
dtype: datetime64[ns]

In [147]: s - DateOffset(months=2)
Out[147]: 
0   2011-11-01
1   2011-11-02
2   2011-11-03
dtype: datetime64[ns]

如果偏移类直接映射到一个TimedeltaDayHour, MinuteSecondMicroMilliNano),它可以被精确地用于像Timedelta-参见 Timedelta部更多的例子。

In [148]: s - Day(2)
Out[148]: 
0   2011-12-30
1   2011-12-31
2   2012-01-01
dtype: datetime64[ns]

In [149]: td = s - pd.Series(pd.date_range('2011-12-29', '2011-12-31'))

In [150]: td
Out[150]: 
0   3 days
1   3 days
2   3 days
dtype: timedelta64[ns]

In [151]: td + Minute(15)
Out[151]: 
0   3 days 00:15:00
1   3 days 00:15:00
2   3 days 00:15:00
dtype: timedelta64[ns]

请注意,某些偏移(例如BQuarterEnd)没有矢量化实现。他们仍然可以使用,但可能会计算得更慢,并将显示PerformanceWarning

In [152]: rng + BQuarterEnd()
Out[152]: DatetimeIndex(['2012-03-30', '2012-03-30', '2012-03-30'], dtype='datetime64[ns]', freq='D')

 

定制营业日

CDayCustomBusinessDay类提供的参数 BusinessDay可用于创建定制的工作日日历占当地的节假日和周末地方惯例类。

作为一个有趣的例子,让我们看一下观察周五周六周末的埃及。

In [153]: from pandas.tseries.offsets import CustomBusinessDay

In [154]: weekmask_egypt = 'Sun Mon Tue Wed Thu'

# 他们也观察国际劳工节所以让我们
# 加一年
In [155]: holidays = ['2012-05-01', datetime(2013, 5, 1), np.datetime64('2014-05-01')]

In [156]: bday_egypt = CustomBusinessDay(holidays=holidays, weekmask=weekmask_egypt)

In [157]: dt = datetime(2013, 4, 30)

In [158]: dt + 2 * bday_egypt
Out[158]: Timestamp('2013-05-05 00:00:00')

让我们映射到工作日名称:

In [159]: dts = pd.date_range(dt, periods=5, freq=bday_egypt)

In [160]: pd.Series(dts.weekday, dts).map(pd.Series('Mon Tue Wed Thu Fri Sat Sun'.split()))
Out[160]: 
2013-04-30    Tue
2013-05-02    Thu
2013-05-05    Sun
2013-05-06    Mon
2013-05-07    Tue
Freq: C, dtype: object

假日日历可用于提供假期列表。有关详细信息,请参阅 假日日历部分。

In [161]: from pandas.tseries.holiday import USFederalHolidayCalendar

In [162]: bday_us = CustomBusinessDay(calendar=USFederalHolidayCalendar())

# 星期五之前的星期五
In [163]: dt = datetime(2014, 1, 17)

# 星期二之后的星期二(星期一被跳过,因为这是一个假期)
In [164]: dt + bday_us
Out[164]: Timestamp('2014-01-21 00:00:00')

可以通常的方式定义尊重特定假日日历的每月偏移量。

In [165]: from pandas.tseries.offsets import CustomBusinessMonthBegin

In [166]: bmth_us = CustomBusinessMonthBegin(calendar=USFederalHolidayCalendar())

# 跳过新年
In [167]: dt = datetime(2013, 12, 17)

In [168]: dt + bmth_us
Out[168]: Timestamp('2014-01-02 00:00:00')

# 用自定义偏移定义日期索引
In [169]: pd.DatetimeIndex(start='20100101',end='20120101',freq=bmth_us)
Out[169]: 
DatetimeIndex(['2010-01-04', '2010-02-01', '2010-03-01', '2010-04-01',
               '2010-05-03', '2010-06-01', '2010-07-01', '2010-08-02',
               '2010-09-01', '2010-10-01', '2010-11-01', '2010-12-01',
               '2011-01-03', '2011-02-01', '2011-03-01', '2011-04-01',
               '2011-05-02', '2011-06-01', '2011-07-01', '2011-08-01',
               '2011-09-01', '2011-10-03', '2011-11-01', '2011-12-01'],
              dtype='datetime64[ns]', freq='CBMS')

注意:频率字符串“C”用于指示使用CustomBusinessDay DateOffset,请务必注意,由于CustomBusinessDay是参数化类型,因此CustomBusinessDay的实例可能不同,并且无法从“C”频率字符串中检测到。因此,用户需要确保在用户的应用程序中始终使用“C”频率字符串。

 

营业时间

BusinessHour类提供在营业时间表示BusinessDay,允许使用特定的开始和结束时间。

默认情况下,BusinessHour使用9:00 - 17:00作为营业时间。添加BusinessHour将按Timestamp小时频率递增。如果目标Timestamp停止营业时间,请转到下一个工作小时,然后递增。如果结果超过营业时间结束,则剩余的小时数将添加到下一个工作日。

In [170]: bh = BusinessHour()

In [171]: bh
Out[171]: <BusinessHour: BH=09:00-17:00>

# 2014-08-01 is 星期五
In [172]: pd.Timestamp('2014-08-01 10:00').weekday()
Out[172]: 4

In [173]: pd.Timestamp('2014-08-01 10:00') + bh
Out[173]: Timestamp('2014-08-01 11:00:00')

# 下面的例子类似: pd.Timestamp('2014-08-01 09:00') + bh
In [174]: pd.Timestamp('2014-08-01 08:00') + bh
Out[174]: Timestamp('2014-08-01 10:00:00')

# 如果结果是在最后的时间,那么就转到下一个工作日
In [175]: pd.Timestamp('2014-08-01 16:00') + bh
Out[175]: Timestamp('2014-08-04 09:00:00')

# 剩下的日子将在第二天添加
In [176]: pd.Timestamp('2014-08-01 16:30') + bh
Out[176]: Timestamp('2014-08-04 09:30:00')

# 增加2个营业时间
In [177]: pd.Timestamp('2014-08-01 10:00') + BusinessHour(2)
Out[177]: Timestamp('2014-08-01 12:00:00')

# 减去3个营业时间
In [178]: pd.Timestamp('2014-08-01 10:00') + BusinessHour(-3)
Out[178]: Timestamp('2014-07-31 15:00:00')

您还可以按关键字指定startend计时。参数必须是str带有hour:minute表示或datetime.time 实例的参数。指定秒,微秒和纳秒作为营业时间的结果ValueError

In [179]: bh = BusinessHour(start='11:00', end=time(20, 0))

In [180]: bh
Out[180]: <BusinessHour: BH=11:00-20:00>

In [181]: pd.Timestamp('2014-08-01 13:00') + bh
Out[181]: Timestamp('2014-08-01 14:00:00')

In [182]: pd.Timestamp('2014-08-01 09:00') + bh
Out[182]: Timestamp('2014-08-01 12:00:00')

In [183]: pd.Timestamp('2014-08-01 18:00') + bh
Out[183]: Timestamp('2014-08-01 19:00:00')

通过start时间晚于end代表午夜营业时间。在这种情况下,营业时间超过午夜并重叠到第二天。有效营业时间的区别在于它是否从有效开始BusinessDay

In [184]: bh = BusinessHour(start='17:00', end='09:00')

In [185]: bh
Out[185]: <BusinessHour: BH=17:00-09:00>

In [186]: pd.Timestamp('2014-08-01 17:00') + bh
Out[186]: Timestamp('2014-08-01 18:00:00')

In [187]: pd.Timestamp('2014-08-01 23:00') + bh
Out[187]: Timestamp('2014-08-02 00:00:00')

# 尽管2014-08-02是satu年份,
# 它是有效的,因为它从08-01(星期五)开始。
In [188]: pd.Timestamp('2014-08-02 04:00') + bh
Out[188]: Timestamp('2014-08-02 05:00:00')

# 尽管2014-08-04是星期一,
# 因为它从08-03(星期日)开始,所以它已经不在营业时间了。
In [189]: pd.Timestamp('2014-08-04 04:00') + bh
Out[189]: Timestamp('2014-08-04 18:00:00')

申请BusinessHour.rollforwardrollback营业时间将导致下一个营业时间开始或前一天结束。与其他偏移BusinessHour.rollforward 不同,可以apply根据定义输出不同的结果。

这是因为一天的营业时间结束等于第二天的营业时间开始。例如,在默认营业时间(9:00 - 17:00)下,和 之间没有间隙(0分钟)。2014-08-01 17:002014-08-04 09:00

# 这会将时间戳调整到业务小时边缘
In [190]: BusinessHour().rollback(pd.Timestamp('2014-08-02 15:00'))
Out[190]: Timestamp('2014-08-01 17:00:00')

In [191]: BusinessHour().rollforward(pd.Timestamp('2014-08-02 15:00'))
Out[191]: Timestamp('2014-08-04 09:00:00')

# 和 BusinessHour().apply(pd.Timestamp('2014-08-01 17:00'))一样.
# And it is the same as BusinessHour().apply(pd.Timestamp('2014-08-04 09:00'))
In [192]: BusinessHour().apply(pd.Timestamp('2014-08-02 15:00'))
Out[192]: Timestamp('2014-08-04 10:00:00')

# 商业日结果(供参考)
In [193]: BusinessHour().rollforward(pd.Timestamp('2014-08-02'))
Out[193]: Timestamp('2014-08-04 09:00:00')

# 和 BusinessDay().apply(pd.Timestamp('2014-08-01')) 一样
# The result is the same as rollworward because BusinessDay never overlap.
In [194]: BusinessHour().apply(pd.Timestamp('2014-08-02'))
Out[194]: Timestamp('2014-08-04 10:00:00')

BusinessHour将周六和周日视为假期。要使用任意假日,您可以使用CustomBusinessHour偏移量,如以下小节中所述。

 

自定义营业时间

版本0.18.1中的新功能。

CustomBusinessHour是的混合物BusinessHour,并CustomBusinessDay允许你指定任意假期。除了跳过指定的自定义假日外,其作用CustomBusinessHour相同BusinessHour

In [195]: from pandas.tseries.holiday import USFederalHolidayCalendar

In [196]: bhour_us = CustomBusinessHour(calendar=USFederalHolidayCalendar())

# 星期五之前的星期五
In [197]: dt = datetime(2014, 1, 17, 15)

In [198]: dt + bhour_us
Out[198]: Timestamp('2014-01-17 16:00:00')

# 星期五,在MLK Day(星期一被跳过,因为这是假日)之后的星期五
In [199]: dt + bhour_us * 2
Out[199]: Timestamp('2014-01-21 09:00:00')

您可以使用BusinessHour和支持的关键字参数CustomBusinessDay

In [200]: bhour_mon = CustomBusinessHour(start='10:00', weekmask='Tue Wed Thu Fri')

# 星期一被跳过,因为这是一个假期,营业时间从10:00开始
In [201]: dt + bhour_mon * 2
Out[201]: Timestamp('2014-01-21 10:00:00')

 

偏移别名

许多字符串别名被赋予有用的公共时间序列频率。我们将这些别名称为偏移别名

别号 描述
B 工作日频率
C 自定义工作日频率
D 日历日频率
W 每周频率
M 月末频率
SM 半月结束频率(15日和月末)
BM 营业月结束频率
CBM 自定义营业月结束频率
MS 月开始频率
SMS 半月开始频率(第1和第15)
BMS 营业月开始频率
CBMS 自定义营业月开始频率
Q 四分之一结束频率
BQ 业务季度结束频率
QS 季度开始频率
BQS 业务季开始频率
A,Y 年终频率
BA,BY 业务年度结束频率
AS,YS 年开始频率
BAS,BYS 营业年度开始频率
BH 营业时间频率
H 每小时频率
T,min 微小的频率
S 其次是频率
L,ms 毫秒
U,us 微秒
N 纳秒

 

组合别名

正如我们之前看到的,别名和偏移实例在大多数函数中都是可替换的:

In [202]: pd.date_range(start, periods=5, freq='B')
Out[202]: 
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
               '2011-01-07'],
              dtype='datetime64[ns]', freq='B')

In [203]: pd.date_range(start, periods=5, freq=BDay())
Out[203]: 
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
               '2011-01-07'],
              dtype='datetime64[ns]', freq='B')

您可以将日间和日内偏移组合在一起:

In [204]: pd.date_range(start, periods=10, freq='2h20min')
Out[204]: 
DatetimeIndex(['2011-01-01 00:00:00', '2011-01-01 02:20:00',
               '2011-01-01 04:40:00', '2011-01-01 07:00:00',
               '2011-01-01 09:20:00', '2011-01-01 11:40:00',
               '2011-01-01 14:00:00', '2011-01-01 16:20:00',
               '2011-01-01 18:40:00', '2011-01-01 21:00:00'],
              dtype='datetime64[ns]', freq='140T')

In [205]: pd.date_range(start, periods=10, freq='1D10U')
Out[205]: 
DatetimeIndex([       '2011-01-01 00:00:00', '2011-01-02 00:00:00.000010',
               '2011-01-03 00:00:00.000020', '2011-01-04 00:00:00.000030',
               '2011-01-05 00:00:00.000040', '2011-01-06 00:00:00.000050',
               '2011-01-07 00:00:00.000060', '2011-01-08 00:00:00.000070',
               '2011-01-09 00:00:00.000080', '2011-01-10 00:00:00.000090'],
              dtype='datetime64[ns]', freq='86400000010U')

 

锚定偏移

对于某些频率,您可以指定锚定后缀:

别号 描述
W-SUN 每周频率(星期日)。与'W'相同
W-MON 每周频率(星期一)
W-TUE 每周频率(星期二)
W-WED 每周频率(星期三)
W-THU 每周频率(星期四)
W-FRI 每周频率(星期五)
W-SAT 每周频率(星期六)
(B)Q(S)- DEC 季度频率,年份在12月结束。与'Q'相同
(B)Q(S)- JAN 季度频率,年份在1月结束
(B)Q(S)- FEB 季度频率,年份在2月结束
(B)Q(S)- MAR 季度频率,年份在3月结束
(B)Q(S)- APR 季度频率,年份在四月结束
(B)Q(S)- MAY 季度频率,年份在5月结束
(B)Q(S)- JUN 季度频率,年份在6月结束
(B)Q(S)- JUL 季度频率,年份在7月结束
(B)Q(S)- AUG 季度频率,年份在8月结束
(B)Q(S)- SEP 季度频率,年份在9月结束
(B)Q(S)- OCT 季度频率,年份在10月结束
(B)Q(S)- NOV 季度频率,年份在11月结束
(B)A(S)- DEC 年度频率,定于12月底。与'A'相同
(B)A(S)- JAN 年度频率,定于1月底
(B)A(S)- FEB 年度频率,定于2月底
(B)A(S)- MAR 年度频率,定于3月底
(B)A(S)- APR 年度频率,定于4月底
(B)A(S)- MAY 年度频率,锚定于5月底
(B)A(S)- JUN 年度频率,锚定于6月底
(B)A(S)- JUL 年度频率,定于7月底
(B)A(S)-AUG 年度频率,定于8月底
(B)A(S)- SEP 年度频率,定于9月底
(B)A(S)- OCT 年度频率,定于10月底
(B)A(S)- NOV 年度频率,定于11月底

这些可以被用作参数date_rangebdate_range,构造函数DatetimeIndex,以及在大熊猫各种其它时间序列相关的功能。

锚定偏移语义

对于锚定到特定频率的开始或结束这些偏移(MonthEndMonthBeginWeekEnd等),下面的规则适用于向前滚动和向后。

n不为0时,如果给定日期不在锚点上,则它会捕捉到下一个(上一个)锚点,并|n|-1向前或向后移动其他步骤。

In [206]: pd.Timestamp('2014-01-02') + MonthBegin(n=1)
Out[206]: Timestamp('2014-02-01 00:00:00')

In [207]: pd.Timestamp('2014-01-02') + MonthEnd(n=1)
Out[207]: Timestamp('2014-01-31 00:00:00')

In [208]: pd.Timestamp('2014-01-02') - MonthBegin(n=1)
Out[208]: Timestamp('2014-01-01 00:00:00')

In [209]: pd.Timestamp('2014-01-02') - MonthEnd(n=1)
Out[209]: Timestamp('2013-12-31 00:00:00')

In [210]: pd.Timestamp('2014-01-02') + MonthBegin(n=4)
Out[210]: Timestamp('2014-05-01 00:00:00')

In [211]: pd.Timestamp('2014-01-02') - MonthBegin(n=4)
Out[211]: Timestamp('2013-10-01 00:00:00')

如果给定的日期上一个锚点,它被移动|n|向前或向后点。

In [212]: pd.Timestamp('2014-01-01') + MonthBegin(n=1)
Out[212]: Timestamp('2014-02-01 00:00:00')

In [213]: pd.Timestamp('2014-01-31') + MonthEnd(n=1)
Out[213]: Timestamp('2014-02-28 00:00:00')

In [214]: pd.Timestamp('2014-01-01') - MonthBegin(n=1)
Out[214]: Timestamp('2013-12-01 00:00:00')

In [215]: pd.Timestamp('2014-01-31') - MonthEnd(n=1)
Out[215]: Timestamp('2013-12-31 00:00:00')

In [216]: pd.Timestamp('2014-01-01') + MonthBegin(n=4)
Out[216]: Timestamp('2014-05-01 00:00:00')

In [217]: pd.Timestamp('2014-01-31') - MonthBegin(n=4)
Out[217]: Timestamp('2013-10-01 00:00:00')

对于这种情况n=0,如果在锚点上没有移动日期,否则它将前滚到下一个锚点。

In [218]: pd.Timestamp('2014-01-02') + MonthBegin(n=0)
Out[218]: Timestamp('2014-02-01 00:00:00')

In [219]: pd.Timestamp('2014-01-02') + MonthEnd(n=0)
Out[219]: Timestamp('2014-01-31 00:00:00')

In [220]: pd.Timestamp('2014-01-01') + MonthBegin(n=0)
Out[220]: Timestamp('2014-01-01 00:00:00')

In [221]: pd.Timestamp('2014-01-31') + MonthEnd(n=0)
Out[221]: Timestamp('2014-01-31 00:00:00')

假期/假日日历

假日和日历提供了一种简单的方法来定义要使用的假日规则,CustomBusinessDay或者在需要预定义假日集的其他分析中。本AbstractHolidayCalendar类提供了所有必要的方法返回节假日列表,只rules需要在一个特定的假期日历类中定义。此外,start_dateend_date 属性确定生成假日的日期范围。这些应该在AbstractHolidayCalendar类上被覆盖,以使范围适用于所有日历子类。 USFederalHolidayCalendar是唯一存在的日历,主要用作开发其他日历的示例。

对于在固定日期(例如,美国阵亡将士纪念日或7月4日)发生的假期,遵守规则确定何时观察该假期是否属于周末或其他非观察日。规定的遵守规则是:

规则 描述
nearest_workday 周六到周五,周日到周一
sunday_to_monday 星期天到星期一
next_monday_or_tuesday 周六到周一和周日/周一到周二
previous_friday 星期六和星期日到上周五“
下个星期一 星期六和星期日到星期一

定义假日和假日日历的示例:

In [222]: from pandas.tseries.holiday import Holiday, USMemorialDay,\
   .....:     AbstractHolidayCalendar, nearest_workday, MO
   .....: 

In [223]: class ExampleCalendar(AbstractHolidayCalendar):
   .....:     rules = [
   .....:         USMemorialDay,
   .....:         Holiday('July 4th', month=7, day=4, observance=nearest_workday),
   .....:         Holiday('Columbus Day', month=10, day=1,
   .....:             offset=DateOffset(weekday=MO(2))), #same as 2*Week(weekday=2)
   .....:         ]
   .....: 

In [224]: cal = ExampleCalendar()

In [225]: cal.holidays(datetime(2012, 1, 1), datetime(2012, 12, 31))
Out[225]: DatetimeIndex(['2012-05-28', '2012-07-04', '2012-10-08'], dtype='datetime64[ns]', freq=None)

使用此日历,创建索引或执行偏移算术会跳过周末和假日(即阵亡将士纪念日/ 7月4日)。例如,下面使用的定义了自定义工作日偏移量ExampleCalendar。与任何其他偏移一样,它可用于创建DatetimeIndex或添加datetime 或Timestamp对象。

In [226]: from pandas.tseries.offsets import CDay

In [227]: pd.DatetimeIndex(start='7/1/2012', end='7/10/2012',
   .....:     freq=CDay(calendar=cal)).to_pydatetime()
   .....: 
Out[227]: 
array([datetime.datetime(2012, 7, 2, 0, 0),
       datetime.datetime(2012, 7, 3, 0, 0),
       datetime.datetime(2012, 7, 5, 0, 0),
       datetime.datetime(2012, 7, 6, 0, 0),
       datetime.datetime(2012, 7, 9, 0, 0),
       datetime.datetime(2012, 7, 10, 0, 0)], dtype=object)

In [228]: offset = CustomBusinessDay(calendar=cal)

In [229]: datetime(2012, 5, 25) + offset
Out[229]: Timestamp('2012-05-29 00:00:00')

In [230]: datetime(2012, 7, 3) + offset
Out[230]: Timestamp('2012-07-05 00:00:00')

In [231]: datetime(2012, 7, 3) + 2 * offset
Out[231]: Timestamp('2012-07-06 00:00:00')

In [232]: datetime(2012, 7, 6) + offset
Out[232]: Timestamp('2012-07-09 00:00:00')

范围由start_date和的end_date类属性定义AbstractHolidayCalendar。默认值如下所示。

In [233]: AbstractHolidayCalendar.start_date
Out[233]: Timestamp('1970-01-01 00:00:00')

In [234]: AbstractHolidayCalendar.end_date
Out[234]: Timestamp('2030-12-31 00:00:00')

通过将属性设置为datetime / Timestamp / string,可以覆盖这些日期。

In [235]: AbstractHolidayCalendar.start_date = datetime(2012, 1, 1)

In [236]: AbstractHolidayCalendar.end_date = datetime(2012, 12, 31)

In [237]: cal.holidays()
Out[237]: DatetimeIndex(['2012-05-28', '2012-07-04', '2012-10-08'], dtype='datetime64[ns]', freq=None)

每个日历类都可以使用get_calendar返回假日类实例的函数按名称访问。此功能将自动提供任何导入的日历类。此外,HolidayCalendarFactory 还提供了一个简单的界面来创建日历,这些日历是日历或日历与其他规则的组合。

In [238]: from pandas.tseries.holiday import get_calendar, HolidayCalendarFactory,\
   .....:     USLaborDay
   .....: 

In [239]: cal = get_calendar('ExampleCalendar')

In [240]: cal.rules
Out[240]: 
[Holiday: MemorialDay (month=5, day=31, offset=<DateOffset: weekday=MO(-1)>),
 Holiday: July 4th (month=7, day=4, observance=<function nearest_workday at 0x7f20d5b40f28>),
 Holiday: Columbus Day (month=10, day=1, offset=<DateOffset: weekday=MO(+2)>)]

In [241]: new_cal = HolidayCalendarFactory('NewExampleCalendar', cal, USLaborDay)

In [242]: new_cal.rules
Out[242]: 
[Holiday: Labor Day (month=9, day=1, offset=<DateOffset: weekday=MO(+1)>),
 Holiday: MemorialDay (month=5, day=31, offset=<DateOffset: weekday=MO(-1)>),
 Holiday: July 4th (month=7, day=4, observance=<function nearest_workday at 0x7f20d5b40f28>),
 Holiday: Columbus Day (month=10, day=1, offset=<DateOffset: weekday=MO(+2)>)]

 

时间序列相关实例方法

移位/滞后

人们可能希望在时间序列中及时地向前或向后移动滞后。用于此的方法shift()是在所有pandas对象上可用的。

In [243]: ts = ts[:5]

In [244]: ts.shift(1)
Out[244]: 
2011-01-31         NaN
2011-02-28   -1.281247
2011-03-31   -0.727707
2011-04-29   -0.121306
2011-05-31   -0.097883
Freq: BM, dtype: float64

shift方法接受一个freq参数,该参数可以接受DateOffset类或其他类似timedelta的对象,也 可以接受 偏移别名

In [245]: ts.shift(5, freq=offsets.BDay())
Out[245]: 
2011-02-07   -1.281247
2011-03-07   -0.727707
2011-04-07   -0.121306
2011-05-06   -0.097883
2011-06-07    0.695775
dtype: float64

In [246]: ts.shift(5, freq='BM')
Out[246]: 
2011-06-30   -1.281247
2011-07-29   -0.727707
2011-08-31   -0.121306
2011-09-30   -0.097883
2011-10-31    0.695775
Freq: BM, dtype: float64

而不是改变数据和索引,的取向DataFrame和 Series对象也有一个tshift()由偏移指定数目的改变了索引的所有日期的便利方法:

In [247]: ts.tshift(5, freq='D')
Out[247]: 
2011-02-05   -1.281247
2011-03-05   -0.727707
2011-04-05   -0.121306
2011-05-04   -0.097883
2011-06-05    0.695775
dtype: float64

请注意,tshift由于数据未重新排列,因此前导条目不再是NaN。

频率转换

改变频率的主要功能是asfreq() 方法。对于a DatetimeIndex,这基本上只是一个很薄但很方便的包装器,reindex() 可以生成一个date_range和调用reindex

In [248]: dr = pd.date_range('1/1/2010', periods=3, freq=3 * offsets.BDay())

In [249]: ts = pd.Series(randn(3), index=dr)

In [250]: ts
Out[250]: 
2010-01-01    0.155932
2010-01-06    1.486218
2010-01-11   -2.148675
Freq: 3B, dtype: float64

In [251]: ts.asfreq(BDay())
Out[251]: 
2010-01-01    0.155932
2010-01-04         NaN
2010-01-05         NaN
2010-01-06    1.486218
2010-01-07         NaN
2010-01-08         NaN
2010-01-11   -2.148675
Freq: B, dtype: float64

asfreq 提供了更多便利,因此您可以为频率转换后可能出现的任何间隙指定插值方法。

In [252]: ts.asfreq(BDay(), method='pad')
Out[252]: 
2010-01-01    0.155932
2010-01-04    0.155932
2010-01-05    0.155932
2010-01-06    1.486218
2010-01-07    1.486218
2010-01-08    1.486218
2010-01-11   -2.148675
Freq: B, dtype: float64

向前/向后填充

缺失数据部分中记录的相关asfreqreindex是。fillna()

转换为Python日期时间

DatetimeIndex可以datetime.datetime使用该to_pydatetime方法将其转换为Python本机对象的数组 。

 

重新采样

警告:接口.resample已在0.18.0中更改为更像groupby,因此更灵活。有关与先前版本的比较,请参阅whatsnew文档

Pandas具有简单,强大且高效的功能,用于在频率转换期间执行重采样操作(例如,将第二数据转换为5分钟数据)。这在财务应用程序中非常常见,但不仅限于此。

resample()是一个基于时间的groupby,然后是每个组的缩减方法。查看一些高级策略的烹饪书示例

从版本0.18.1开始,该resample()函数可以直接在 DataFrameGroupBy对象中使用,请参阅groupby文档

注意: .resample()类似于使用rolling()具有基于时间的偏移的操作,请参阅此处的讨论。

基础知识

In [253]: rng = pd.date_range('1/1/2012', periods=100, freq='S')

In [254]: ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)

In [255]: ts.resample('5Min').sum()
Out[255]: 
2012-01-01    25653
Freq: 5T, dtype: int64

resample功能非常灵活,允许您指定许多不同的参数来控制频率转换和重采样操作。

任何经由可用的功能调度可作为返回的对象的方法,包括summeanstdsem, maxminmedianfirstlastohlc

In [256]: ts.resample('5Min').mean()
Out[256]: 
2012-01-01    256.53
Freq: 5T, dtype: float64

In [257]: ts.resample('5Min').ohlc()
Out[257]: 
            open  high  low  close
2012-01-01   296   496    6    449

In [258]: ts.resample('5Min').max()
Out[258]: 
2012-01-01    496
Freq: 5T, dtype: int64

对于下采样,closed可以设置为“左”或“右”以指定间隔的哪一端关闭:

In [259]: ts.resample('5Min', closed='right').mean()
Out[259]: 
2011-12-31 23:55:00    296.000000
2012-01-01 00:00:00    256.131313
Freq: 5T, dtype: float64

In [260]: ts.resample('5Min', closed='left').mean()
Out[260]: 
2012-01-01    256.53
Freq: 5T, dtype: float64

参数like labelloffset用于处理结果标签。label指定结果是使用间隔的开头还是结尾标记。loffset对输出标签执行时间调整。

In [261]: ts.resample('5Min').mean() # by default label='left'
Out[261]: 
2012-01-01    256.53
Freq: 5T, dtype: float64

In [262]: ts.resample('5Min', label='left').mean()
Out[262]: 
2012-01-01    256.53
Freq: 5T, dtype: float64

In [263]: ts.resample('5Min', label='left', loffset='1s').mean()
Out[263]: 
2012-01-01 00:00:01    256.53
dtype: float64

注意:的缺省值labelclosed被“左”为除了“M”,“A”,“Q”,“BM”,“BA”,“BQ”,和“W”的所有频率偏移,所有具有“默认对'。

In [264]: rng2 = pd.date_range('1/1/2012', end='3/31/2012', freq='D')

In [265]: ts2 = pd.Series(range(len(rng2)), index=rng2)

# default: label='right', closed='right'
In [266]: ts2.resample('M').max()
Out[266]: 
2012-01-31    30
2012-02-29    59
2012-03-31    90
Freq: M, dtype: int64

# default: label='left', closed='left'
In [267]: ts2.resample('SM').max()
Out[267]: 
2011-12-31    13
2012-01-15    29
2012-01-31    44
2012-02-15    58
2012-02-29    73
2012-03-15    89
2012-03-31    90
Freq: SM-15, dtype: int64

In [268]: ts2.resample('SM', label='right', closed='right').max()
Out[268]: 
2012-01-15    14.0
2012-01-31    30.0
2012-02-15    45.0
2012-02-29    59.0
2012-03-15    74.0
2012-03-31    90.0
2012-04-15     NaN
Freq: SM-15, dtype: float64

axis参数可以设置为0或1,并允许您重新采样a的指定轴DataFrame

kind可以设置为'timestamp'或'period',以将结果索引转换为/从时间戳和时间跨度表示。默认情况下,resample 保留输入表示。

convention重新采样周期数据时可以设置为“开始”或“结束”(详情如下)。它指定低频周期如何转换为更高频率周期。

 

上采样

对于上采样,您可以指定上采样的方法,并在limit创建的间隙上插入参数:

# from secondly to every 250 milliseconds
In [269]: ts[:2].resample('250L').asfreq()
Out[269]: 
2012-01-01 00:00:00.000    296.0
2012-01-01 00:00:00.250      NaN
2012-01-01 00:00:00.500      NaN
2012-01-01 00:00:00.750      NaN
2012-01-01 00:00:01.000    199.0
Freq: 250L, dtype: float64

In [270]: ts[:2].resample('250L').ffill()
Out[270]: 
2012-01-01 00:00:00.000    296
2012-01-01 00:00:00.250    296
2012-01-01 00:00:00.500    296
2012-01-01 00:00:00.750    296
2012-01-01 00:00:01.000    199
Freq: 250L, dtype: int64

In [271]: ts[:2].resample('250L').ffill(limit=2)
Out[271]: 
2012-01-01 00:00:00.000    296.0
2012-01-01 00:00:00.250    296.0
2012-01-01 00:00:00.500    296.0
2012-01-01 00:00:00.750      NaN
2012-01-01 00:00:01.000    199.0
Freq: 250L, dtype: float64

 

稀疏重采样

稀疏时间序列相对于您要重新采样的时间量而言,您的点数要少得多。天真地对稀疏序列进行上采样可能会产生大量中间值。当你不希望使用一种方法来填补这些值,如fill_methodIS None,然后中间值将被充满NaN

由于resample是基于时间的groupby,以下是仅有效地重新采样不是全部的组的方法NaN

In [272]: rng = pd.date_range('2014-1-1', periods=100, freq='D') + pd.Timedelta('1s')

In [273]: ts = pd.Series(range(100), index=rng)

如果我们想重新采样到系列的全部范围:

In [274]: ts.resample('3T').sum()
Out[274]: 
2014-01-01 00:00:00     0
2014-01-01 00:03:00     0
2014-01-01 00:06:00     0
2014-01-01 00:09:00     0
2014-01-01 00:12:00     0
2014-01-01 00:15:00     0
2014-01-01 00:18:00     0
                       ..
2014-04-09 23:42:00     0
2014-04-09 23:45:00     0
2014-04-09 23:48:00     0
2014-04-09 23:51:00     0
2014-04-09 23:54:00     0
2014-04-09 23:57:00     0
2014-04-10 00:00:00    99
Freq: 3T, Length: 47521, dtype: int64

我们只能重新采样那些我们有积分的群组,如下所示:

In [275]: from functools import partial

In [276]: from pandas.tseries.frequencies import to_offset

In [277]: def round(t, freq):
   .....:     freq = to_offset(freq)
   .....:     return pd.Timestamp((t.value // freq.delta.value) * freq.delta.value)
   .....: 

In [278]: ts.groupby(partial(round, freq='3T')).sum()
Out[278]: 
2014-01-01     0
2014-01-02     1
2014-01-03     2
2014-01-04     3
2014-01-05     4
2014-01-06     5
2014-01-07     6
              ..
2014-04-04    93
2014-04-05    94
2014-04-06    95
2014-04-07    96
2014-04-08    97
2014-04-09    98
2014-04-10    99
Length: 100, dtype: int64

 

聚合

聚合APIgroupby API窗口函数API类似,Resampler可以选择性地重新采样a。

重新采样a DataFrame,默认情况下将对具有相同功能的所有列执行操作。

In [279]: df = pd.DataFrame(np.random.randn(1000, 3),
   .....:                   index=pd.date_range('1/1/2012', freq='S', periods=1000),
   .....:                   columns=['A', 'B', 'C'])
   .....: 

In [280]: r = df.resample('3T')

In [281]: r.mean()
Out[281]: 
                            A         B         C
2012-01-01 00:00:00 -0.038580 -0.085117 -0.024750
2012-01-01 00:03:00  0.052387 -0.061477  0.029548
2012-01-01 00:06:00  0.121377 -0.010630 -0.043691
2012-01-01 00:09:00 -0.106814 -0.053819  0.097222
2012-01-01 00:12:00  0.032560  0.080543  0.167380
2012-01-01 00:15:00  0.060486 -0.057602 -0.106213

我们可以使用标准getitem选择一个或多个特定列。

In [282]: r['A'].mean()
Out[282]: 
2012-01-01 00:00:00   -0.038580
2012-01-01 00:03:00    0.052387
2012-01-01 00:06:00    0.121377
2012-01-01 00:09:00   -0.106814
2012-01-01 00:12:00    0.032560
2012-01-01 00:15:00    0.060486
Freq: 3T, Name: A, dtype: float64

In [283]: r[['A','B']].mean()
Out[283]: 
                            A         B
2012-01-01 00:00:00 -0.038580 -0.085117
2012-01-01 00:03:00  0.052387 -0.061477
2012-01-01 00:06:00  0.121377 -0.010630
2012-01-01 00:09:00 -0.106814 -0.053819
2012-01-01 00:12:00  0.032560  0.080543
2012-01-01 00:15:00  0.060486 -0.057602

您可以传递函数的列表或字典来进行聚合,输出DataFrame

In [284]: r['A'].agg([np.sum, np.mean, np.std])
Out[284]: 
                           sum      mean       std
2012-01-01 00:00:00  -6.944481 -0.038580  0.985150
2012-01-01 00:03:00   9.429707  0.052387  1.078022
2012-01-01 00:06:00  21.847876  0.121377  0.996365
2012-01-01 00:09:00 -19.226593 -0.106814  0.914070
2012-01-01 00:12:00   5.860874  0.032560  1.100055
2012-01-01 00:15:00   6.048588  0.060486  1.001532

在重新采样时DataFrame,您可以传递要应用于每个列的函数列表,从而生成具有分层索引的聚合结果:

In [285]: r.agg([np.sum, np.mean])
Out[285]: 
                             A                    B                    C          
                           sum      mean        sum      mean        sum      mean
2012-01-01 00:00:00  -6.944481 -0.038580 -15.320993 -0.085117  -4.454941 -0.024750
2012-01-01 00:03:00   9.429707  0.052387 -11.065916 -0.061477   5.318688  0.029548
2012-01-01 00:06:00  21.847876  0.121377  -1.913420 -0.010630  -7.864429 -0.043691
2012-01-01 00:09:00 -19.226593 -0.106814  -9.687468 -0.053819  17.499920  0.097222
2012-01-01 00:12:00   5.860874  0.032560  14.497725  0.080543  30.128432  0.167380
2012-01-01 00:15:00   6.048588  0.060486  -5.760208 -0.057602 -10.621260 -0.106213

通过将dict传递给aggregate您可以将不同的聚合应用于以下列DataFrame

In [286]: r.agg({'A' : np.sum,
   .....:        'B' : lambda x: np.std(x, ddof=1)})
   .....: 
Out[286]: 
                             A         B
2012-01-01 00:00:00  -6.944481  1.087752
2012-01-01 00:03:00   9.429707  1.014552
2012-01-01 00:06:00  21.847876  0.954588
2012-01-01 00:09:00 -19.226593  1.027990
2012-01-01 00:12:00   5.860874  1.021503
2012-01-01 00:15:00   6.048588  1.004984

函数名称也可以是字符串。为了使字符串有效,必须在重新采样的对象上实现:

In [287]: r.agg({'A' : 'sum', 'B' : 'std'})
Out[287]: 
                             A         B
2012-01-01 00:00:00  -6.944481  1.087752
2012-01-01 00:03:00   9.429707  1.014552
2012-01-01 00:06:00  21.847876  0.954588
2012-01-01 00:09:00 -19.226593  1.027990
2012-01-01 00:12:00   5.860874  1.021503
2012-01-01 00:15:00   6.048588  1.004984

此外,您还可以分别为每列指定多个聚合函数。

In [288]: r.agg({'A' : ['sum','std'], 'B' : ['mean','std'] })
Out[288]: 
                             A                   B          
                           sum       std      mean       std
2012-01-01 00:00:00  -6.944481  0.985150 -0.085117  1.087752
2012-01-01 00:03:00   9.429707  1.078022 -0.061477  1.014552
2012-01-01 00:06:00  21.847876  0.996365 -0.010630  0.954588
2012-01-01 00:09:00 -19.226593  0.914070 -0.053819  1.027990
2012-01-01 00:12:00   5.860874  1.100055  0.080543  1.021503
2012-01-01 00:15:00   6.048588  1.001532 -0.057602  1.004984

如果a DataFrame没有datetimelike索引,而是想要根据框架中的datetimelike列重新取样,则可以将其传递给 on关键字。

In [289]: df = pd.DataFrame({'date': pd.date_range('2015-01-01', freq='W', periods=5),
   .....:                    'a': np.arange(5)},
   .....:                   index=pd.MultiIndex.from_arrays([
   .....:                            [1,2,3,4,5],
   .....:                            pd.date_range('2015-01-01', freq='W', periods=5)],
   .....:                        names=['v','d']))
   .....: 

In [290]: df
Out[290]: 
                   date  a
v d                       
1 2015-01-04 2015-01-04  0
2 2015-01-11 2015-01-11  1
3 2015-01-18 2015-01-18  2
4 2015-01-25 2015-01-25  3
5 2015-02-01 2015-02-01  4

In [291]: df.resample('M', on='date').sum()
Out[291]: 
            a
date         
2015-01-31  6
2015-02-28  4

同样,如果您希望按日期时间级别重新采样,则MultiIndex可以将其名称或位置传递给 level关键字。

In [292]: df.resample('M', level='d').sum()
Out[292]: 
            a
d            
2015-01-31  6
2015-02-28  4

 

时间跨度表示

规则的时间间隔由Periodpandas中的Period对象表示,而对象序列在a中收集PeriodIndex,可以使用便利函数创建period_range

周期(时间移动步长)*

Period表示时间跨度(例如,一天,一个月,四分之一等)。您可以freq使用下面的频率别名通过关键字指定范围。因为freq代表一个跨度Period,它不能像“-3D”那样是负面的。

In [293]: pd.Period('2012', freq='A-DEC')
Out[293]: Period('2012', 'A-DEC')

In [294]: pd.Period('2012-1-1', freq='D')
Out[294]: Period('2012-01-01', 'D')

In [295]: pd.Period('2012-1-1 19:00', freq='H')
Out[295]: Period('2012-01-01 19:00', 'H')

In [296]: pd.Period('2012-1-1 19:00', freq='5H')
Out[296]: Period('2012-01-01 19:00', '5H')

从周期中加上和减去整数会使周期按其自身的频率移动。Period不同freq(span)之间不允许算术运算。

In [297]: p = pd.Period('2012', freq='A-DEC')

In [298]: p + 1
Out[298]: Period('2013', 'A-DEC')

In [299]: p - 3
Out[299]: Period('2009', 'A-DEC')

In [300]: p = pd.Period('2012-01', freq='2M')

In [301]: p + 2
Out[301]: Period('2012-05', '2M')

In [302]: p - 1
Out[302]: Period('2011-11', '2M')

In [303]: p == pd.Period('2012-01', freq='3M')
---------------------------------------------------------------------------
IncompatibleFrequency                     Traceback (most recent call last)
<ipython-input-303-4b67dc0b596c> in <module>()
----> 1 p == pd.Period('2012-01', freq='3M')

/pandas/pandas/_libs/tslibs/period.pyx in pandas._libs.tslibs.period._Period.__richcmp__()

IncompatibleFrequency: Input has different freq=3M from Period(freq=2M)

如果Period频率是每天或更高(DHTSLUN),offsetstimedelta式的,可以添加,如果结果可以具有相同频率。否则,ValueError将被提出。

In [304]: p = pd.Period('2014-07-01 09:00', freq='H')

In [305]: p + Hour(2)
Out[305]: Period('2014-07-01 11:00', 'H')

In [306]: p + timedelta(minutes=120)
Out[306]: Period('2014-07-01 11:00', 'H')

In [307]: p + np.timedelta64(7200, 's')
Out[307]: Period('2014-07-01 11:00', 'H')
In [1]: p + Minute(5)
Traceback
   ...
ValueError: Input has different freq from Period(freq=H)

如果Period有其他频率,则只能offsets添加相同的频率。否则,ValueError将被提出。

In [308]: p = pd.Period('2014-07', freq='M')

In [309]: p + MonthEnd(3)
Out[309]: Period('2014-10', 'M')
In [1]: p + MonthBegin(3)
Traceback
   ...
ValueError: Input has different freq from Period(freq=M)

获取Period具有相同频率的实例的差异将返回它们之间的频率单位数:

In [310]: pd.Period('2012', freq='A-DEC') - pd.Period('2002', freq='A-DEC')
Out[310]: 10

 

PeriodIndex和period_range 

Period可以在a中收集常规的对象序列,可以PeriodIndex使用period_range便利函数构建:

In [311]: prng = pd.period_range('1/1/2011', '1/1/2012', freq='M')

In [312]: prng
Out[312]: 
PeriodIndex(['2011-01', '2011-02', '2011-03', '2011-04', '2011-05', '2011-06',
             '2011-07', '2011-08', '2011-09', '2011-10', '2011-11', '2011-12',
             '2012-01'],
            dtype='period[M]', freq='M')

PeriodIndex构造也可以直接使用:

In [313]: pd.PeriodIndex(['2011-1', '2011-2', '2011-3'], freq='M')
Out[313]: PeriodIndex(['2011-01', '2011-02', '2011-03'], dtype='period[M]', freq='M')

通过乘法频率输出,其序列Period乘以跨度。

In [314]: pd.PeriodIndex(start='2014-01', freq='3M', periods=4)
Out[314]: PeriodIndex(['2014-01', '2014-04', '2014-07', '2014-10'], dtype='period[3M]', freq='3M')

如果start或者endPeriod对象,它们将被用作锚端点一个PeriodIndex与频率相匹配,所述的 PeriodIndex构造。

In [315]: pd.PeriodIndex(start=pd.Period('2017Q1', freq='Q'),
   .....:                end=pd.Period('2017Q2', freq='Q'), freq='M')
   .....: 
Out[315]: PeriodIndex(['2017-03', '2017-04', '2017-05', '2017-06'], dtype='period[M]', freq='M')

就像DatetimeIndex,a PeriodIndex也可以用来索引pandas对象:

In [316]: ps = pd.Series(np.random.randn(len(prng)), prng)

In [317]: ps
Out[317]: 
2011-01    0.258318
2011-02   -2.503700
2011-03   -0.303053
2011-04    0.270509
2011-05    1.004841
2011-06   -0.129044
2011-07   -1.406335
2011-08   -1.310412
2011-09    0.769439
2011-10   -0.542325
2011-11    2.010541
2011-12    1.001558
2012-01   -0.087453
Freq: M, dtype: float64

PeriodIndex使用相同的规则支持加法和减法Period

In [318]: idx = pd.period_range('2014-07-01 09:00', periods=5, freq='H')

In [319]: idx
Out[319]: 
PeriodIndex(['2014-07-01 09:00', '2014-07-01 10:00', '2014-07-01 11:00',
             '2014-07-01 12:00', '2014-07-01 13:00'],
            dtype='period[H]', freq='H')

In [320]: idx + Hour(2)
Out[320]: 
PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
             '2014-07-01 14:00', '2014-07-01 15:00'],
            dtype='period[H]', freq='H')

In [321]: idx = pd.period_range('2014-07', periods=5, freq='M')

In [322]: idx
Out[322]: PeriodIndex(['2014-07', '2014-08', '2014-09', '2014-10', '2014-11'], dtype='period[M]', freq='M')

In [323]: idx + MonthEnd(3)
Out[323]: PeriodIndex(['2014-10', '2014-11', '2014-12', '2015-01', '2015-02'], dtype='period[M]', freq='M')

PeriodIndex有自己的dtype命名period,请参考Period Dtypes

 

Period Dtypes

版本0.19.0中的新功能。

PeriodIndex有一个自定义的period dtype。这是一个类似于时区感知的dtype()的pandas扩展dtype.datetime64[ns,tz]

periodD型细胞保持freq属性和表示与 period[freq]period[D]period[M]使用频率字符串

In [324]: pi = pd.period_range('2016-01-01', periods=3, freq='M')

In [325]: pi
Out[325]: PeriodIndex(['2016-01', '2016-02', '2016-03'], dtype='period[M]', freq='M')

In [326]: pi.dtype
Out[326]: period[M]

periodD型可以使用.astype(...)。它允许一个改变 freq一个的PeriodIndex.asfreq(),并转换 DatetimeIndexPeriodIndex喜欢to_period()

# change monthly freq to daily freq
In [327]: pi.astype('period[D]')
Out[327]: PeriodIndex(['2016-01-31', '2016-02-29', '2016-03-31'], dtype='period[D]', freq='D')

# convert to DatetimeIndex
In [328]: pi.astype('datetime64[ns]')
Out[328]: DatetimeIndex(['2016-01-01', '2016-02-01', '2016-03-01'], dtype='datetime64[ns]', freq='MS')

# convert to PeriodIndex
In [329]: dti = pd.date_range('2011-01-01', freq='M', periods=3)

In [330]: dti
Out[330]: DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31'], dtype='datetime64[ns]', freq='M')

In [331]: dti.astype('period[M]')
Out[331]: PeriodIndex(['2011-01', '2011-02', '2011-03'], dtype='period[M]', freq='M')

 

PeriodIndex部分字符串索引

您可以在日期和字符串传递到SeriesDataFramePeriodIndex在相同的方式DatetimeIndex。有关详细信息,请参阅DatetimeIndex部分字符串索引

In [332]: ps['2011-01']
Out[332]: 0.25831819727391592

In [333]: ps[datetime(2011, 12, 25):]
Out[333]: 
2011-12    1.001558
2012-01   -0.087453
Freq: M, dtype: float64

In [334]: ps['10/31/2011':'12/31/2011']
Out[334]: 
2011-10   -0.542325
2011-11    2.010541
2011-12    1.001558
Freq: M, dtype: float64

传递表示频率较低的字符串会PeriodIndex返回部分切片数据。

In [335]: ps['2011']
Out[335]: 
2011-01    0.258318
2011-02   -2.503700
2011-03   -0.303053
2011-04    0.270509
2011-05    1.004841
2011-06   -0.129044
2011-07   -1.406335
2011-08   -1.310412
2011-09    0.769439
2011-10   -0.542325
2011-11    2.010541
2011-12    1.001558
Freq: M, dtype: float64

In [336]: dfp = pd.DataFrame(np.random.randn(600,1),
   .....:                    columns=['A'],
   .....:                    index=pd.period_range('2013-01-01 9:00', periods=600, freq='T'))
   .....: 

In [337]: dfp
Out[337]: 
                         A
2013-01-01 09:00  0.005210
2013-01-01 09:01 -0.014385
2013-01-01 09:02 -0.212404
2013-01-01 09:03 -1.227760
2013-01-01 09:04 -0.809722
2013-01-01 09:05 -1.719723
2013-01-01 09:06 -0.808486
...                    ...
2013-01-01 18:53 -0.783098
2013-01-01 18:54  0.755005
2013-01-01 18:55 -1.116732
2013-01-01 18:56 -0.940692
2013-01-01 18:57  0.228536
2013-01-01 18:58  0.109472
2013-01-01 18:59  0.235414

[600 rows x 1 columns]

In [338]: dfp['2013-01-01 10H']
Out[338]: 
                         A
2013-01-01 10:00 -0.148998
2013-01-01 10:01  2.154810
2013-01-01 10:02 -1.605646
2013-01-01 10:03  0.021024
2013-01-01 10:04 -0.623737
2013-01-01 10:05  1.451612
2013-01-01 10:06  1.062463
...                    ...
2013-01-01 10:53  0.273119
2013-01-01 10:54 -0.994071
2013-01-01 10:55 -1.222179
2013-01-01 10:56 -1.167118
2013-01-01 10:57  0.262822
2013-01-01 10:58 -0.283786
2013-01-01 10:59  1.190726

[60 rows x 1 columns]

与此一样DatetimeIndex,端点将包含在结果中。以下示例将数据从10:00开始切换到11:59。

In [339]: dfp['2013-01-01 10H':'2013-01-01 11H']
Out[339]: 
                         A
2013-01-01 10:00 -0.148998
2013-01-01 10:01  2.154810
2013-01-01 10:02 -1.605646
2013-01-01 10:03  0.021024
2013-01-01 10:04 -0.623737
2013-01-01 10:05  1.451612
2013-01-01 10:06  1.062463
...                    ...
2013-01-01 11:53 -1.477914
2013-01-01 11:54  0.594465
2013-01-01 11:55 -0.903243
2013-01-01 11:56  1.182131
2013-01-01 11:57  0.621345
2013-01-01 11:58 -0.996113
2013-01-01 11:59 -0.191659

[120 rows x 1 columns]

 

使用PeriodIndex进行频率转换和重采样

频率PeriodPeriodIndex可以通过该asfreq 方法转换。让我们从2011财年开始,到12月结束:

In [340]: p = pd.Period('2011', freq='A-DEC')

In [341]: p
Out[341]: Period('2011', 'A-DEC')

我们可以将其转换为每月频率。使用该how参数,我们可以指定是否返回开始月份或结束月份:

In [342]: p.asfreq('M', how='start')
Out[342]: Period('2011-01', 'M')

In [343]: p.asfreq('M', how='end')
Out[343]: Period('2011-12', 'M')

短线's'和'e'是为方便起见而提供的:

In [344]: p.asfreq('M', 's')
Out[344]: Period('2011-01', 'M')

In [345]: p.asfreq('M', 'e')
Out[345]: Period('2011-12', 'M')

转换为“超级时段”(例如,年度频率是季度频率的超级时段)会自动返回包含输入时段的超级时段:

In [346]: p = pd.Period('2011-12', freq='M')

In [347]: p.asfreq('A-NOV')
Out[347]: Period('2012', 'A-NOV')

请注意,由于我们转换为11月结束的年度频率,因此2011年12月的月度实际上是2012年A-NOV期间。

具有锚定频率的周期转换对于处理经济,商业和其他领域常见的各种季度数据特别有用。许多组织定义相对于其会计年度开始和结束月份的季度。因此,2011年第一季度可能在2010年启动或数月到2011年通过固定频率,大熊猫适用于所有季度的频率Q-JAN通过Q-DEC

Q-DEC 定义常规日历季度:

In [348]: p = pd.Period('2012Q1', freq='Q-DEC')

In [349]: p.asfreq('D', 's')
Out[349]: Period('2012-01-01', 'D')

In [350]: p.asfreq('D', 'e')
Out[350]: Period('2012-03-31', 'D')

Q-MAR 定义3月份的会计年度结束:

In [351]: p = pd.Period('2011Q4', freq='Q-MAR')

In [352]: p.asfreq('D', 's')
Out[352]: Period('2011-01-01', 'D')

In [353]: p.asfreq('D', 'e')
Out[353]: Period('2011-03-31', 'D')

 

在表示之间转换(时间格式变换)*

使用以下方法将带时间戳的数据转换为PeriodIndex-ed数据to_period ,反之亦然to_timestamp

In [354]: rng = pd.date_range('1/1/2012', periods=5, freq='M')

In [355]: ts = pd.Series(np.random.randn(len(rng)), index=rng)

In [356]: ts
Out[356]: 
2012-01-31   -0.898547
2012-02-29   -1.332247
2012-03-31   -0.741645
2012-04-30    0.094321
2012-05-31   -0.438813
Freq: M, dtype: float64

In [357]: ps = ts.to_period()

In [358]: ps
Out[358]: 
2012-01   -0.898547
2012-02   -1.332247
2012-03   -0.741645
2012-04    0.094321
2012-05   -0.438813
Freq: M, dtype: float64

In [359]: ps.to_timestamp()
Out[359]: 
2012-01-01   -0.898547
2012-02-01   -1.332247
2012-03-01   -0.741645
2012-04-01    0.094321
2012-05-01   -0.438813
Freq: MS, dtype: float64

请记住,'s'和'e'可用于返回句点开头或结尾的时间戳:

In [360]: ps.to_timestamp('D', how='s')
Out[360]: 
2012-01-01   -0.898547
2012-02-01   -1.332247
2012-03-01   -0.741645
2012-04-01    0.094321
2012-05-01   -0.438813
Freq: MS, dtype: float64

在周期和时间戳之间进行转换可以使用一些方便的算术函数。在下面的示例中,我们将季度频率与11月结束的年度转换为季度结束后的月末的上午9点:

In [361]: prng = pd.period_range('1990Q1', '2000Q4', freq='Q-NOV')

In [362]: ts = pd.Series(np.random.randn(len(prng)), prng)

In [363]: ts.index = (prng.asfreq('M', 'e') + 1).asfreq('H', 's') + 9

In [364]: ts.head()
Out[364]: 
1990-03-01 09:00   -0.564874
1990-06-01 09:00   -1.426510
1990-09-01 09:00    1.295437
1990-12-01 09:00    1.124017
1991-03-01 09:00    0.840428
Freq: H, dtype: float64

 

表示超出范围的跨度

如果你有一个是外部的数据Timestamp范围,请参阅时间戳限制,那么你可以使用PeriodIndex和/或SeriesPeriods做计算。

In [365]: span = pd.period_range('1215-01-01', '1381-01-01', freq='D')

In [366]: span
Out[366]: 
PeriodIndex(['1215-01-01', '1215-01-02', '1215-01-03', '1215-01-04',
             '1215-01-05', '1215-01-06', '1215-01-07', '1215-01-08',
             '1215-01-09', '1215-01-10',
             ...
             '1380-12-23', '1380-12-24', '1380-12-25', '1380-12-26',
             '1380-12-27', '1380-12-28', '1380-12-29', '1380-12-30',
             '1380-12-31', '1381-01-01'],
            dtype='period[D]', length=60632, freq='D')

int64基于YYYYMMDD的表示转换。

In [367]: s = pd.Series([20121231, 20141130, 99991231])

In [368]: s
Out[368]: 
0    20121231
1    20141130
2    99991231
dtype: int64

In [369]: def conv(x):
   .....:     return pd.Period(year = x // 10000, month = x//100 % 100, day = x%100, freq='D')
   .....: 

In [370]: s.apply(conv)
Out[370]: 
0   2012-12-31
1   2014-11-30
2   9999-12-31
dtype: object

In [371]: s.apply(conv)[2]
Out[371]: Period('9999-12-31', 'D')

这些可以很容易地转换为PeriodIndex

In [372]: span = pd.PeriodIndex(s.apply(conv))

In [373]: span
Out[373]: PeriodIndex(['2012-12-31', '2014-11-30', '9999-12-31'], dtype='period[D]', freq='D')

 

 

时区处理

....

 

参考:http://pandas.pydata.org/pandas-docs/stable/timeseries.html

 

 

相关标签: pandas 日期处理