datetime数据类型
简介
python自带的datetime模块包含了一些处理时间的数据类型和函数。其中,datetime模块中包含的数据类型如下:
date:存储由年、月、日组成的日期
time:存储由小时、分钟、秒、微秒组成的时间
datetime:同时存储date和time
timedelta:表示两个datetime之间的差值
下面为一些使用示例:
1 now=datetime.datetime.now()
datetime.datetime(2021, 1, 9, 15, 47, 27, 207732)
1 2 3 4 5 6 7 print (now.year, now.month, now.day, now.hour, now.minute, now.second, now.microsecond)
2021 1 9 15 47 27 207732
datetime.date(2021, 1, 9)
datetime.time(15, 47, 27, 207732)
1 delta=datetime.datetime(2011 ,1 ,7 )-datetime.datetime(2008 ,6 ,24 ,8 ,15 )
1 2 print (delta.days, delta.seconds)
926 56700
字符串与datetime的转换
一个datetime类型的变量,可以通过str或者strftime函数将其转换为字符串,例如:
'2021-01-09 15:47:27.207732'
1 now.strftime('%Y-%m-%d' )
'2021-01-09'
在上述操作中,可以使用的格式化符号包括: - %Y:4位数表示的年份 - %y:2位数表示的年份 - %m:2位数表示的月份(01至12) - %d:2位数表示的日期(01至31) - %H:24小时制小时(00至23) - %I:12小时制小时(01至12) - %M:2位数表示的分钟(00至59) - %S:秒数(00至61,60和61为了表示时间调整时的重复计秒) - %w:表示周日到周六(0至6,0为周日) - %U:表示每一年的星期数(00至53,周日作为每周的第一天,在第一个周日之前的所有天数被认为是第0周) - %W:与%U类似,但是将周一作为每周的第一天 - %z:UTC时区的偏移量,如果没有设置时区则为空 - %F:'%Y-%m-%d'格式的简写 - %D:'%m/%d/%y'格式的简写 - %a:简写的星期名称 - %A:全拼的星期名称 - %b:简写的月份名称 - %B:全拼的月份名称 - %c:输入全部的日期和时间,例如"Tue 01 May 2012 04:20:57 PM" - %p:输出时间对应的是AM或PM - %x:输出'month/day/year'格式的时间 - %X:输出'hour:min:sec'格式的时间
同时,datetime也提供了将字符串转换为datetime类型变量的函数,这一函数接收两个字符串作为参数,第一个字符串表示时间,第二个字符串表示第一个字符串对应的时间格式:
1 datetime.datetime.strptime('2011-01-03' , '%Y-%m-%d' )
datetime.datetime(2011, 1, 3, 0, 0)
也可以借助第三方库dateutil,完成字符串自动转换为datetime的操作。
1 2 from dateutil.parser import parseparse('Jan 31, 1997 10:45 PM' )
datetime.datetime(1997, 1, 31, 22, 45)
Pandas库中包含了一个to_datetime函数,可以将一个包含时间格式字符串的list转换为datetime格式的index:
1 2 3 import numpy as npimport pandas as pdpd.to_datetime(['7/6/2011' , '8/6/2011' ])
DatetimeIndex(['2011-07-06', '2011-08-06'], dtype='datetime64[ns]', freq=None)
时间序列
简介
在Pandas的数据格式中,可以使用一系列字符串或datetime类型的变量,来生成一个TimeSeries类型的变量。例:
1 ts = pd.Series(np.random.randn(6 ), index=[datetime.datetime(2011 , 1 , 2 ), datetime.datetime(2011 , 1 , 5 ), datetime.datetime(2011 , 1 , 7 ),datetime.datetime(2011 , 2 , 8 ), datetime.datetime(2011 , 1 , 10 ), datetime.datetime(2011 , 2 , 12 )])
2011-01-02 -1.516700
2011-01-05 -0.509528
2011-01-07 0.484152
2011-02-08 -1.096136
2011-01-10 0.721982
2011-02-12 -0.789547
dtype: float64
DatetimeIndex(['2011-01-02', '2011-01-05', '2011-01-07', '2011-02-08',
'2011-01-10', '2011-02-12'],
dtype='datetime64[ns]', freq=None)
index操作
如果一个DataFrame或Series使用了DatetimeIndex,那么可以使用一些特殊的index方式:
2011-01-10 0.721982
dtype: float64
2011-01-10 0.721982
dtype: float64
2011-01-02 -1.516700
2011-01-05 -0.509528
2011-01-07 0.484152
2011-02-08 -1.096136
2011-01-10 0.721982
2011-02-12 -0.789547
dtype: float64
2011-01-02 -1.516700
2011-01-05 -0.509528
2011-01-07 0.484152
2011-01-10 0.721982
dtype: float64
2011-01-07 0.484152
2011-02-08 -1.096136
2011-01-10 0.721982
2011-02-12 -0.789547
dtype: float64
时间序列的生成
Pandas中的函数data_range()函数可以生成一个时间序列。例:
1 pd.date_range('4/1/2012' , '6/1/2012' )
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20',
'2012-04-21', '2012-04-22', '2012-04-23', '2012-04-24',
'2012-04-25', '2012-04-26', '2012-04-27', '2012-04-28',
'2012-04-29', '2012-04-30', '2012-05-01', '2012-05-02',
'2012-05-03', '2012-05-04', '2012-05-05', '2012-05-06',
'2012-05-07', '2012-05-08', '2012-05-09', '2012-05-10',
'2012-05-11', '2012-05-12', '2012-05-13', '2012-05-14',
'2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18',
'2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22',
'2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26',
'2012-05-27', '2012-05-28', '2012-05-29', '2012-05-30',
'2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
1 pd.date_range(start='4/1/2012' , periods=20 )
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20'],
dtype='datetime64[ns]', freq='D')
1 pd.date_range(end='6/1/2012' , periods=20 )
DatetimeIndex(['2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16',
'2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20',
'2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24',
'2012-05-25', '2012-05-26', '2012-05-27', '2012-05-28',
'2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
1 pd.date_range('1/1/2000' , '1/3/2000 23:59' , freq='4h' )
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 04:00:00',
'2000-01-01 08:00:00', '2000-01-01 12:00:00',
'2000-01-01 16:00:00', '2000-01-01 20:00:00',
'2000-01-02 00:00:00', '2000-01-02 04:00:00',
'2000-01-02 08:00:00', '2000-01-02 12:00:00',
'2000-01-02 16:00:00', '2000-01-02 20:00:00',
'2000-01-03 00:00:00', '2000-01-03 04:00:00',
'2000-01-03 08:00:00', '2000-01-03 12:00:00',
'2000-01-03 16:00:00', '2000-01-03 20:00:00'],
dtype='datetime64[ns]', freq='4H')
freq参数中可以使用的字母符号如下但不限于:
D:日历天(包含周末)
B:工作日(不含周末)
H:每小时
T or min:每分钟
S:每秒钟
L or ms:毫秒(1/1000秒)
U:微秒
M:每个月最后一天
BM:每个月的最后一个工作日
MS:每个月的第一天
BMS:每个月的第一个工作日
W-MON,W-TUE,……:每周的周几
WOM-1MON,WOM-2MON,……:每个月的第几个周几
……
时移
shift函数可以将数据对应的时间上移或下移。例:
2011-01-02 NaN
2011-01-05 NaN
2011-01-07 -1.516700
2011-02-08 -0.509528
2011-01-10 0.484152
2011-02-12 -1.096136
dtype: float64
2011-02-28 -1.516700
2011-02-28 -0.509528
2011-02-28 0.484152
2011-03-31 -1.096136
2011-02-28 0.721982
2011-03-31 -0.789547
dtype: float64
Pandas中的时间也可以用offsets变量做修改:
1 now+3 *pd.tseries.offsets.Day()
Timestamp('2021-01-12 15:47:27.207732')
1 now+pd.tseries.offsets.MonthEnd(2 )
Timestamp('2021-02-28 15:47:27.207732')
1 pd.tseries.offsets.MonthEnd(2 ).rollback(now)
Timestamp('2020-12-31 15:47:27.207732')
时区
Python的第三方库pytz包含了时区的数据库,可以用它来设置时间的时区。使用pytz中的timezone函数,可以生成一个表示时区的变量。
1 2 import pytztz = pytz.timezone('US/Eastern' )
在默认情况下,Pandas生成的时间序列是没有时区的。如果想设置时区,需要传入额外参数tz。例:
1 pd.date_range('3/9/2012 9:30' , periods=10 , freq='D' , tz='UTC' )
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00',
'2012-03-15 09:30:00+00:00', '2012-03-16 09:30:00+00:00',
'2012-03-17 09:30:00+00:00', '2012-03-18 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
使用tz_localize函数可以将一个没有时区的时间序列转换为一个有时区的时间序列。这样,在使用tz_convert函数对这个时间序列转换时区的时候,则会指定UTC作为时区的基准。例:
1 ts_utc = ts.tz_localize('UTC' )
2011-01-02 00:00:00+00:00 -1.516700
2011-01-05 00:00:00+00:00 -0.509528
2011-01-07 00:00:00+00:00 0.484152
2011-02-08 00:00:00+00:00 -1.096136
2011-01-10 00:00:00+00:00 0.721982
2011-02-12 00:00:00+00:00 -0.789547
dtype: float64
1 ts_utc.tz_convert('US/Eastern' )
2011-01-01 19:00:00-05:00 -1.516700
2011-01-04 19:00:00-05:00 -0.509528
2011-01-06 19:00:00-05:00 0.484152
2011-02-07 19:00:00-05:00 -1.096136
2011-01-09 19:00:00-05:00 0.721982
2011-02-11 19:00:00-05:00 -0.789547
dtype: float64
当创建一个timestamp类型变量的时候,可以直接传入时区。例:
1 pd.Timestamp('2011-03-12 04:00' , tz='Europe/Moscow' )
Timestamp('2011-03-12 04:00:00+0300', tz='Europe/Moscow')
如果两个不同时区的时间序列进行合并,那么合并的结果会被自动转换为UTC时区。例如:
1 ts.tz_localize('Europe/London' )+ts.tz_localize('Asia/Shanghai' )
2011-01-01 16:00:00+00:00 NaN
2011-01-02 00:00:00+00:00 NaN
2011-01-04 16:00:00+00:00 NaN
2011-01-05 00:00:00+00:00 NaN
2011-01-06 16:00:00+00:00 NaN
2011-01-07 00:00:00+00:00 NaN
2011-01-09 16:00:00+00:00 NaN
2011-01-10 00:00:00+00:00 NaN
2011-02-07 16:00:00+00:00 NaN
2011-02-08 00:00:00+00:00 NaN
2011-02-11 16:00:00+00:00 NaN
2011-02-12 00:00:00+00:00 NaN
dtype: float64
时间周期
Period类和PeriodIndex类
Pandas中有一个period类,可以创建一个period类型的变量,对应一个时间跨度。例:
1 p = pd.Period(2007 , freq='A-DEC' )
Period('2007', 'A-DEC')
Period('2012', 'A-DEC')
1 pd.Period(2027 , freq='A-DEC' )-p
<20 * YearEnds: month=12>
使用period_range函数,可以生成一个PeriodIndex类型的变量,是一组具有规则的时间序列:
1 rng = pd.period_range('1/1/2000' , '6/30/2000' , freq='M' )
PeriodIndex(['2000-01', '2000-02', '2000-03', '2000-04', '2000-05', '2000-06'], dtype='period[M]', freq='M')
1 pd.Series(np.random.randn(6 ), index=rng)
2000-01 1.155621
2000-02 -0.949274
2000-03 1.474354
2000-04 1.653150
2000-05 0.976651
2000-06 1.849326
Freq: M, dtype: float64
1 pd.PeriodIndex(['2001Q3' , '2002Q2' , '2003Q1' ], freq='Q-DEC' )
PeriodIndex(['2001Q3', '2002Q2', '2003Q1'], dtype='period[Q-DEC]', freq='Q-DEC')
Period和PeriodIndex时间频率的转换
使用asfreq函数,可以对一个Period或PeriodIndex类型的变量转换时间频率。
1 p = pd.Period('2007' , freq='A-DEC' )
Period('2007', 'A-DEC')
1 p.asfreq('M' ,how='start' )
Period('2007-01', 'M')
Period('2008', 'A-JUN')
时间序列与时间周期的互相转换
使用to_period函数,可以把一个时间序列timestamp转换为一个时间周期PeriodIndex。在转换时,会将原来时间序列中的时间自动划分到它所在的那个时间周期内。例如:
1 2 3 rng = pd.date_range('1/1/2000' , periods=3 , freq='M' ) ts = pd.Series(np.random.randn(3 ), index=rng) pts = ts.to_period()
2000-01 1.739193
2000-02 -0.201334
2000-03 -0.076694
Freq: M, dtype: float64
1 2 pts2=ts.to_period('D' ) pts2
2000-01-31 1.739193
2000-02-29 -0.201334
2000-03-31 -0.076694
Freq: D, dtype: float64
使用to_timestamp()函数,可以将PeriodIndex转换回timestamp。例:
1 pts.to_timestamp(how='end' )
2000-01-31 23:59:59.999999999 1.739193
2000-02-29 23:59:59.999999999 -0.201334
2000-03-31 23:59:59.999999999 -0.076694
Freq: M, dtype: float64
时间序列相关的统计
以时间序列作为index的series或dataframe变量,可以调用pandas中一些相关的统计函数做一些相关的统计数据。
可以使用的相关函数包括:
rolling_count:返回移动窗口的非NaN数目
rolling_sum:计算移动窗口内的和
rolling_mean:计算移动窗口内的平均值
rolling_median:计算移动窗口内的中位数
rolling_var, rolling_std:计算移动窗口内的方差、标准差
rolling_skew, rolling_kurt:计算移动窗口内的偏度、峰度
rolling_min, rolling_max:计算移动窗口内的最值
rolling_quantile:计算移动窗口内的某个百分位数
rolling_corr, rolling_cov:计算移动窗口内的协方差和相关系数
rolling_apply:将移动窗口内的数值用到某个函数内
ewma:指数权重的移动平均
ewmvar, ewmstd:指数权重的移动方差、标准差
ewmcorr, ewmcov:指数权重的相关系数、协方差
同时,对于一个以时间序列为index的series或dataframe,可以对其调用plot函数来做图。横坐标会被自动设置为时间序列中的值。
参考
Python for Data Analysis, 2nd Edition.