datetime 数据类型
学习目标
- 应用Pandas来处理日期时间类型数据
1 Python的datetime对象
- Python内置了datetime对象,可以在datetime库中找到
from datetime import datetime
now = datetime.now()
now
显示结果:
datetime.datetime(2020, 6, 17, 19, 47, 56, 965416)
- 还可以手动创建datetime
t1 = datetime.now()
t2 = datetime(2020,1,1)
diff = t1-t2
print(t2)
print(diff)
显示结果:
2020-01-01 00:00:00 518 days, 11:06:49.342877
- 查看diff的数据类型
print(type(diff))
显示结果:
<class 'datetime.timedelta'>
2 将pandas中的数据转换成datetime
- 可以使用to_datetime函数把数据转换成datetime类型
#加载数据 并把Date列转换为datetime对象
ebola = pd.read_csv('data/country_timeseries.csv')
#获取左上角数据
ebola.iloc[:5,:5]
显示结果:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 1/5/2015 289 2776.0 NaN 10030.0 1 1/4/2015 288 2775.0 NaN 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 NaN 8157.0 NaN 4 12/31/2014 284 2730.0 8115.0 9633.0
- 从数据中看出 Date列是日期,但通过info查看加载后数据为object类型
ebola.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 122 entries, 0 to 121 Data columns (total 18 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 122 non-null object 1 Day 122 non-null int64 2 Cases_Guinea 93 non-null float64 3 Cases_Liberia 83 non-null float64 4 Cases_SierraLeone 87 non-null float64 5 Cases_Nigeria 38 non-null float64 6 Cases_Senegal 25 non-null float64 7 Cases_UnitedStates 18 non-null float64 8 Cases_Spain 16 non-null float64 9 Cases_Mali 12 non-null float64 10 Deaths_Guinea 92 non-null float64 11 Deaths_Liberia 81 non-null float64 12 Deaths_SierraLeone 87 non-null float64 13 Deaths_Nigeria 38 non-null float64 14 Deaths_Senegal 22 non-null float64 15 Deaths_UnitedStates 18 non-null float64 16 Deaths_Spain 16 non-null float64 17 Deaths_Mali 12 non-null float64 dtypes: float64(16), int64(1), object(1) memory usage: 17.3+ KB
- 可以通过to_datetime方法把Date列转换为datetime,然后创建新列
ebola['date_dt'] = pd.to_datetime(ebola['Date'])
ebola.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 122 entries, 0 to 121 Data columns (total 19 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 122 non-null object 1 Day 122 non-null int64 2 Cases_Guinea 93 non-null float64 3 Cases_Liberia 83 non-null float64 4 Cases_SierraLeone 87 non-null float64 5 Cases_Nigeria 38 non-null float64 6 Cases_Senegal 25 non-null float64 7 Cases_UnitedStates 18 non-null float64 8 Cases_Spain 16 non-null float64 9 Cases_Mali 12 non-null float64 10 Deaths_Guinea 92 non-null float64 11 Deaths_Liberia 81 non-null float64 12 Deaths_SierraLeone 87 non-null float64 13 Deaths_Nigeria 38 non-null float64 14 Deaths_Senegal 22 non-null float64 15 Deaths_UnitedStates 18 non-null float64 16 Deaths_Spain 16 non-null float64 17 Deaths_Mali 12 non-null float64 18 date_dt 122 non-null datetime64[ns] dtypes: datetime64[ns](1), float64(16), int64(1), object(1) memory usage: 18.2+ KB
- 如果数据中包含日期时间数据,也可以在加载的时候,通过parse_dates参数指定时间字段所在列的下标
ebola = pd.read_csv('data/country_timeseries.csv', parse_dates=[0])
ebola.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 122 entries, 0 to 121 Data columns (total 18 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 122 non-null datetime64[ns] 1 Day 122 non-null int64 2 Cases_Guinea 93 non-null float64 3 Cases_Liberia 83 non-null float64 4 Cases_SierraLeone 87 non-null float64 5 Cases_Nigeria 38 non-null float64 6 Cases_Senegal 25 non-null float64 7 Cases_UnitedStates 18 non-null float64 8 Cases_Spain 16 non-null float64 9 Cases_Mali 12 non-null float64 10 Deaths_Guinea 92 non-null float64 11 Deaths_Liberia 81 non-null float64 12 Deaths_SierraLeone 87 non-null float64 13 Deaths_Nigeria 38 non-null float64 14 Deaths_Senegal 22 non-null float64 15 Deaths_UnitedStates 18 non-null float64 16 Deaths_Spain 16 non-null float64 17 Deaths_Mali 12 non-null float64 dtypes: datetime64[ns](1), float64(16), int64(1) memory usage: 17.3 KB
3 提取日期的各个部分
- 获取了一个datetime对象,就可以提取日期的各个部分了
d = pd.to_datetime('2020-06-20')
d
显示结果:
Timestamp('2020-06-20 00:00:00')
- 可以看到得到的数据是Timestamp类型,通过Timestamp可以获取年,月,日等部分
print(d.year)
print(d.month)
print(d.day)
显示结果:
2020 6 20
- 通过ebola数据集的Date列,创建新列year
ebola['year'] = ebola['Date'].dt.year
ebola['year']
显示结果:
0 2015 1 2015 2 2015 3 2015 4 2014 ... 117 2014 118 2014 119 2014 120 2014 121 2014 Name: year, Length: 122, dtype: int64
ebola['month'], ebola['day'] = (ebola['Date'].dt.month, ebola['Date'].dt.day)
ebola[['Date','year','month','day']].head()
显示结果:
Date year month day 0 2015-01-05 2015 1 5 1 2015-01-04 2015 1 4 2 2015-01-03 2015 1 3 3 2015-01-02 2015 1 2 4 2014-12-31 2014 12 31
ebola.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 122 entries, 0 to 121 Data columns (total 21 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 122 non-null datetime64[ns] 1 Day 122 non-null int64 2 Cases_Guinea 93 non-null float64 3 Cases_Liberia 83 non-null float64 4 Cases_SierraLeone 87 non-null float64 5 Cases_Nigeria 38 non-null float64 6 Cases_Senegal 25 non-null float64 7 Cases_UnitedStates 18 non-null float64 8 Cases_Spain 16 non-null float64 9 Cases_Mali 12 non-null float64 10 Deaths_Guinea 92 non-null float64 11 Deaths_Liberia 81 non-null float64 12 Deaths_SierraLeone 87 non-null float64 13 Deaths_Nigeria 38 non-null float64 14 Deaths_Senegal 22 non-null float64 15 Deaths_UnitedStates 18 non-null float64 16 Deaths_Spain 16 non-null float64 17 Deaths_Mali 12 non-null float64 18 year 122 non-null int64 19 month 122 non-null int64 20 day 122 non-null int64 dtypes: datetime64[ns](1), float64(16), int64(4) memory usage: 20.1 KB
4 日期运算和Timedelta
4.1 datetime类型的日期可以直接进行时间计算
Ebola数据集中的Day列表示一个国家爆发Ebola疫情的天数。这一列数据可以通过日期运算重建该列
- 疫情爆发的第一天(数据集中最早的一天)是2014-03-22。计算疫情爆发的天数时,只需要用每个日期减去这个日期即可
# 获取疫情爆发的第一天
ebola['Date'].min()
显示结果:
Timestamp('2014-03-22 00:00:00')
- 添加爆发时长列
ebola['outbreak_d'] = ebola['Date'] - ebola['Date'].min()
ebola[['Date','Day','outbreak_d']].head()
显示结果:
Date Day outbreak_d 0 2015-01-05 289 289 days 1 2015-01-04 288 288 days 2 2015-01-03 287 287 days 3 2015-01-02 286 286 days 4 2014-12-31 284 284 days
- 查看最后五行数据
ebola[['Date','Day','outbreak_d']].tail()
显示结果:
Date Day outbreak_d 117 2014-03-27 5 5 days 118 2014-03-26 4 4 days 119 2014-03-25 3 3 days 120 2014-03-24 2 2 days 121 2014-03-22 0 0 days
- 执行这种日期运算,会得到一个timedelta对象
ebola.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 122 entries, 0 to 121 Data columns (total 22 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 122 non-null datetime64[ns] 1 Day 122 non-null int64 2 Cases_Guinea 93 non-null float64 3 Cases_Liberia 83 non-null float64 4 Cases_SierraLeone 87 non-null float64 5 Cases_Nigeria 38 non-null float64 6 Cases_Senegal 25 non-null float64 7 Cases_UnitedStates 18 non-null float64 8 Cases_Spain 16 non-null float64 9 Cases_Mali 12 non-null float64 10 Deaths_Guinea 92 non-null float64 11 Deaths_Liberia 81 non-null float64 12 Deaths_SierraLeone 87 non-null float64 13 Deaths_Nigeria 38 non-null float64 14 Deaths_Senegal 22 non-null float64 15 Deaths_UnitedStates 18 non-null float64 16 Deaths_Spain 16 non-null float64 17 Deaths_Mali 12 non-null float64 18 year 122 non-null int64 19 month 122 non-null int64 20 day 122 non-null int64 21 outbreak_d 122 non-null timedelta64[ns] dtypes: datetime64[ns](1), float64(16), int64(4), timedelta64[ns](1) memory usage: 21.1 KB
4.2 练习
需求:通过
data/banklist.csv
数据,计算每个季度、每年银行破产的数量
- 加载
data/banklist.csv
数据
banks = pd.read_csv('data/banklist.csv')
banks.head()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OnMKFDom-1631494033739)(./img/时间数据类型-01.png)]
- 可以看到有两列数据是日期时间类型,可以在导入数据的时候直接解析日期
banks = pd.read_csv('data/banklist.csv',parse_dates=[5,6])
banks.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 553 entries, 0 to 552 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Bank Name 553 non-null object 1 City 553 non-null object 2 ST 553 non-null object 3 CERT 553 non-null int64 4 Acquiring Institution 553 non-null object 5 Closing Date 553 non-null datetime64[ns] 6 Updated Date 553 non-null datetime64[ns] dtypes: datetime64[ns](2), int64(1), object(4) memory usage: 30.4+ KB
- 添加两列,分别表示银行破产的季度和年份
banks['closing_quarter'], banks['closing_year'] = (banks['Closing Date'].dt.quarter, banks['Closing Date'].dt.year)
banks.head()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bRipwir6-1631494033741)(./img/时间数据类型-02.png)]
- 可以根据新添加的两列,计算每年破产银行数量
# 根据closing_year分组,再计算每组数据的行数
closing_year = banks.groupby(['closing_year']).size()
closing_year
显示结果:
closing_year 2000 2 2001 4 2002 11 2003 3 2004 4 2007 3 2008 25 2009 140 2010 157 2011 92 2012 51 2013 24 2014 18 2015 8 2016 5 2017 6 dtype: int64
- 出图
closing_year.plot()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TMhhdHaf-1631494033743)(./img/时间数据类型-03.png)]
- 计算每年每季度破产银行数量,并出图
closing_year_q = banks.groupby(['closing_year', 'closing_quarter']).size()
closing_year_q.plot()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REHbrcD2-1631494033745)(./img/时间数据类型-04.png)]
5 时间数据索引
股票价格是包含日期的典型数据,以
data/TSLA.csv
为例
5.1 加载数据
- 加载特斯拉股票数据
tesla = pd.read_csv('data/TSLA.csv')
tesla
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jzPtrhni-1631494033746)(./img/tsl-01.png)]
- 可以看出,tesla股票数据中第一列为日期,在加载数据的时候,可以直接解析日期数据
tesla = pd.read_csv('data/TSLA.csv', parse_dates=[0])
tesla.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1215 entries, 0 to 1214 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 1215 non-null datetime64[ns] 1 High 1215 non-null float64 2 Low 1215 non-null float64 3 Open 1215 non-null float64 4 Close 1215 non-null float64 5 Volume 1215 non-null int64 6 Adj Close 1215 non-null float64 dtypes: datetime64[ns](1), float64(5), int64(1) memory usage: 66.6 KB
- 转换为时间类型后,就可以基于日期数据获取数据子集,比如要获取2015年8月的股票数据
tesla.loc[(tesla.Date.dt.year==2015) & (tesla.Date.dt.month==8)]
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oUj9byS2-1631494033747)(./img/tsl-02.png)]
5.2 DatetimeIndex对象
- 在处理包含datetime的数据时,经常需要把datetime对象设置成DateFrame的索引
#首先把Date列指定为索引
tesla.index = tesla['Date']
tesla.index
显示结果:
DatetimeIndex(['2015-08-19', '2015-08-20', '2015-08-21', '2015-08-24', '2015-08-25', '2015-08-26', '2015-08-27', '2015-08-28', '2015-08-31', '2015-09-01', ... '2020-06-03', '2020-06-04', '2020-06-05', '2020-06-08', '2020-06-09', '2020-06-10', '2020-06-11', '2020-06-12', '2020-06-15', '2020-06-16'], dtype='datetime64[ns]', name='Date', length=1215, freq=None)
- 查看数据集
tesla.head()
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oIWEcWtH-1631494033748)(./img/tsl-03.png)]
- 把索引设置为日期对象后,可以直接使用日期中的年份来获取数据
tesla['2016'].iloc[:5] # 数据的日期索引为有序的才能使用此方法查询
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i6V4Ka35-1631494033749)(./img/tsl-04.png)]
- 也可以根据年份和月份获取数据
tesla['2016-06'].iloc[:5]
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7p5obZiT-1631494033750)(./img/tsl-05.png)]
5.3 TimedeltaIndex对象
- 首先创建一个timedelta
tesla['ref_date'] = tesla['Date'] - tesla['Date'].min()
tesla['ref_date']
显示结果:
Date 2015-08-19 0 days 2015-08-20 1 days 2015-08-21 2 days 2015-08-24 5 days 2015-08-25 6 days ... 2020-06-10 1757 days 2020-06-11 1758 days 2020-06-12 1759 days 2020-06-15 1762 days 2020-06-16 1763 days Name: ref_date, Length: 1215, dtype: timedelta64[ns]
- 把timedelta设置为index
tesla.index = tesla['ref_date']
tesla.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> TimedeltaIndex: 1215 entries, 0 days to 1763 days Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 1215 non-null datetime64[ns] 1 High 1215 non-null float64 2 Low 1215 non-null float64 3 Open 1215 non-null float64 4 Close 1215 non-null float64 5 Volume 1215 non-null int64 6 Adj Close 1215 non-null float64 7 ref_date 1215 non-null timedelta64[ns] dtypes: datetime64[ns](1), float64(5), int64(1), timedelta64[ns](1) memory usage: 85.4 KB
tesla.head()
显示结果:
Date High Low Open Close Volume Adj Close ref_date ref_date 0 days 2015-08-19 260.649994 255.020004 260.329987 255.250000 3604300 255.250000 0 days 1 days 2015-08-20 254.559998 241.899994 252.059998 242.179993 4905800 242.179993 1 days 2 days 2015-08-21 243.800003 230.509995 236.000000 230.770004 6590200 230.770004 2 days 5 days 2015-08-24 231.399994 195.000000 202.789993 218.869995 9581600 218.869995 5 days 6 days 2015-08-25 230.899994 219.119995 230.520004 220.029999 4327300 220.029999 6 days
- 可以基于ref_date来选择数据
tesla['0 days':'4 days']
显示结果:
Date High Low Open Close Volume Adj Close ref_date ref_date 0 days 2015-08-19 260.649994 255.020004 260.329987 255.250000 3604300 255.250000 0 days 1 days 2015-08-20 254.559998 241.899994 252.059998 242.179993 4905800 242.179993 1 days 2 days 2015-08-21 243.800003 230.509995 236.000000 230.770004 6590200 230.770004 2 days
6 日期范围
- 包含日期的数据集中,并非每一个都包含固定频率。比如在Ebola数据集中,日期并没有规律
ebola.iloc[:,:5]
显示结果:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 2015-01-05 289 2776.0 NaN 10030.0 1 2015-01-04 288 2775.0 NaN 9780.0 2 2015-01-03 287 2769.0 8166.0 9722.0 3 2015-01-02 286 NaN 8157.0 NaN 4 2014-12-31 284 2730.0 8115.0 9633.0 … … … … … … 117 2014-03-27 5 103.0 8.0 6.0 118 2014-03-26 4 86.0 NaN NaN 119 2014-03-25 3 86.0 NaN NaN 120 2014-03-24 2 86.0 NaN NaN 121 2014-03-22 0 49.0 NaN NaN
- 从上面的数据中可以看到,缺少2015年1月1日,2014年3月23日,如果想让日期连续,可以创建一个日期范围来为数据集重建索引。这时,我们可以使用
df.date_range()
函数来创建连续的日期范围
head_range = pd.date_range(start='2014-12-31', end='2015-01-05')
head_range
显示结果:
DatetimeIndex(['2014-12-31', '2015-01-01', '2015-01-02', '2015-01-03', '2015-01-04', '2015-01-05'], dtype='datetime64[ns]', freq='D')
- 在上面的例子中,只取前5行,首先设置日期索引,然后为数据重建连续索引
ebola_5 = ebola.head()
ebola_5.index = ebola_5['Date']
ebola_5.reindex(head_range)
ebola_5.iloc[:,:5]
显示结果:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 2014-12-31 2014-12-31 284.0 2730.0 8115.0 9633.0 2015-01-01 NaT NaN NaN NaN NaN 2015-01-02 2015-01-02 286.0 NaN 8157.0 NaN 2015-01-03 2015-01-03 287.0 2769.0 8166.0 9722.0 2015-01-04 2015-01-04 288.0 2775.0 NaN 9780.0 2015-01-05 2015-01-05 289.0 2776.0 NaN 10030.0
- 使用date_range函数创建日期序列时,可以传入一个参数freq,默认情况下freq取值为D,表示日期范围内的值是逐日递增的。
# 2020年1月1日这周所有的工作日,freq='B'表示取工作日,freq默认为'D'返回全部日期
pd.date_range('2020-01-01', '2020-01-07', freq='B')
显示结果:从结果中看到生成的日期中缺少1月4日,1月5日,为休息日
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06', '2020-01-07'], dtype='datetime64[ns]', freq='B')
- 【查表】freq的可选参数
Alias | Description |
---|---|
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 | microseconds |
N | 纳秒 |
- 在freq传入参数的基础上,可以做一些调整
# 隔一个工作日取一个工作日
pd.date_range('2020-01-01', '2020-01-07', freq='2B')
显示结果:
DatetimeIndex(['2020-01-01', '2020-01-03', '2020-01-07'], dtype='datetime64[ns]', freq='2B')
- freq传入的参数可以传入多个
#2020年每个月的第一个星期四
pd.date_range('2020-01-01','2020-12-31',freq='WOM-1THU')
显示结果:
DatetimeIndex(['2020-01-02', '2020-02-06', '2020-03-05', '2020-04-02', '2020-05-07', '2020-06-04', '2020-07-02', '2020-08-06', '2020-09-03', '2020-10-01', '2020-11-05', '2020-12-03'], dtype='datetime64[ns]', freq='WOM-1THU')
#每个月的第三个星期五
pd.date_range('2020-01-01','2020-12-31',freq='WOM-3FRI')
显示结果:
DatetimeIndex(['2020-01-17', '2020-02-21', '2020-03-20', '2020-04-17', '2020-05-15', '2020-06-19', '2020-07-17', '2020-08-21', '2020-09-18', '2020-10-16', '2020-11-20', '2020-12-18'], dtype='datetime64[ns]', freq='WOM-3FRI')
7 datetime类型案例
- 加载丹佛市犯罪记录数据集
crime = pd.read_csv('data/crime.csv',parse_dates=['REPORTED_DATE'])
crime
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eaqiCmSY-1631494033752)(./img/时间数据类型-05.png)]
- 查看数据集总体情况
crime.info()
显示结果:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 460911 entries, 0 to 460910 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 OFFENSE_TYPE_ID 460911 non-null object 1 OFFENSE_CATEGORY_ID 460911 non-null object 2 REPORTED_DATE 460911 non-null datetime64[ns] 3 GEO_LON 457296 non-null float64 4 GEO_LAT 457296 non-null float64 5 NEIGHBORHOOD_ID 460911 non-null object 6 IS_CRIME 460911 non-null int64 7 IS_TRAFFIC 460911 non-null int64 dtypes: datetime64[ns](1), float64(2), int64(2), object(3) memory usage: 28.1+ MB
- 设置报警时间为索引
crime = crime.set_index('REPORTED_DATE')
crime.head()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RbICRUy9-1631494033752)(./img/时间数据类型-06.png)]
- 查看某一天的报警记录
crime.loc['2016-05-12'] # 日期索引为无序的,只能通过loc获取数据
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T1utnikU-1631494033753)(./img/时间数据类型-07.png)]
- 查看某一段时间的犯罪记录
crime.loc['2015-3-4':'2016-1-1'].sort_index()
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g40meam5-1631494033754)(./img/时间数据类型-08.png)]
- 时间段可以包括小时分钟
crime.loc['2015-3-4 22': '2016-1-1 23:45:00'].sort_index()
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1A4rZKZ8-1631494033755)(./img/时间数据类型-09.png)]
- 查询凌晨两点到五点的报警记录
- between_time函数
# between_time函数,include_end=False表示不包含结束时间,默认为True,同样也有include_start参数
crime.between_time('4:00', '5:00', include_end=False).head(10)
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ggnsfzg-1631494033756)(./img/时间数据类型-10.png)]
- 查看发生在某个时刻的犯罪记录
- at_time函数
crime.at_time('5:47')
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uBxqfZOJ-1631494033757)(./img/时间数据类型-11.png)]
- 当数据量庞大时,在按时间段选取数据时,可以将时间索引排序,排序之后再选取效率更高
# sort_index() 对索引进行排序,默认升序
crime_sort = crime.sort_index()
- 计算每周的犯罪数量
- resample函数,传入
'W'
参数表示按周对时间索引进行分组
- resample函数,传入
# resample函数传入W参数,表示按周分组,size查看分组后每组数量行数
weekly_crimes = crime_sort.resample('W').size()
weekly_crimes
显示结果:
REPORTED_DATE 2012-01-08 877 2012-01-15 1071 2012-01-22 991 2012-01-29 988 2012-02-05 888 ... 2017-09-03 1956 2017-09-10 1733 2017-09-17 1976 2017-09-24 1839 2017-10-01 1059 Freq: W-SUN, Length: 300, dtype: int64
- 检验分组结果:查看起始数据到2012-1-8的报警记录数量
len(crime_sort.loc[:'2012-1-8'])
显示结果:
877
- 检验分组结果:查看2012-1-9到2012-1-15的报警记录数量
len(crime_sort.loc['2012-1-9':'2012-1-15'])
显示结果:
1071
- 也可以把周四作为每周的结束
crime_sort.resample('W-THU').size()
显示结果:
REPORTED_DATE 2012-01-05 462 2012-01-12 1116 2012-01-19 924 2012-01-26 1061 2012-02-02 926 ... 2017-09-07 1803 2017-09-14 1866 2017-09-21 1926 2017-09-28 1720 2017-10-05 28 Freq: W-THU, Length: 301, dtype: int64
- 将按周分组结果可视化
# 去除warnning警告信息
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['KaiTi', 'SimHei', 'FangSong'] # 汉字字体,优先使用楷体,如果找不到楷体,则使用黑体
mpl.rcParams['font.size'] = 12 # 字体大小
mpl.rcParams['axes.unicode_minus'] = False # 正常显示负号
# 出图
weekly_crimes.plot(figsize=(16,4), title='丹佛报警情况')
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3tOC2IAv-1631494033758)(./img/时间数据类型-12.png)]
- 分别统计每季度的犯罪和交通事故报警次数
# resample('Q')按季度分组数据后,提取['IS_CRIME', 'IS_TRAFFIC']字段,并对提取的列的值做sum求和计算
crime_quarterly = crime_sort.resample('Q')['IS_CRIME', 'IS_TRAFFIC'].sum()
crime_quarterly
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OfOrGivR-1631494033759)(./img/时间数据类型-13.png)]
resample('Q')
统计的所有日期都是该季度的最后一天,使用QS
参数生成每季度的第一天
crime_sort.resample('QS')['IS_CRIME', 'IS_TRAFFIC'].sum().head()
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8RsMKiaE-1631494033760)(./img/时间数据类型-14.png)]
- 结果可视化
plot_kwargs = dict(figsize=(16,4), color=['black', 'blue'], title='丹佛犯罪和交通事故数据')
crime_quarterly.plot(**plot_kwargs)
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2UviMjfg-1631494033760)(./img/时间数据类型-15.png)]
- 分析工作日的犯罪情况:可以通过Timestamp的dt属性得到周几,然后统计
DatetimeIndex.dt.weekday
可以返回日期是星期几
crime = pd.read_csv('data/crime.csv', parse_dates=['REPORTED_DATE'])
wd_counts = crime['REPORTED_DATE'].dt.weekday.value_counts()
wd_counts
显示结果:
0 70024 4 69621 2 69538 3 69287 1 68394 5 58834 6 55213 Name: REPORTED_DATE, dtype: int64
- 出图
wd_counts.plot(kind='barh', title='星期一~星期日丹佛犯罪和交通事故报警数量统计')
显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZiD8PcY4-1631494033761)(./img/时间数据类型-16.png)]
小结
- Pandas中,datetime64用来表示时间序列类型
- 时间序列类型的数据可以作为行索引,对应的数据类型是DatetimeIndex类型
- datetime64类型可以做差,返回的是Timedelta类型
- 转换成时间序列类型后,可以按照时间的特点对数据进行处理
- 提取日期的各个部分(月,日,星期…)
- 进行日期运算
- 按照日期范围取值