系列文章目录
Python数据分析入门笔记6——数据清理案例练习
Python数据分析入门笔记7——数据集成、变换与规约
Python数据分析入门笔记
- 系列文章目录
- 前言
- 一、datetime对象
- 1. 快速上手,自己创建
- 2. 将pandas中的数据转换成datetime对象——to_datetime()
- 3. 提取日期的各个部分
- 4. 日期运算和Timedelta
- 5. 日期范围的处理——date_range函数
- 二、案例——丹佛市犯罪数据
- 1. 读取文件,设置索引。——read_csv()和set_index()
- 2. 查看指定日期的记录——loc
- 3. 查看指定日期范围的记录——loc
- 4. 查看指定时间范围的报警记录——between_time()
- 5. 查看发生在某个时刻的犯罪记录——at_time()
- 6. 按周统计——resample('W')
- 7. 分析季度数据——resample('Q')
- 8. 按是否工作日分析
- 总结
前言
文中用到的练习资源文件,可直接点击下载:
- 埃博拉疫情数据分析
- 丹佛市犯罪信息
一、datetime对象
关于时间模块更多内容,可查看此文:Python模块——datatime
1. 快速上手,自己创建
- 获取当前时间,计算距离WHO宣布新冠疫情大流行多久
import pandas as pd
from datetime import datetime
# 获取当前时间
now = datetime.now()
t2 = datetime(2020,3,11)
diff = now - t2
print(diff)
哦,原来已经两年多了,希望疫情快些结束吧!!!!!!
2. 将pandas中的数据转换成datetime对象——to_datetime()
- 可以使用to_datetime函数把数据转换成datetime类型。
示例:读取ebola数据文件,发现日期列数据格式无法识别,因此需要转换为datetime类型后再新开一列。
# 加载数据 并把Date列转换为datetime对象
ebola = pd.read_csv('data/country_timeseries.csv')
# 获取左上角数据,取前五行前五列
ebola.iloc[:5,:5]
#用ebola.info()查看发现文件中的日期类型并不标准,只能识别为object
# 因此需要调用to_datetime方法,将这一列转换后放入新的列中
ebola['date_dt'] = pd.to_datetime(ebola['Date'])
# parse_dates属性,数值为0说明0号列中是时间数据
ebola = pd.read_csv('data/country_timeseries.csv',parse_dates=[0])
# 最后再取前五行前五列观察一下数据的变化
ebola.iloc[:5,:5]
3. 提取日期的各个部分
- 可以通过Timestamp类型来获取年、月、日等部分的信息
示例:将Ebola数据中Date列日期信息,拆分为year、month和day三列。
# 新建year列,用来存储拆分出来的年份信息
ebola['year'] = ebola['Date'].dt.year
# 同时创建两列,分别存储月份和天信息
ebola['month'],ebola['day'] = (ebola['Date'].dt.month,ebola['Date'].dt.day)
# 查看指定四列数据中的前五条
ebola[['Date','year','month','day']].head()
4. 日期运算和Timedelta
- 可以结合Python自带函数,获取最大时间和最小时间
示例:Ebola数据集中的Day列表示一个国家爆发Ebola疫情的天数。这一列数据可以通过日期运算重建该列
疫情爆发的第一天(数据集中最早的一天)是2014-03-22。计算疫情爆发的天数时,只需要用每个日期减去这个日期即可。
# 获取疫情爆发的第一天
ebola['Date'].min()
能看到,Ebola疫情最早爆发时间是:
然后计算出疫情爆发天数,写入新建的“outbreak_d”列中,这个计算出的数据类型就是timedelta
ebola['outbreak_d'] = ebola['Date']-ebola['Date'].min()
ebola[['Date','Day','outbreak_d']].head()
5. 日期范围的处理——date_range函数
包含日期的数据集中,并非每一个都包含固定频率。比如在Ebola数据集中,日期并没有规律。
# 查看前五行和后五行数据
ebola.iloc[:,:5]
从上面的数据中可以看到,缺少2015年1月1日,2014年3月23日,如果想让日期连续,可以创建一个日期范围来为数据集重建索引。
- 可以使用date_range函数来创建连续的日期范围
date_range函数格式(start、end和periods三个参数至少指定两个):
date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None, **kwargs)
参数说明:
参数名 | 说明 |
start | 指定生成时间序列的开始时间 |
end | 指定生成时间序列的结束时间 |
periods | 指定生成时间序列的数量 |
freq | 生成频率,默认为‘D’,即时间跨度为一天。W为每周,M为每月,Q为每季度,B为工作日… |
小例子:
二、案例——丹佛市犯罪数据
任务说明:
- 读取csv文件,设置报警时间为索引。
- 查看2016年5月12号的报警记录。
- 查看2015年3月4日到2016年1月1日的犯罪记录。
- 查看凌晨两点到五点的报警记录
- 查看发生在5点47分的犯罪记录
- 计算每周的犯罪数量
- 分析每季度的犯罪和交通事故数据
1. 读取文件,设置索引。——read_csv()和set_index()
import pandas as pd
# 读取文件,用parse_dates将时间数据转换为日期格式
crime=pd.read_csv('data/crime.csv',parse_dates=['REPORTED_DATE'])
# 将报警时间这一列设置为索引
crime=crime.set_index('REPORTED_DATE')
(1)验证步骤:
首先需要执行crime.info(),检测文档中的REPORTED_DATE列是不是正确的datetime格式
然后需要执行crime.head(),看前五行的数据情况,检验索引是否设置成功,如果设置成功,索引列会放在最左边,数据如下图:
(2)特别注意:
最开始设置索引的语句中,设置完索引的对象我没有更新到crime中,写成了
crime.set_index(‘REPORTED_DATE’)
这样做的结果就是,索引一直不生效,加上inplace=True就可以了
# crime=crime.set_index('REPORTED_DATE')这一行也可以写成下述格式
crime.set_index('REPORTED_DATE',inplace=True)
(3)不懂就问:
这里为什么必须设置inplace?原有的列不能直接设置为索引吗?
2. 查看指定日期的记录——loc
- 查看2016年5月12日的犯罪记录。
注意,遇到这种查看指定日期或指定时间范围的问题,最好提前排序,后续直接对有序对象进行操作。
# 为了方便后续操作,这里将时间索引排序
crime_sort=crime.sort_index()
# 后续都对crime_sort对象进行操作
crime_sort.loc['2016-05-12']
正常情况下的运行结果如图:
特别注意:一定要保证上一步中的索引设置成功,我一开始由于索引没设置上,所以一直报错,而且KeyError中并没有明确指示,费老劲了。报错截图如下:
3. 查看指定日期范围的记录——loc
- 查看2015-3-4到2016-1-1时间段的犯罪记录。
- 若使用的是未经排序的crime,就需要在最后面加上sort_index()排一下序
crime.loc['2015-3-4':'2016-1-1'].sort_index()
- 若使用的是排序过的crime_sort,则可直接查看
crime_sort.loc['2015-3-4':'2016-1-1']
正常运行结果如图:
特别注意:由于我一开始索引没设置好,默认是按数字递增的索引,因此用loc拿到的数据也是错误的,错误截图如下:
4. 查看指定时间范围的报警记录——between_time()
- 查询凌晨两点到五点的报警记录
crime.between_time('2:00', '5:00', include_end=False)
运行结果如下:
5. 查看发生在某个时刻的犯罪记录——at_time()
- 查看发生在5点47分的犯罪记录
crime.at_time('5:47')
运行结果如下:
6. 按周统计——resample(‘W’)
为了统计每周的犯罪数量,需要按周分组。
这里用到了resample重采样,降低采样频率。
(1)调用resample()方法,设置为按周采样
crime_sort.resample('W')
分组结束后,需要用size查看一下分组大小
# size查看分组大小,即每周犯罪数量
weekly_crimes=crime_sort.resample('W').size()
weekly_crimes
然后可以检验一下分组结果,如len(crime_sort.loc[‘2012-1-9’:‘2012-1-15’])
执行后也输出1071,说明数据无误
(2)将按周分组的结果,做可视化处理
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
weekly_crimes.plot(figsize=(16,4),title="丹佛犯罪情况")
特别注意:
若标题上的中文显示为小方框,说明中文无法识别。
亲测事先引入matplotlib库设置中文后即可解决。
7. 分析季度数据——resample(‘Q’)
- 分析每季度的犯罪和交通事故数据。若犯罪用‘IS_CRIME’列表示,交通事故用’IS_TRAFFIC’列表示。
(1)用resample进行重采样,拿到季度数据。
crime_quarterly=crime_sort.resample('Q')['IS_CRIME','IS_TRAFFIC'].sum()
crime_quarterly
运行结果如下:
(2)所有日期都是该季度的最后一天,因此要使用QS生成每季度的第一天
crime_sort.resample('QS')['IS_CRIME', 'IS_TRAFFIC'].sum().head()
(3)【这里看不懂,**代表指针吗?望大神指路】作图
plot_kwargs = dict(figsize=(16,4), color=['black', 'blue'], title='丹佛犯罪和交通事故数据')
crime_quarterly.plot(**plot_kwargs)
8. 按是否工作日分析
- 分析工作日的犯罪情况:可以通过Timestamp的dt属性得到周几,然后统计
crime = pd.read_csv('data/crime.csv', parse_dates=['REPORTED_DATE'])
wd_counts = crime['REPORTED_DATE'].dt.weekday.value_counts()
wd_counts
总结
终于勉强把这个内容做了一遍。。。
关于最后那个案例,推荐这个文章:
《Pandas Cookbook》第10章 时间序列分析