注意:重要且关键章节已标星
目录
事实证明,熊猫作为处理时间序列数据的工具非常成功,特别是在财务数据分析领域。使用NumPy datetime64
和timedelta64
dtypes,我们整合了其他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_datetime ,date_range ,bdate_range ,DatetimeIndex |
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')
Timestamp
并Period
可以作为索引。名单 Timestamp
和Period
被自动强制转换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
的并不严格,因此如果无法在第一天解析日期,则会将其解析为dayfirst
False。
如果传递单个字符串to_datetime
,则返回单个字符串Timestamp
。 Timestamp
也可以接受字符串输入,但是它不接受像dayfirst
或format
那样的字符串解析选项,所以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
整数或字符串列组装成Series
的Timestamps
。
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组件的标准名称,包括:
- 要求:
year
,month
,day
- 可选:
hour
,minute
,second
,millisecond
,microsecond
,nanosecond
无效数据
默认行为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')
我们减去时期(UTC时间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_range
,bdate_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
可以很容易地使用的参数的各种组合等生成日期的范围start
,end
,periods
,和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中的新功能。
指定start
,end
和periods
将生成一系列均匀间隔的日期,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”作为频率字符串传递时才使用weekmask
和holidays
参数。支持已经扩展,bdate_range
可以使用任何自定义频率字符串。
版本0.21.0中的新功能。
bdate_range
还可以使用weekmask
和holidays
参数生成一系列自定义频率日期。仅在传递自定义频率字符串时才使用这些参数。
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对象上的
shift
andtshift
方法快速移动。DatetimeIndex
具有相同频率的重叠对象的联合非常快(对于快速数据对齐很重要)。- 通过性能,如快速访问日期字段
year
,month
等等。- 正则化功能
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
这种类型的切片将在一个工作DataFrame
用DatetimeIndex
为好。由于部分字符串选择是标签切片的一种形式,因此将包括端点。这将包括在包含日期的匹配时间:
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
部分字符串索引也适用于DataFrame
a MultiIndex
:
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
警告:但是,如果将字符串视为完全匹配,则
DataFrame
s中的选择[]
将按列而不是按行进行,请参阅索引基础知识。例如将提高为具有相同的分辨率指标,有这样的名字没有列: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 取决于句点的“准确性”,换句话说,间隔与索引的分辨率有何关联。相比之下,使用Timestamp
或datetime
对象进行索引是准确的,因为对象具有确切的含义。这些也遵循包含两个端点的语义。
这些Timestamp
和datetime
对象有确切的和,即使他们没有明确规定(他们是)。hours, minutes,
seconds
0
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 | 逻辑指示日期是否属于闰年 |
此外,如果您具有Series
datetimelike值,则可以通过访问器访问这些属性.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')
该rollforward
和rollback
方法做的正是你所期待的:
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。
这些操作(apply
,rollforward
和rollback
)保存时间(小时,分钟等)的默认信息。要重置时间,请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
偏移可与被用在Series
或DatetimeIndex
施加的偏移量的每个元素。
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]
如果偏移类直接映射到一个Timedelta
(Day
,Hour
, Minute
,Second
,Micro
,Milli
,Nano
),它可以被精确地用于像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')
定制营业日
本CDay
或CustomBusinessDay
类提供的参数 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')
您还可以按关键字指定start
和end
计时。参数必须是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.rollforward
和rollback
营业时间将导致下一个营业时间开始或前一天结束。与其他偏移BusinessHour.rollforward
不同,可以apply
根据定义输出不同的结果。
这是因为一天的营业时间结束等于第二天的营业时间开始。例如,在默认营业时间(9:00 - 17:00)下,和 之间没有间隙(0分钟)。2014-08-01 17:00
2014-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_range
,bdate_range
,构造函数DatetimeIndex
,以及在大熊猫各种其它时间序列相关的功能。
锚定偏移语义
对于锚定到特定频率的开始或结束这些偏移(MonthEnd
,MonthBegin
,WeekEnd
等),下面的规则适用于向前滚动和向后。
当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_date
和end_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
向前/向后填充
与缺失数据部分中记录的相关asfreq
和reindex
是。fillna()
转换为Python日期时间
DatetimeIndex
可以datetime.datetime
使用该to_pydatetime
方法将其转换为Python本机对象的数组 。
重新采样
警告:接口
.resample
已在0.18.0中更改为更像groupby,因此更灵活。有关与先前版本的比较,请参阅whatsnew文档。
Pandas具有简单,强大且高效的功能,用于在频率转换期间执行重采样操作(例如,将第二数据转换为5分钟数据)。这在财务应用程序中非常常见,但不仅限于此。
resample()
是一个基于时间的groupby,然后是每个组的缩减方法。查看一些高级策略的烹饪书示例。
从版本0.18.1开始,该resample()
函数可以直接在 DataFrameGroupBy
对象中使用,请参阅groupby文档。
基础知识
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
功能非常灵活,允许您指定许多不同的参数来控制频率转换和重采样操作。
任何经由可用的功能调度可作为返回的对象的方法,包括sum
,mean
,std
,sem
, max
,min
,median
,first
,last
,ohlc
:
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 label
和loffset
用于处理结果标签。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
注意:的缺省值
label
和closed
被“左”为除了“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_method
IS 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
聚合
与聚合API,groupby 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
时间跨度表示
规则的时间间隔由Period
pandas中的Period
对象表示,而对象序列在a中收集PeriodIndex
,可以使用便利函数创建period_range
。
周期(时间移动步长)*
A 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
频率是每天或更高(D
,H
,T
,S
,L
,U
,N
),offsets
和timedelta
式的,可以添加,如果结果可以具有相同频率。否则,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
或者end
是Period
对象,它们将被用作锚端点一个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]
的period
D型细胞保持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]
该period
D型可以使用.astype(...)
。它允许一个改变 freq
一个的PeriodIndex
像.asfreq()
,并转换 DatetimeIndex
到PeriodIndex
喜欢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部分字符串索引
您可以在日期和字符串传递到Series
并DataFrame
与PeriodIndex
在相同的方式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进行频率转换和重采样
频率Period
和PeriodIndex
可以通过该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
和/或Series
中Periods
做计算。
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