惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
V
Vulnerabilities – Threatpost
T
Tenable Blog
Forbes - Security
Forbes - Security
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
S
Securelist
C
Cybersecurity and Infrastructure Security Agency CISA
Project Zero
Project Zero
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
Visual Studio Blog
WordPress大学
WordPress大学
Latest news
Latest news
K
Kaspersky official blog
T
Tailwind CSS Blog
T
Threat Research - Cisco Blogs
B
Blog RSS Feed
C
Cisco Blogs
博客园 - 聂微东
Martin Fowler
Martin Fowler
T
The Blog of Author Tim Ferriss
小众软件
小众软件
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
L
LINUX DO - 热门话题
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Privacy International News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CERT Recently Published Vulnerability Notes
Cisco Talos Blog
Cisco Talos Blog
S
SegmentFault 最新的问题
Security Latest
Security Latest
Y
Y Combinator Blog
爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
P
Privacy & Cybersecurity Law Blog
L
LINUX DO - 最新话题
月光博客
月光博客
The GitHub Blog
The GitHub Blog
博客园 - 三生石上(FineUI控件)
S
Security Affairs
P
Proofpoint News Feed
D
DataBreaches.Net
有赞技术团队
有赞技术团队
云风的 BLOG
云风的 BLOG

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
开放
2019-03-05 · via 少数派

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

开放

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 编程愉快(和出入平安)!

延伸阅读

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

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

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