跳转至

10 datetime 数据类型

学习目标

  • 应用Pandas来处理日期时间类型数据

1 datetime介绍

1.1 Python的datetime对象

  • Python内置了datetime对象,可以在datetime库中找到
from datetime import datetime
t1 = datetime.now()
t1
t2 = datetime(2021,1,1)
t2

1.2 将pandas中的数据转换成datetime

  • 可以使用to_datetime函数把数据转换成datetime类型
#加载数据 并把Date列转换为datetime对象
ebola = pd.read_csv('data/country_timeseries.csv').iloc[:5,:5]
  • 从数据中看出 Date列是日期,但通过info查看加载后数据为object类型
ebola.info()
  • 可以通过to_datetime方法把Date列转换为datetime
ebola['Date'] = pd.to_datetime(ebola['Date'])
ebola.info()
  • 也可以在加载的时候,通过parse_dates参数指定日期时间列
ebola = pd.read_csv('data/country_timeseries.csv',parse_dates=[0]).iloc[:5,:5]
ebola.info()

1.3 提取日期的各个部分

  • 获取了一个datetime对象,就可以提取日期的各个部分了
d = pd.to_datetime('2020-06-20')
d # Timestamp('2020-06-20 00:00:00')
  • 可以看到得到的数据是Timestamp类型,通过Timestamp可以获取年,月,日等部分
d.year
d.month
d.day
  • 通过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

1.4 日期范围 date_range

  • 可以使用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')
  • 使用date_range函数创建日期序列时,可以传入一个参数freq,默认情况下freq取值为D,表示日期范围内的值是逐日递增的。
# 2020年1月1日这周所有的工作日
pd.date_range('2020-01-01','2020-01-07',freq='B')

显示结果:

DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06',
               '2020-01-07'],
              dtype='datetime64[ns]', freq='B')
  • 从结果中看到生成的日期中缺少1月4日,1月5日,为休息日

feq参数的可能取值

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年每个月的第一个星期四
# 星期几缩写:MON/TUE/WED/THU/FRI/SAT/SUN
# W-MON:从指定星期几开始算起,每周
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')

2 datetime类型案例

2.1 加载数据集

# 某城市报警记录
crime = pd.read_csv('data/crime.csv',parse_dates=['REPORTED_DATE'])
crime
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()

2.2 数据查看

1 查看某一天的报警记录

crime.loc['2016-05-12']

2 查看某一段时间的犯罪记录

crime.loc['2015-3-4':'2016-1-1'].sort_index()

3 时间段可以包括小时分钟

crime.loc['2015-3-4 22':'2016-1-1 23:45:00'].sort_index()

4 查询凌晨两点到五点的报警记录

crime.between_time('2:00', '5:00', include_end=False)

5 查看发生在某个时刻的犯罪记录

crime.at_time('5:47')

2.3 分析每周报警记录

  • 为了统计每周的犯罪数,需要按周分组

1 resample重采样

  • 可以按照指定时间周期分组
crime.resample('W')
#size查看分组大小
weekly_crimes = crime.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

2 检验分组结果

len(crime.loc[:'2012-1-8'])

显示结果:

877
len(crime.loc['2012-1-9':'2012-1-15'])

显示结果:

1071

3 调整结果

  • 也可以把周四作为每周的结束
crime.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

4 将按周分组结果可视化

weekly_crimes.plot(figsize=(16,4),title='丹佛犯罪情况')

显示结果:

img

小结

  • Pandas中,datetime64用来表示时间序列类型
  • 时间序列类型的数据可以作为行索引,对应的数据类型是DatetimeIndex类型
  • 转换成时间序列类型后,可以按照时间的特点对数据进行处理
  • 提取日期的各个部分(月,日,星期...)
  • 进行日期运算
  • 按照日期范围取值