1. 日期和时间数据的类型及工具
import pandas as pd
import numpy as np
from datetime import datetime
now = datetime. now( )
now
datetime.datetime(2019, 8, 11, 14, 17, 29, 402021)
datetime 既存储了日期,也存储了细化到微秒的时间
now. year, now. month, now. day
(2019, 8, 11)
timedelta 表示两个 datetime 对象的时间差
delta = datetime( 2019 , 1 , 1 ) - datetime( 2018 , 8 , 8 , 10 , 10 )
print ( delta, delta. days, delta. seconds, sep= '\n' )
145 days, 13:50:00
145
49800
为 datetime 对象加上(或减去)一个 timedelta 或其整数倍来产生一个新的 datetime 对象
from datetime import timedelta
start = datetime( 2019 , 8 , 1 )
start + timedelta( 12 ) * 2
datetime.datetime(2019, 8, 25, 0, 0)
datetime 模块中的类型表格
类型
描述
date
使用公历日历存储日历日期(年月日)
time
将时间存储为小时、分钟、秒和微秒
datetime
存储日期和时间
timedelta
表示两个 datetime 值之间的差(如日、秒和微秒)
tzinfo
用于存储时区信息的基本类型
1.1 字符串与 datetime 互相转换
使用 str 方法或传递一个指定的格式给 strftime 方法来对 datetime 对象和 pandas 的 Timestamp 对象进行格式化
stamp = datetime( 2019 , 8 , 1 )
print ( str ( stamp) )
print ( stamp. strftime( '%Y-%m-%d' ) )
2019-08-01 00:00:00
2019-08-01
使用 datetime.strptime 将字符串转换为日期
value = '2019-08-01'
print ( datetime. strptime( value, '%Y-%m-%d' ) )
datestrs = [ '8/1/2019' , '8/2/2019' ]
print ( [ datetime. strptime( x, '%m/%d/%Y' ) for x in datestrs] )
2019-08-01 00:00:00
[datetime.datetime(2019, 8, 1, 0, 0), datetime.datetime(2019, 8, 2, 0, 0)]
使用 dateutil 的 parser.parse 方法解析大部分人类可理解的日期表示
from dateutil. parser import parse
print ( parse( '2019-08-01' ) )
print ( parse( 'Aug 1, 2019 10:00 PM' ) )
print ( parse( '1/8/2019' , dayfirst= True ) )
2019-08-01 00:00:00
2019-08-01 22:00:00
2019-08-01 00:00:00
使用 pandas.to_datetime 将日期表示转换为 DataFrame 的索引
datestrs = [ '2019-08-01 12:00:00' , '2019-08-02 00:00:00' ]
print ( pd. to_datetime( datestrs) )
idx = pd. to_datetime( datestrs + [ None ] )
print ( idx)
print ( pd. isnull( idx) )
DatetimeIndex(['2019-08-01 12:00:00', '2019-08-02 00:00:00'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2019-08-01 12:00:00', '2019-08-02 00:00:00', 'NaT'], dtype='datetime64[ns]', freq=None)
[False False True]
datetime 格式说明(兼容 ISO C89)(基础知识部分也有该表格)
https://blog.youkuaiyun.com/u012470887/article/details/92431590
类型
描述
%Y
四位的年份
%y
两位的年份
%m
两位的月份[01, 12]
%d
两位的天数值 [01, 31]
%H
小时值(24 小时制)[00, 23]
%I
小时值(12 小时制)[01, 12]
%M
两位的分钟值 [00, 59]
%S
秒值 [00, 61] (60, 61用于区分闰秒)
%w
星期值 [0(星期天), 6]
%U
一年中的第几个星期值 [00, 53],星期天为每周第一天,第一个星期天前一周是第0周
%W
一年中的第几个星期值 [00, 53],星期一为每周第一天,第一个星期一前一周是第0周
%z
UTC 时区偏置,格式为 +HHMM 或 -HHMM,如果是简单时区则为空
%F
%Y -%m-%d 的简写
%D
%m/%d/%y 的简写
2. 时间序列基础
pandas 中的基础时间序列种类是由时间戳索引的 Series, 在 pandas 外部则通常表示为 Python 字符串或 datetime 对象
from datetime import datetime
dates = [ datetime( 2019 , 8 , 1 ) , datetime( 2019 , 8 , 5 ) ,
datetime( 2019 , 8 , 7 ) , datetime( 2019 , 8 , 8 ) ,
datetime( 2019 , 8 , 10 ) , datetime( 2019 , 8 , 12 ) ]
ts = pd. Series( np. random. randn( 6 ) , index= dates)
ts
2019-08-01 0.468772
2019-08-05 2.333443
2019-08-07 -0.502920
2019-08-08 1.145697
2019-08-10 -0.504389
2019-08-12 -1.343926
dtype: float64
这种情况下,这些 datetime 对象可以被放入 DatetimeIndex 中
ts. index
DatetimeIndex(['2019-08-01', '2019-08-05', '2019-08-07', '2019-08-08',
'2019-08-10', '2019-08-12'],
dtype='datetime64[ns]', freq=None)
和其他 Series 一样,不同索引的时间序列之间的算术运算在日期上自动对齐
ts + ts[ : : 2 ]
2019-08-01 0.937543
2019-08-05 NaN
2019-08-07 -1.005840
2019-08-08 NaN
2019-08-10 -1.008777
2019-08-12 NaN
dtype: float64
DatetimeIndex 中的标量值是 pandas 的 Timestamp 对象
stamp = ts. index[ 0 ]
stamp
Timestamp('2019-08-01 00:00:00')
2.1 索引、选择、子集
基于标签进行索引和选择时,时间序列的行为和其他的 pandas.Series 类似
stamp = ts. index[ 2 ]
s[ stamp]
-0.5029199053879977
print ( ts[ '8/1/2019' ] )
print ( ts[ '20190801' ] )
0.46877169482728676
0.46877169482728676
对于一个长的时间序列,可以传递一个年份或一个年份和月份来选择数据的切片
longer_ts = pd. Series( np. random. randn( 1000 ) ,
index= pd. date_range( '1/1/2017' , periods= 1000 ) )
print ( longer_ts[ : 10 ] , longer_ts[ '2018' ] [ : 10 ] , longer_ts[ '2018-05' ] [ : 10 ] , sep= '\n' + '*' * 10 + '\n' )
2017-01-01 -1.000006
2017-01-02 -0.012311
2017-01-03 1.290370
2017-01-04 -1.411002
2017-01-05 -1.043768
2017-01-06 -2.026386
2017-01-07 0.923300
2017-01-08 -1.159909
2017-01-09 -0.340406
2017-01-10 -2.195334
Freq: D, dtype: float64
**********
2018-01-01 -0.614101
2018-01-02 0.034989
2018-01-03 -0.816531
2018-01-04 -0.025899
2018-01-05 1.499072
2018-01-06 -0.025201
2018-01-07 -1.936647
2018-01-08 0.748457
2018-01-09 -0.159147
2018-01-10 -1.762938
Freq: D, dtype: float64
**********
2018-05-01 1.912698
2018-05-02 -0.614768
2018-05-03 3.010737
2018-05-04 -0.828237
2018-05-05 0.866249
2018-05-06 -0.035166
2018-05-07 -1.222878
2018-05-08 0.541532
2018-05-09 1.337297
2018-05-10 -1.633647
Freq: D, dtype: float64
也可以使用 datetime 对象进行切片,由于大部分时间序列数据是按时间顺序排序的,因此可以使用不包含在时间序列中的时间戳进行切片,以执行范围查询
ts[ datetime( 2019 , 8 , 4 ) : datetime( 2019 , 8 , 10 ) ]
2019-08-05 2.333443
2019-08-07 -0.502920
2019-08-08 1.145697
2019-08-10 -0.504389
dtype: float64
使用 truncate() 方法也可以实现在两个日期间对 Series 进行切片
ts. truncate( before= '8/2/2019' , after= '8/8/2019' )
2019-08-05 2.333443
2019-08-07 -0.502920
2019-08-08 1.145697
dtype: float64
上面的操作也同样适用于 DataFrame,并在其行上进行索引
dates = pd. date_range( '1/1/2018' , periods= 100 , freq= 'W-WED' )
long_df = pd. DataFrame( np. random. randn( 100 , 4 ) ,
index= dates,
columns= [ 'Colorado' , 'Texas' , 'Nwe York' , 'Ohio' ] )
long_df[ : 10 ]
Colorado
Texas
Nwe York
Ohio
2018-01-03
-0.865582
1.623844
-0.200563
-1.166387
2018-01-10
0.441938
1.022298
-0.834719
-0.125343
2018-01-17
-0.767586
-0.434506
0.008906
-0.359749
2018-01-24
0.151662
-0.904767
-1.224332
1.169810
2018-01-31
-0.172146
-0.495993
0.841341
-0.080990
2018-02-07
0.485385
-1.327956
0.144750
0.294078
2018-02-14
-0.071519
1.098334
-0.923484
-1.466727
2018-02-21
-0.482320
-0.122691
-0.719345
-1.044682
2018-02-28
0.160908
1.044807
-0.020349
-0.426059
2018-03-07
-0.009414
0.081428
-0.523577
1.182005
long_df. loc[ '5-2018' ]
Colorado
Texas
Nwe York
Ohio
2018-05-02
-1.519427
-0.158811
1.191555
1.005464
2018-05-09
-0.704590
-0.332483
0.096710
-0.031565
2018-05-16
0.062633
0.375264
-0.321858
-0.776452
2018-05-23
-1.657576
-0.445090
-0.718661
-1.409694
2018-05-30
0.153913
0.402754
1.435081
-0.883503
2.2 含有重复索引的时间序列
对于有些数据,可能在某个特定的时间戳上有多个数据,导致索引重复,可以调用索引对象的 is_unique 属性查看是否重复,对于不重复的索引,其索引的结果为标量值,对于重复的索引,其索引结果为 Series 的切片
dates = pd. DatetimeIndex( [ '1/1/2019' , '1/2/2019' , '1/2/2019' , '1/2/2019' , '1/3/2019' ] )
dup_ts = pd. Series( np. arange( 5