1满哪、日期和時間數(shù)據(jù)類型及工具
Python標(biāo)準(zhǔn)庫中包含用于日期和時間的數(shù)據(jù)類型婿斥,而且還有日歷方面的功能,我們主要會用到datetime哨鸭、time和calendar模塊民宿,datetime.datetime是用的最多的數(shù)據(jù)類型。
from datetime import datetime
now = datetime.now()
now
#datetime.datetime(2017, 10, 9, 18, 17, 27, 413058)
now.year,now.month,now.day
#(2017, 10, 9)
datetime以毫秒形式存儲日期和時間像鸡,datetime.timedelta表示兩個datetime對象之間的時間差.
delta = datetime(2011,1,7) - datetime(2008,6,24,8,15)
delta.days,delta.seconds
#(926, 56700)
可以給datetime對象加上或者減去一個或多個timedelta活鹰,會產(chǎn)生一個新對象:
from datetime import timedelta
start = datetime(2011,1,7)
start - 2 * timedelta(12)
#datetime.datetime(2010, 12, 14, 0, 0)
利用str或者strftime方法,datetime對象和pandas的Timestamp對象可以被格式化為字符串:
stamp = datetime(2011,1,3)
str(stamp)
#'2011-01-03 00:00:00'
stamp.strftime('%Y-%m-%d')
#'2011-01-03'
datetime.strptime也可以用這些格式化編碼將字符串轉(zhuǎn)化為日期:
value = '2011-01-03'
datetime.strptime(value,'%Y-%m-%d')
#datetime.datetime(2011, 1, 3, 0, 0)
datetime.strptime是通過已知格式進(jìn)行日期解析的最佳方式只估,但是每次都要編寫格式定義很麻煩志群,尤其是對于一些常見的日期格式,這種情況下蛔钙,可以用dateutil這個第三方包中的parser.parse方法,dateutil可以解析幾乎所有人類能夠理解的日期表示形式:
from dateutil.parser import parse
parse('2011-01-03')
#datetime.datetime(2011, 1, 3, 0, 0)
parse('Jan 31,1997 10:45 PM')
#datetime.datetime(2017, 1, 31, 22, 45)
在國際通用格式中锌云,日通常出現(xiàn)在月的前面,傳入dayfirst=True即可:
parse('6/12/2011',dayfirst=True)
#datetime.datetime(2011, 12, 6, 0, 0)
pandas通常是用于處理成組日期的吁脱,不管這些日期是DataFrame的軸索引還是列桑涎,to_datetime方法可以解析多種不同的日期表示形式。
datestrs = ['7/6/2011','8/6/2011']
pd.to_datetime(datestrs)
#DatetimeIndex(['2011-07-06', '2011-08-06'], dtype='datetime64[ns]', freq=None)
to_datetime可以處理缺失值兼贡,NAT是pandas中時間戳數(shù)據(jù)的NA值:
pd.to_datetime(datestrs+[None])
#DatetimeIndex(['2011-07-06', '2011-08-06', 'NaT'], dtype='datetime64[ns]', freq=None)
2攻冷、時間序列基礎(chǔ)
pandas最基本的時間序列類型就是以時間戳為索引的Series:
from datetime import datetime
dates = [datetime(2011,1,2),datetime(2011,1,5),datetime(2011,1,7),datetime(2011,1,8),datetime(2011,1,10),datetime(2011,1,12)]
ts = pd.Series(np.random.randn(6),index=dates)
ts
#輸出
2011-01-02 -0.881964
2011-01-05 -0.554943
2011-01-07 -1.111905
2011-01-08 -0.941412
2011-01-10 -2.492096
2011-01-12 -1.871858
dtype: float64
這里的Series索引不是普通的索引,而是DatetimeIndex遍希,而ts變?yōu)榱艘粋€TimeSeries,同時等曼,可以看到,pandas用Numpy的datetime64數(shù)據(jù)類型以納秒形式存儲時間戳孵班。
ts.index
#輸出
DatetimeIndex(['2011-01-02', '2011-01-05', '2011-01-07', '2011-01-08',
'2011-01-10', '2011-01-12'],
dtype='datetime64[ns]', freq=None)
跟其他Series一樣涉兽,不同索引的時間序列之間的算數(shù)運(yùn)算會自動對齊:
ts + ts[::2]
#輸出
2011-01-02 -1.763929
2011-01-05 NaN
2011-01-07 -2.223810
2011-01-08 NaN
2011-01-10 -4.984192
2011-01-12 NaN
dtype: float64
DateTimeIndex中的各個標(biāo)量值是pandas的Timestamp對象.
由于TimeSeries是Series的一個子類,所以在索引以及數(shù)據(jù)選曲方面他們的行為是一樣的篙程,但是我們還可以傳入一個可以被解釋為日期的字符串來進(jìn)行索引:
ts['1/10/2011']
#-2.4920958699660636
ts['20110110']
#-2.4920958699660636
對于較長的時間序列枷畏,只需傳入年或年月即可輕松選取數(shù)據(jù)的切片:
longer_ts = pd.Series(np.random.randn(1000),index=pd.date_range('1/1/2000',periods=1000))
longer_ts['2001']
#輸出
2001-01-01 0.430658
2001-01-02 0.238326
2001-01-03 0.742078
2001-01-04 2.026365
2001-01-05 1.119718
2001-01-06 0.051642
2001-01-07 -0.948585
2001-01-08 0.088678
2001-01-09 -0.093978
2001-01-10 -0.452213
2001-01-11 0.194490
2001-01-12 -0.791522
2001-01-13 0.994300
2001-01-14 -0.466681
2001-01-15 -0.104991
2001-01-16 0.398028
2001-01-17 -0.174210
2001-01-18 0.061167
2001-01-19 0.338023
2001-01-20 0.786561
2001-01-21 0.433504
2001-01-22 -0.097737
2001-01-23 1.651351
2001-01-24 -1.620065
2001-01-25 -1.369003
2001-01-26 -0.789305
2001-01-27 -0.770117
2001-01-28 -1.190250
2001-01-29 -0.457968
2001-01-30 1.594643
...
2001-12-02 0.022856
2001-12-03 -1.074076
2001-12-04 -0.342918
2001-12-05 0.736527
2001-12-06 0.192286
2001-12-07 0.020938
2001-12-08 1.494041
2001-12-09 0.848802
2001-12-10 0.023913
2001-12-11 0.164936
2001-12-12 0.427615
2001-12-13 -0.067649
2001-12-14 0.779254
2001-12-15 -0.753810
2001-12-16 0.950142
2001-12-17 1.494037
2001-12-18 0.134798
2001-12-19 -0.019051
2001-12-20 1.171783
2001-12-21 0.253665
2001-12-22 0.634205
2001-12-23 0.372734
2001-12-24 -0.382349
2001-12-25 0.023428
2001-12-26 0.273047
2001-12-27 -1.312320
2001-12-28 -0.431074
2001-12-29 -1.501706
2001-12-30 1.185465
2001-12-31 -0.452883
Freq: D, Length: 365, dtype: float64
longer_ts['2001-05']
#輸出
2001-05-01 -0.903594
2001-05-02 -0.549671
2001-05-03 1.196419
2001-05-04 -0.965646
2001-05-05 -1.193606
2001-05-06 -0.762428
2001-05-07 0.216929
2001-05-08 -1.177503
2001-05-09 0.282163
2001-05-10 -0.938378
2001-05-11 0.200773
2001-05-12 0.723701
2001-05-13 -1.172896
2001-05-14 1.504694
2001-05-15 0.355133
2001-05-16 0.049116
2001-05-17 0.218060
2001-05-18 -0.513406
2001-05-19 -0.791606
2001-05-20 -1.703427
2001-05-21 -1.012035
2001-05-22 1.206804
2001-05-23 -0.345615
2001-05-24 1.813632
2001-05-25 -0.731229
2001-05-26 2.079715
2001-05-27 -1.140633
2001-05-28 1.356075
2001-05-29 1.644058
2001-05-30 -1.785124
2001-05-31 1.773346
Freq: D, dtype: float64
通過日期進(jìn)行切片的方式只對規(guī)則Series有效:
ts[datetime(2011,1,7):]
#輸出
2011-01-07 -1.111905
2011-01-08 -0.941412
2011-01-10 -2.492096
2011-01-12 -1.871858
dtype: float64
ts['1/6/2011':'1/11/2011']
#輸出
2011-01-07 -1.111905
2011-01-08 -0.941412
2011-01-10 -2.492096
dtype: float64
還有一個等價的實例方法也可以截取兩個日期之間的TimeSeries:
ts.truncate(after='1/9/2011')
#輸出
2011-01-02 -0.881964
2011-01-05 -0.554943
2011-01-07 -1.111905
2011-01-08 -0.941412
dtype: float64
DataFrame也同樣適用上面的規(guī)則
dates = pd.date_range('1/1/2000',periods=100,freq='W-WED')
long_df = pd.DataFrame(np.random.randn(100,4),index=dates,columns=['Colorado','Texas','New York','Ohio'])
long_df.loc['2001-5']
pandas中的時間序列一般被認(rèn)為是不規(guī)則的,也就是說虱饿,沒有固定的頻率拥诡,對于大部分程序而言,這是無所謂的氮发,但是渴肉,他常常需要以某種相對固定的頻率進(jìn)行分析,比如每月爽冕,每日仇祭,每15min等。pandas有一套標(biāo)準(zhǔn)時間序列頻率以及用于重采樣颈畸,頻率推斷乌奇,生成固定頻率日期范圍的工具.
例如没讲,我們可以將之前的時間序列轉(zhuǎn)換為一個具有固定頻率(每日)的時間序列,只需調(diào)用resample即可.返回DatetimeIndexResampler礁苗,獲取值使用asfreq():
ts1 = ts.resample('D').asfreq()
ts1
#輸出
2011-01-02 -0.881964
2011-01-03 NaN
2011-01-04 NaN
2011-01-05 -0.554943
2011-01-06 NaN
2011-01-07 -1.111905
2011-01-08 -0.941412
2011-01-09 NaN
2011-01-10 -2.492096
2011-01-11 NaN
2011-01-12 -1.871858
Freq: D, dtype: float64
生成日期范圍使用date_range函數(shù)
index = pd.date_range('4/1/2012','6/1/2012')
index
#輸出
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')
默認(rèn)情況下爬凑,date_range會產(chǎn)生按天計算的時間點(diǎn),如果只傳入起始或結(jié)束日期试伙,那就還得傳入一個表示一段時間的數(shù)字:
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')
如果你不想按天生成數(shù)據(jù)嘁信,想要按照一定的頻率生成,我們傳入freq參數(shù)即可.如想按5小時生成數(shù)據(jù):
pd.date_range(end='4/1/2012',periods=20,freq='5H')
#輸出
DatetimeIndex(['2012-03-28 01:00:00', '2012-03-28 06:00:00',
'2012-03-28 11:00:00', '2012-03-28 16:00:00',
'2012-03-28 21:00:00', '2012-03-29 02:00:00',
'2012-03-29 07:00:00', '2012-03-29 12:00:00',
'2012-03-29 17:00:00', '2012-03-29 22:00:00',
'2012-03-30 03:00:00', '2012-03-30 08:00:00',
'2012-03-30 13:00:00', '2012-03-30 18:00:00',
'2012-03-30 23:00:00', '2012-03-31 04:00:00',
'2012-03-31 09:00:00', '2012-03-31 14:00:00',
'2012-03-31 19:00:00', '2012-04-01 00:00:00'],
dtype='datetime64[ns]', freq='5H')
如果你想生成一個由每月最后一個工作日組成的日期索引疏叨,可以使用BM頻率:
pd.date_range('1/1/2000','12/1/2000',freq='BM')
#輸出
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28',
'2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',
'2000-09-29', '2000-10-31', '2000-11-30'],
dtype='datetime64[ns]', freq='BM')
date_range默認(rèn)會保留起始和結(jié)束的時間戳的時間信息潘靖,但是如果我們想產(chǎn)生一組規(guī)范化到午夜的時間戳,normalize選項可以實現(xiàn)這個功能:
pd.date_range('5/2/2012 12:56:31',periods=5)
#輸出
DatetimeIndex(['2012-05-02 12:56:31', '2012-05-03 12:56:31',
'2012-05-04 12:56:31', '2012-05-05 12:56:31',
'2012-05-06 12:56:31'],
dtype='datetime64[ns]', freq='D')
pd.date_range('5/2/2012 12:56:31',periods=5,normalize=True)
#輸出
Out[46]:
DatetimeIndex(['2012-05-02', '2012-05-03', '2012-05-04', '2012-05-05',
'2012-05-06'],
dtype='datetime64[ns]', freq='D')
WOM(week of Month)是一種非常實用的頻率類考廉,它以WOM開頭秘豹,它使你能獲得諸如每月第三個星期五之類的日期:
rng = pd.date_range('1/1/2012','9/1/2012',freq='WOM-3FRI')
rng
#輸出
DatetimeIndex(['2012-01-20', '2012-02-17', '2012-03-16', '2012-04-20',
'2012-05-18', '2012-06-15', '2012-07-20', '2012-08-17'],
dtype='datetime64[ns]', freq='WOM-3FRI')