目录
(2)datetime.timedelta 两个datetime之间的差,以天数与及秒来存储
(1)strftime(format) 是对datetime对象和pandas的Timestamp对象进行格式化
(2)datetime.srtptime(str[format]) 将字符串转换日期
(3)用dateutil包的parser.parse() 代替srtptime来转化成通用的格式(比较省事)
(3)pandas.to_datetime() 可以转换不同的日期格式,pandas主要面向处理日期数组
(3)聚合含有非唯一时间戳。使用groupby并传递level=0
(1)调用resample,将时间序列转换为固定的每日频率数据
(1)pandas.date_range是根据特定频率生成指定长度的DatetimeIndex
11.1日期与时间数据的类型工具
类型 | 描述 |
date | 使用公历日期存储日历日期(年,月,日) |
time | 将时间存储为小时,分钟, 秒和微秒(1 秒=1000000 微秒) |
datetime | 存储日期和时间 |
timedelta | 表示两个datetime值之间的差(如日,秒和微秒) |
tzinfo | 用于存储时区信息的基本类型 |
(1)datetime.datetime
from datetime import datetime
now = datetime.now() #datetime.now()输出的是时间格式
now
out: datetime.datetime(2021, 12, 9, 20, 28, 46, 943398)
获得的now,"底层"上是一个时间词典,可用now.year, now.month, now.day, now.hour, now.minute, now.second 来获取相对的年份,月份等
(2)datetime.timedelta 两个datetime之间的差,以天数与及秒来存储
dalta = datetime(2011, 1, 7) - datetime(2021,8,24,5,16)
dalta
out:datetime.timedelta(days=-3883, seconds=67440)
timedelta可以与时间(日期)进行运算
from datetime import timedelta
from datetime import timedelta
now + timedelta(11)
now - timedelta(12)/2
now + timedelta(12)*2
11.1.1 字符串与datetime互相转换
比较常用的datetime格式化:
- %Y 四位数的年份表示(000-9999)
- %y 两位数的年份表示(00-99)
- %m 月份(01-12)
- %d 月内中的一天(0-31)
- %H 24小时制小时数(0-23)
- %I 12小时制小时数(01-12)
- %M 分钟数(00-59)
- %S 秒(00-59)
- %U 一年中的星期数(00-53)星期天为星期的开始
- %w 星期(0-6),星期天为 0,星期一为 1,以此类推。
- %W 一年中的星期数(00-53)星期一为星期的开始
- %F %Y-%m-%d的简写(例如:2021-10-09)
- %D %m/%d/%y的简写(例如:03/10/21)
(1)strftime(format) 是对datetime对象和pandas的Timestamp对象进行格式化
import datetime
stamp = datetime.datetime(2021, 12, 9)
print(type(stamp))
print(type(str(stamp))) #str()转成str
print(stamp.strftime('%Y-%m-%d')) #stamp.strftime(format)把时间格式化
#print(stamp.strftime('%F')) 与上一条相等
out:
<class 'datetime.datetime'>
<class 'str'>
2021-12-09
(2)datetime.srtptime(str[format]) 将字符串转换日期
import datetime
v_str = '2021-12-09'
v_time = datetime.datetime.strptime(v_str, '%Y-%m-%d')
print(v_time)
out:2021-12-09 00:00:00
注:用impotr datetime时,使用srtptime(str[format]),前面需要加datetime.datetime.,而非datetime.
列表的应用:
from datetime import datetime
datestrs = ['9/12/2021', '8/12/2021']
date_time = [datetime.strptime(x, '%m/%d/%Y') for x in datestrs]
print(date_time)
out:[datetime.datetime(2021, 9, 12, 0, 0), datetime.datetime(2021, 8, 12, 0, 0)]
注:datestrs给定,年份是4位数,因些在格式化得用"Y",而不能"y",年份为2位数时,同理。
(3)用dateutil包的parser.parse() 代替srtptime来转化成通用的格式(比较省事)
注:dateutil.parser并不完美,例如:'42'将被解析为2042年的当前日期
from dateutil.parser import parse
date_1 = parse('2021-12-09')
print(date_1)
date_2 = parse('Jan 31, 1997 10:45 PM')
print(date_2)
date_3 = parse('9/12/2021', dayfirst=True) #日期有前面需要用dayfirst=True声明
print(date_3)
out:
2021-12-09 00:00:00
1997-01-31 22:45:00
2021-12-09 00:00:00
(3)pandas.to_datetime() 可以转换不同的日期格式,pandas主要面向处理日期数组
import pandas as pd
datestrs = ['9/12/2021', '8/12/2021']
date_times = pd.to_datetime(datestrs)
print(date_times)
out:DatetimeIndex(['2021-09-12', '2021-08-12'], dtype='datetime64[ns]', freq=None)
to_datetime还可以处理被认为是缺失值的值(None、空字符串等)
import pandas as pd
datestrs = ['9/12/2021', '8/12/2021']
idx = pd.to_datetime(datestrs + [None])
#idx = pd.to_datetime(datestrs + ['']) 同上
print(idx)
print(idx[2])
print(pd.isnull(idx))
out:
DatetimeIndex(['2021-09-12', '2021-08-12', 'NaT'], dtype='datetime64[ns]', freq=None)
NaT
[False False True]
注:Nat(Not a time)是pandas中时间戳数据的是null值
11.2时间序列基础
(1)panda的基础时间序列种类
panda是由时间戳索引的Series,在pandas外部则通常表示为Python字符串或datetime对象
from datetime import datetime
import numpy as np
import pandas as pd
dates = [datetime(2021, 10, 10), datetime(2021, 10, 11),
datetime(2021, 10, 12), datetime(2021, 10, 13)]
#randn函数返回一个或一组样本,具有标准正态分布
ts = pd.Series(np.random.randn(4), index=dates)
print('-----------ts-----------\n', ts)
#在此情况下,这些datetime对象可以放入DatetimeIndex中:
print('---------ts.index---------\n', ts.index)
print('--------ts + ts[::2]------\n',ts + ts[::2])
out:-----------ts-----------
2021-10-10 -0.013340
2021-10-11 -1.399646
2021-10-12 0.312608
2021-10-13 -1.265291
dtype: float64
---------ts.index---------
DatetimeIndex(['2021-10-10', '2021-10-11', '2021-10-12', '2021-10-13'], dtype='datetime64[ns]', freq=None)
--------ts + ts[::2]------
2021-10-10 -0.026680
2021-10-11 NaN
2021-10-12 0.625216
2021-10-13 NaN
dtype: float64
DatetimeIndex中的标量值是pandas的Timestamp对象,所有使用datetime对象的地方都可以用Timestamp。
stamp = ts.index[0]
print(stamp)
out:
2021-10-10 00:00:00
11.2.1索引、选择、子集
(1)索引和选择
基于标签进行索引和选择时,时间序列的行为和其他的pandas.Series类似:
stamp = ts.index[0]
print(ts[stamp])
out:
-0.013340
同等的索引:
stamp = ts.index[1]
print(ts[stamp])
print(ts['2021-10-11'])
print(ts['20211011'])
print(ts[datetime(2021, 10, 11)])
out:
-1.399646
-1.399646
-1.399646
-1.399646
(2)用年份与月份进行切片
对长的时间序列,可以传递一具年份或一个年份和月份来轻松选择数据的切片
from datetime import datetime
import numpy as np
import pandas as pd
longer_ts = pd.Series(np.random.randn(1000),
index=pd.date_range('2021/1/1', periods=1000))
print('----------longer_ts-------------\n', longer_ts)
print('----------longer_ts-------------\n', longer_ts['2021'])
print('----------longer_ts-------------\n', longer_ts['2021-5'])
(3)datetime对象切片
使用datetime对象进行切片也可以
print(longer_ts[datetime(2021,1,20)])
(4)时间戳进行片
大多数的时间序列是按时间顺序顺序的,可使用包含在时间序列中的时间戳进行片,以执行范围查询(注:切片包括头与尾两个日期)
print(longer_ts['2021/1/2':'2021/1/5'])
(5)truncat进行切片
有一个等价的方法:truncate,它只可以在两个日期间对Series进行切片,
print(longer_ts.truncate(after='2021/1/5')) #输出的是2021/1/1-2021/1/4
print(longer_ts.truncate(before='2021/1/5'))
注:
after(之后)是之前的日期,before(之前)是之后的日期
truncate需要排序索引,顺序与倒序都可以
11.2.2含有重复索引的时间序列
(1)is_unique,检查索引是否是唯一
from datetime import datetime
import numpy as np
import pandas as pd
dates = pd.DatetimeIndex(['10/11/2021', '10/12/2021','10/12/2021','10/12/2021','10/13/2021'])
dup_ts = pd.Series(np.arange(5), index = dates)
print(dup_ts)
print('dup_ts.index.is_unique:', dup_ts.index.is_unique)
(2)对重复索引进行切片
对(1)中进行索引,结果是标量值不是Series切片取决于是否有时间戳是重复的
print('不重复\n', dup_ts['10/11/2021'])
print('重复\n', dup_ts['10/12/2021'])
out:
不重复
0
重复
2021-10-12 1
2021-10-12 2
2021-10-12 3
dtype: int32
(3)聚合含有非唯一时间戳。使用groupby并传递level=0
grouped = dup_ts.groupby(level=0)
print(grouped.mean()) #重复索引,进行平均数输出
print(grouped.count()) #重复索引,进行统计输出
11.3日期范围、频率和移位
(1)调用resample,将时间序列转换为固定的每日频率数据
resampler = ts.resample('D')
字符串'D'被解释为每日频率
11.3.1生成日期范围
(1)pandas.date_range是根据特定频率生成指定长度的DatetimeIndex
index = pd.date_range('2021-12-10', '2021-12-31')
(2)date_range 传递范围数字
默认情况下:date_range生成的每日的时间戳。若只传递一个起始或结尾日期,就必须传递一个用于生成范围的数字。
index_1 = pd.date_range(start = '2021-12-10', periods=22)
index_2 = pd.date_range(end = '2021-12-31', periods=22)
(3)date_range 传递基础时间序列频率
传递基础时间序列频率(不全)
别名 | 偏置类型 | 描述 |
D | Day | 日历日的每天 |
B | BusinessDay | 工作日的每天 |
H | Hour | 每小时 |
T或min | Minute | 每分钟 |
S | Second | 每秒 |
M | MonthEnd | 日历日的月底日期 |
BM | BusinessMonthEnd | 工作日的月底日期 |
MS | MonthBegin | 日历日的月初日期 |
BMS | BusinessMonthBegin | 工作日的月初日期 |
index = pd.date_range('2021-12-10', '2021-12-31', freq='B')
(4)date_range 保留时间
默认情况下,若是开始或结束时间戳有时间,则date_range都会保留
pd.date_range('2021-12-10 17:24', periods=5)
(5)normalize: 标准化零点的时间戳(去掉时间)
pd.date_range('2021-12-10 17:24', periods=5, normalize=True)
11.3.2频率和日期偏置
(1)pandas的频率是由基本频率和倍数组成
from pandas.tseries.offsets import Hour, Minute
import pandas as pd
hour = Hour()
#传递一个整数来定义偏置量的倍数
four_hours = Hour(4)
#在基础频率前放一个整数,可以生成倍数
four_hours_day = pd.date_range('2021-12-10', '2021-12-31 12:13:26', freq='5h')
print(four_hours_day)
(2)多个偏置可通过加法进行联合
Hour(2) + Minute(15)
(3)传递字符串,可有效转换为同等的表达式
pd.date_range('2021-12-10', '2021-12-31 12:13:26', freq='1d5h')
11.3.3移位(前向和后向)日期
(1)shift,进行位移而不改变索引
在Series和DataFrame都可以用shift
from pandas.tseries.offsets import Hour, Minute
import pandas as pd
import numpy as np
ts = pd.Series(np.random.randn(4),
index=pd.date_range('2021-05-10', periods=4, freq='m'))
print(ts)
print(ts.shift(2))
print(ts.shift(-2))
out:
2021-05-31 0.406805
2021-06-30 -1.203896
2021-07-31 0.887920
2021-08-31 1.734760
Freq: M, dtype: float64
2021-05-31 NaN
2021-06-30 NaN
2021-07-31 0.406805
2021-08-31 -1.203896
Freq: M, dtype: float64
2021-05-31 0.88792
2021-06-30 1.73476
2021-07-31 NaN
2021-08-31 NaN
Freq: M, dtype: float64
注:在进行位移时,会有时间序列的起始位或结束位引入缺失值
(2)频率传递给shift来推移时间戳
如果频率是已知的,可把频率传递给shift来推移时间戳
print(ts.shift(2, freq='M'))
print(ts.shift(2, freq='D'))
print(ts.shift(2, freq='90T'))
out:
2021-07-31 0.406805
2021-08-31 -1.203896
2021-09-30 0.887920
2021-10-31 1.734760
Freq: M, dtype: float64
2021-06-02 0.406805
2021-07-02 -1.203896
2021-08-02 0.887920
2021-09-02 1.734760
dtype: float64
2021-05-31 03:00:00 0.406805
2021-06-30 03:00:00 -1.203896
2021-07-31 03:00:00 0.887920
2021-08-31 03:00:00 1.734760
dtype: float64
(3)使用偏置进行移位日期
from datetime import datetime
from pandas.tseries.offsets import Day, MonthEnd
now = datetime(2021, 12, 10)
print(now + 3 * Day())
print(now + MonthEnd())
print(now + MonthEnd(2))
(4)使用rollforward 和 rollback
使用rollforward 和 rollback 分别显式地将日期向前或向后“滚动”
offset = MonthEnd()
print(offset.rollforward(now))
print(offset.rollback(now))