从开放数据中,你可以了解一个城市或者社区是否安全,并合理避险。


开放

3月2日,应主办方 TechMill 的邀请,我参加了在达拉斯公共图书馆举行的“达拉斯-沃斯堡开放数据日”(DFW Open Data Day)。


为了鼓励我 INFO 5731 课程的学生们积极参加这项活动,我还制定了加分政策。


不过因为加分策略偏于保守,来的学生没有预期那么多。


利用 NCTCOG 提供的新 Waze 数据,我改进了之前在 HackNTX 2018 做的深度学习模型,取得了不小的进展。


对我而言,另一项收获,是参加了这次活动的主题报告。


报告人是 Richard ,他给参会的部分人员讲解了开放数据的定义、用途和使用方法。


虽然从2013年开始,我就在课程中为学生们讲解开放数据。但是从他的报告中,我依然收获了很多东西。

例如说,美国联邦政府和地方当局为什么要在网站上开放这么多数据?

要知道,一旦数据开放出来,普通人是可以对数据进行组织、包装和再分发,甚至是可以赚取经济利益的。

Richard 告诉我们,如果许多人都要求提供某一项数据,公务人员就有很大的动力把数据直接发布出来。因为这样,可以避免数据请求的巨大压力。

我把 Richard 的报告幻灯放在了“延伸阅读”模块里。如果你感兴趣,可以在读过本文后访问浏览。

Richard 还当场带领大家,以 Denton 市的犯罪记录开放数据为例,用 Excel 加以分析。

虽然“犯罪记录”听上去很让人不安。但是这种数据的公开,可以让大众了解到某个城市或者地区的治安情况。对于人们择业、选房、投资,甚至是日常出行和活动等决策,都可以提供辅助参考。

从这个讲座中,我收获良多。

本文,我借鉴 Richard 的分析思路,换成用 Python 和数据分析包 Pandas 对该数据集进行分析和可视化。希望通过这个例子,让你了解开放数据的获取、整理、分析和可视化。

希望你举一反三,把这种能力,应用到更多的数据集上,获得对数据的洞见。

数据

首先,访问 Denton 开放数据主页,地址是 http://data.cityofdenton.com/ 。


首页就有搜索栏,我们可以输入“crime”(犯罪)进行查询。

这是返回的搜索结果。


结果不仅包含数据名称,还有数据类型。第一条是 csv 格式,最符合我们分析的需求,因此我们点击第一项链接。


在这个页面,我们点击右侧蓝色“explore”旁边的下拉按钮,可以看到“预览”和“下载”选项。我们可以直接下载数据集。但此处请你复制下载链接,放到笔记软件或者编辑器里面,备用。

环境

本文的配套源代码,我放在了 Github 项目中。请你点击这个链接(http://t.cn/EIKS05O)访问。


如果你对我的教程满意,欢迎在页面右上方的 Star 上点击一下,帮我加一颗星。谢谢!

注意这个页面的中央,有个按钮,写着“在 Colab 打开”(Open in Colab)。请你点击它。

然后,Google Colab 就会自动开启。


Colab 为你提供了全套的运行环境。你只需要依次执行代码,就可以复现本教程的运行结果了。

如果你对 Google Colab 不熟悉,没关系。我这里有一篇教程,专门讲解 Google Colab 的特点与使用方式。

为了你能够更为深入地学习与了解代码,我建议你在 Google Colab 中开启一个全新的 Notebook ,并且根据下文,依次输入代码并运行。在此过程中,充分理解代码的含义。

这种看似笨拙的方式,其实是学习的有效路径

代码

首先,将我们前面获取到的数据下载地址,存入到 url 变量中。

url = "http://data.cityofdenton.com/dataset/17695047-0aeb-46a2-a9db-66847743ed1c/resource/d356a409-6764-46d7-942d-4d5a7ffb1c28/download/crime_data_20190301.csv"

然后,利用 wget 命令,把 csv 格式的数据下载到本地。

!wget {url}crime_data_20190301 100%[===================>]   9.22M  8.22MB/s    in 1.1s    2019-03-04 02:31:39 (8.22 MB/s) - ‘crime_data_20190301.csv’ saved [9667384/9667384]

读入 Pandas 软件包。

import pandas as pd

用 Pandas 的 csv 数据格式读取功能,把数据读入,并且存入到 df 变量里面。

df = pd.read_csv('crime_data_20190301.csv')

让我们看看 df 的前几行。

df.head()

好的,数据已经成功读取。

下面我们来着重分析一下,都有哪些犯罪类型,每种类型下,又有多少记录。

这里我们使用的是 Pandas 中的 value_counts 函数。它可以帮助我们自动统计某一列中不同类别出现的次数,而且还自动进行排序。为了显示的方便,我们只要求展示前10项内容。

df.crime.value_counts().iloc[:10]

看来, Denton 最主要的犯罪类型,是“轻微人身攻击”(Simple Assault)。“酒醉”(Drunkenness)的次数也不少,排名第三位。

为了更直观查看数据统计结果,我们调用 Pandas 内置的绘图函数 plot ,并且指定绘图类型为“横向条状图”(barh)。

df.crime.value_counts().iloc[:10].sort_values().plot(kind='barh')

这样看起来,一目了然。

下面,我们着重了解某一种犯罪的情况。因为犯罪类型五花八门,所以我们从中选择一种严重的暴力犯罪——抢劫(Robbery)。

这里,为了后续分析的便利。我们首先把抢劫类型的犯罪单独提炼出来,存储在 robbery 这样一个新的数据框里。

robbery = df[df.crime.str.contains('ROBBERY')]; robbery.head()

我们来看看 robbery 数据框的大小。

robbery.shape
(660, 6)

一共是660条记录,每条记录有6列。

我们查看一下“犯罪位置”(locname)类型,以及每种类型对应的记录条目数。

这次,我们使用 groupby 函数,先把犯罪位置进行分类,然后用 size 函数来查看条目统计。

这里,我们指定排序为从大到小。

robbery.groupby('locname').size().sort_values(ascending=False)

作为练习,希望你可以用 value_counts 函数,自己改写上面的语句。


根据结果显示,入室抢劫次数最多,在学校、公交车上发生的次数最少。

下面还是用 plot 函数,把结果可视化呈现。

robbery.groupby('locname').size().sort_values(ascending=False).head(10).sort_values().plot(kind='barh')

下一步,我们尝试把分析的粒度做得更加细致——研究一下,哪些街区比较危险。


回顾上图中,地址信息都表示为类似“19XX BRINKER RD”这样的方式。把具体地址的后两位隐藏,是为了保护受害者的隐私。

我们如果要统计某一条街道的犯罪数量,就需要把前面的数字忽略,并且按照街道名称加总。

这个处理起来,并不困难,只要用正则表达式即可。

regex = r"\d+XX\s(?P<street>.*)"subst = "\\g<street>"

这里,我们用括号把需要保留的内容,赋值为 street 分组。然后替换的时候,只保留这个分组的信息。于是前面的具体地址数字就忽略了。

调用 Pandas 的 str.replace 函数,我们可以让它自动将每一个地址都进行解析替换,并且把结果存入到了一个新的列名称,即 street

robbery["street"] = robbery.publicadress.str.replace(regex, subst)

看看此时新的 robbery 数据框样子。

robbery.head()

注意最后多出来的一列,确实已经变成了我们希望转换的形式。

依然按照前面的方法,我们分组统计每一条街道上的犯罪数量,并且进行排序。

robbery.groupby('street').size().sort_values(ascending=False).head(10)

看来,大学西道(W University DR)抢劫频发,没事儿最好少去瞎转悠。我住的街道还好,没有出现在前10名的范畴。

注意,我们其实是在分析10年的犯罪信息汇总。如果更进一步,想要利用时间数据,进行切分,我们就得把日期信息做一下转换处理。

这里,请你安装一个特别好用的时间分析软件包 python-dateutil 。我第一次使用的时候,立即决定弃用 datetime 包了。

!pip install python-dateutil

我们从 dateutil 里面的 parser 模块,载入全部内容。

from dateutil.parser import *

下面,我们抽取年度信息。因为目前的日期时间列(incidentdatetime)是个字符串,因此我们可以直接用 parse 函数解析它,并且抽取其中的年份(year)项。

robbery["year"] = robbery.incidentdatetime.apply(lambda x: parse(x).year)

以此类推,我们抽取“月”和“小时”的信息。

robbery["month"] = robbery.incidentdatetime.apply(lambda x: parse(x).month)
robbery["hour"] = robbery.incidentdatetime.apply(lambda x: parse(x).hour)

好了,来看看此时的 robbery 数据框。

robbery.head()

注意后三列是我们刚刚生成的。

我们先按照年度来看看抢劫犯罪数量的变化趋势。

robbery.groupby('year').size()

注意这里,数量最少的是 2019 年。看似是很喜人的变化。可惜我们分析数据的时候,一定要留心这种细节。

我们读取的数据,统计时间截止到 2019 年的 3 月初。因此,2019年数据并不全。

所以,比较稳妥的方法,是干脆去掉所有2019年的条目。

robbery = robbery[~(robbery.year == 2019)]

去除后,看看此时的 robbery 数据框。

robbery.shape
(643, 10)

数量没错,恰好少了 17 行。

好了,我们来绘制一下抢劫犯罪数量变化趋势折线图。

Pandas 的 plot 函数,默认状态下,就是绘制折线图。因此我们不需要加入参数。

robbery.groupby('year').size().plot()

看来,从 2013 到 2016 年的抢劫犯罪形成了一个低谷。近两年的数据,又有上行的趋势。

但是,我们能否就此得出结论,说 Denton 这两年的治安,越来越差了呢?

还不行。

因为考虑犯罪,不能只看绝对数值,还要看相对比例。我这里给你提供一个数据源,请你参考它,进行比例数值计算,修正上面的折线图。

下面,我们比较一下,不同月份之间,是否有明显的抢劫犯罪发生数量差别。

robbery.groupby('month').size().plot(kind='bar')

从上图中,可以看到,从 2010 到 2018 年,10月和12月犯罪数量较多,2月和7月相对好一些。

但是,我们可能更加关心近年的情况。因为扔掉了2019年的不完整数据,此时我们能使用的最近年份,是2018.

我们就把2018年的月份犯罪记录统计做可视化。

robbery[robbery.year==2018].groupby('month').size().plot(kind='bar')

2018年的10月,犯罪数量相对不算高,但12月看来确实是需要注意安全的。

下面我们来看看,抢劫一般发生在什么时间。这次我们用的,是小时(hour)数据。

robbery.groupby('hour').size().plot(kind='bar')

从总体数据看来,每天早上8点,你是不用太担心抢劫的;晚上23点嘛……

我们再看看2018年的情况。

robbery[robbery.year==2018].groupby('hour').size().plot(kind='bar')

8点依然比较安全。但是最危险的时段,变成了晚上8点多。莫非劫匪们也打算早点儿休息?

如果我们更加小心谨慎,还可以根据不同月份,来查看不同时段的抢劫案件发生数量。

这里,我们把 groupby 里面的单一变量,换成一个列表。于是 Pandas 就会按照列表中指定的顺序,先按照月份分组,再按照小时分组。

robbery[robbery.year==2018].groupby(['month', 'hour']).size()

但是这样的统计结果,无法直接绘制。我们需要做一个变换。这里用的是 Pandas 中的 unstack 函数,把内侧的分组索引(hour)转换到列上。

robbery[robbery.year==2018].groupby(['month', 'hour']).size().unstack(0)

因为许多时间段,本来就没有抢劫案件发生,所以这个表中,出现了许多空值(NaN)。我们根据具体情况,采用0来填充。Pandas 中数据填充的函数是 fillna

robbery[robbery.year==2018].groupby(['month', 'hour']).size().unstack(0).fillna(0)

好了,这下就可以可视化了。

我们希望绘制的,不是一张图,而是 12 张。分别代表 12 个月。这种图形,有个专门的名称,叫做“分面图”(facet plot)。 Pandas 的 plot 函数有一个非常方便的参数,叫做 subplots ,可以帮助我们轻松达成目标。

每张图,我们依然采用柱状图的方式。因为默认方式绘制的图像,尺寸可能不符合我们的预期。因此我们显式指定图片的长宽。

robbery[robbery.year==2018].groupby(['month', 'hour']).size().unstack(0).fillna(0).plot(subplots=True, kind='bar', figsize=(5,30))

你看了这张图以后,作何感想?

我觉得,每个月份,这张图对于哪个时段最好不要出门,都具备比较高的指导意义。因此……可以当成黄历来使用。

开个玩笑啦,别当真。

如果你对于图像的品质有追求,我建议你学用 Matplotlib 或者 seaborn 来重绘上图。这也作为今天的最后一道练习题,留给你解决。欢迎你把答案用留言的方式和大家分享。

小结

通过本文的学习,希望你已掌握了以下内容:

  1. 如何检索、浏览和获取开放数据;

  2. 如何用 Python 和 Pandas 做数据分类统计;

  3. 如何在 Pandas 中做数据变换,以及缺失值补充;

  4. 如何用 Pandas 中的 plot 函数做折线图、柱状图,以及分面图(facet plot)。

祝 Python 编程愉快(和出入平安)!

延伸阅读

你可能也会对以下话题感兴趣。点击链接就可以查看。

  • 学 Python ,能提升你的竞争力吗?

  • 如何高效学 Python ?

  • 《文科生数据科学上手指南》分享

  • Richard 在 DFW Open Data Day 的分享幻灯

喜欢请点赞和打赏。还可以微信关注和置顶我的公众号“玉树芝兰”(nkwangshuyi)。

如果你对 Python 与数据科学感兴趣,不妨阅读我的系列教程索引贴《如何高效入门数据科学?》,里面还有更多的有趣问题及解法。

由于微信公众号外部链接的限制,文中的部分链接可能无法正确打开。如有需要,请点击文末的“阅读原文”按钮,访问可以正常显示外链的版本。

知识星球入口在这里:


如何用 Python 和 Pandas 分析犯罪记录开放数据?相关推荐

  1. python使用pandas通过聚合获取时序数据的最后一个指标数据(例如长度指标、时间指标)生成标签并与原表连接(join)进行不同标签特征的可视化分析

    python使用pandas通过聚合获取时序数据的最后一个指标数据(例如长度指标.时间指标)生成标签并与原表连接(join)进行不同标签特征的可视化分析 目录

  2. python处理excel表格数据-利用Python处理和分析Excel表中数据实战.doc

    利用Python处理和分析Excel表中数据实战 [利用python进行数据分析--基础篇]利用Python处理和分析Excel表中数据实战 原创 2017年06月28日 15:09:32 标签: p ...

  3. python《pandas入门》实现Excel数据字段的拆分

    ** python<pandas入门>实现Excel数据字段的拆分 ,简单说一下自己为什么写博客,主要原因如下: 1,先简单介绍下自己,我是药学本科毕业,工作几年了.在这几年里做过药物相关 ...

  4. 如何用python进行相关性分析_Python 数据相关性分析

    概述 在我们的工作中,会有一个这样的场景,有若干数据罗列在我们的面前,这组数据相互之间可能会存在一些联系,可能是此增彼涨,或者是负相关,也可能是没有关联,那么我们就需要一种能把这种关联性定量的工具来对 ...

  5. 如何用python进行相关性分析_Python文章相关性分析---金庸武侠小说分析

    最近常听同事提及相关性分析,正巧看到这个google的开源库,并把相关操作与调试结果记录下来. 小说集可以百度<金庸小说全集 14部>全(TXT)作者:金庸 下载下来. 需要整理好格式,门 ...

  6. 如何用Python做情感分析?

    商品评论挖掘.电影推荐.股市预测--情感分析大有用武之地.本文帮助你一步步用Python做出自己的情感分析结果,难道你不想试试看? 需求 如果你关注数据科学研究或是商业实践,"情感分析&qu ...

  7. 如何用python进行相关性分析_使用 Python 查找分类变量和连续变量之间的相关性...

    在表格数据集上创建任何机器学习模型之前, 通常我们会检查独立变量和目标变量之间是否存在关系.这可以通过测量两个变量之间的相关性来实现.在 python 中, pandas 提供了一个函数 datafr ...

  8. python和excel数据分析_利用Python处理和分析Excel表中数据实战

    作为一个学习用Python进行数据分析的新手来说,通过本文来记录分享一些我在用Python中的pandas.numpy来分析Excel表中数据的数据清洗和整理的工作,目的是熟悉numpy以及panda ...

  9. 使用Python和Pandas的最简单的数据清理方法

    在本文中,我们将学习如何使用Python包Pyjanitor简化数据预处理工作.具体来说,我们将学习如何: 向一个Pandasdataframe(数据帧)中添加一个列 删除缺失的值 删除一个空列 清洗 ...

  10. 如何用python进行相关性分析_如何利用python进行时间序列分析

    题记:毕业一年多天天coding,好久没写paper了.在这动荡的日子里,也希望写点东西让自己静一静.恰好前段时间用python做了一点时间序列方面的东西,有一丁点心得体会想和大家分享下.在此也要特别 ...

最新文章

  1. PostgreSQL 批量权限 管理方法
  2. 结合typedef更为直观的应用函数指针
  3. android studio无线真机调试
  4. DEPHI中tform类的构造函数与FORMCREATE的关系
  5. python对话机器人框架_长篇文讲解:使用Python AIML搭建聊天机器人的方法示例(收藏)...
  6. bitmapdata的知识点
  7. ThreadLocal和线程同步机制的对比
  8. 12 计算机组成原理第七章 输入/输出系统 中断系统
  9. 2015第16周四自控力
  10. Python基础学习5 -字符串
  11. 剑指offer-06-旋转数组的最小数字
  12. spyder python下载_Spyder Python软件-Spyder Python下载-最火手机站
  13. 基于thinkphp6开放,免费开源可商用的兴趣社区论坛圈子小程序
  14. Word解决:以下内容无法保存在未启用宏的文档中: ●VBA工程 请单击“否“返回”另存为“对话框,然后在文件类型“下拉框中选择一种启用宏的文件类型。是否继续将其另存为未启用宏的文档?
  15. 服务器保密系统,泛微OA系统secWall保密方案之一:服务器端部署
  16. 如何在标准的机器学习流程上玩出新花样?
  17. 多人同时编辑excel,只需一招就搞定
  18. POJ 3691 AcWing 1053 修复DNA
  19. 当CNN遇见Transformer!华为诺亚提出CMT:新视觉Backbone
  20. compact php,如何使用php compact()函数

热门文章

  1. 外接显示器屏幕亮度调节
  2. 让临时停车号码牌会说话--鲁哇客智能挪车号码牌技术升级之路
  3. iOS开发中图片的模糊处理
  4. php 创建临时id_使用PHP创建ID3标签阅读器
  5. 白话电视:被移动设备抢走的光环,靠什么夺回来?
  6. Win8 配置局域网可以访问IIS网站
  7. 产生式系统Python PySide2的GUI界面
  8. c语言算兔子野鸡,“上山兔子下山鸡,离水甲鱼不要追”,有什么科学依据?...
  9. 怎么理解token,tokenize,tokenizer.
  10. 动辄上亿损失,网络安全谁来买单?