第 6 章 数据获取与存储
找到要研究的第一个数据集,可能是向回答问题这一目标迈出的最重要一步。在第 1 章里我们说过,你首先应该花点时间将问题细化,让问题足够具体,能够找到关于问题的好数据,同时问题又要足够宽泛,可以让你和其他人都感兴趣。
另一种可能是,你已经找到了感兴趣的数据集,但无法提出令人信服的问题。如果你不了解也不信任数据来源,应该花点时间调查一下。问问你自己:数据是否有效?是否更新过?我能否信任当前以及未来的更新和出版物?
本章我们会讲到,你可以将数据保存在什么地方,以供后续使用。如果你不熟悉数据库的话,我们也会讲到数据库的使用场景和使用方法,并演示如何创建简单数据库来存储数据。如果你已经很熟悉数据库,或者你的数据源就是一个数据库的话,我们会讲到 Python 中基本的数据库连接结构。
如果你还没决定使用哪个数据集的话,不必担心。下面用的几个例子,你都可以在本书仓库(https://github.com/jackiekazil/datawrangling)中找到。
我们强烈建议你带着几个问题阅读本书,这样你才能更好地在实践中学习。这些问题可能是你一直想研究的问题,也可能是与本书所探索数据相关的问题。即使你选取的问题很简单,在编写代码中学习也是最好的学习方法。
6.1 并非所有数据生而平等
对于遇到的每一个数据集,尽管我们愿意相信其真实性和数据质量,但并非所有数据都能符合我们的预期。即使是你目前使用的数据集,在深入研究之后也可能是无用且无效的数据源。对于你面临的数据处理问题,在寻求自动化解决方案时,你会发现 Python 工具可以帮你分辨好数据和坏数据,还可以帮你评价数据的可用性。第 7 章和第 8 章会讲到用 Python 做数据清洗和数据探索,第 14 章会讲到自动化,在这些章节里我们都会介绍关于这些工具的更多内容。
刚刚得到新数据时,我们建议做一个数据气味测试,测试该数据是否是可靠的信息源,并决定是否信任该数据。你可以问问自己以下几个问题。
如果我有问题或疑虑的话,能够联系上作者本人吗?
数据是否定期检查错误并更新?
数据里是否包含数据获取方法的信息,是否包含数据获取过程中使用的样本类型?
有没有其他数据源可以验证这个数据集?
根据我对这个话题了解的所有知识,数据看起来是否可信?
如果你对至少三个问题的回答都是“是”,这说明你走对路了!如果至少对两个问题的回答是“否”,你可能需要花更多时间寻找可靠的数据。
你可能需要联系最初采集数据并发布的作者或机构,以寻求更多信息。通常情况下,给合适的人打电话或发电子邮件,可以帮你回答上面至少一个问题,并验证数据源的可靠性。
6.2 真实性核查
为保证报告的可信,对你的数据做真实性核查是非常重要的,尽管有时可能既烦人又累人。根据数据集的不同情况,真实性核查可能包括以下内容。
联系数据源,核实最新的方法和版本。
找到其他好的数据源作对照。
联系专家,探讨好的数据源和真实信息。
进一步研究你选定的主题,检查你的数据源和 / 或数据集是否可信。
有些图书馆和大学可以访问只对订阅用户开放的出版物和教育档案,它们是真实性核查的重要资源。如果可以访问类似 LexisNexis(http://lexisnexis.com/)、国会季刊新闻库(http://library.cqpress.com/)、JSTOR(http://jstor.org/)、康奈尔大学的 arXiv 项目(http://arxiv.org/)和谷歌学术搜索(http://scholar.google.com/)这样的工具,你可以看一下其他人对你的主题已经做了哪些研究及研究成果。
谷歌搜索也可以在真实性核查方面提供帮助。如果某人宣称数据来自于公开发布的来源,那么有可能其他人已经对这一说法做过真实性核查,或者已经证实了这一说法。同样,在评价网上发布的内容时,你需要自己仔细斟酌。数据源是否真实?论证能否令人信服,是否有意义?证据是否有效?对这些问题的回答要做综合评价。
政府部门拥有大量的数据集。如果想研究本地城市、州或国家的某一现象,通常你可以通过电话或电子邮件找到某个人,他手头有很有用的数据集。全球人口普查局会定期发布普查数据,如果你纠结于想要回答什么问题,可以从这些数据开始。
对第一个数据集做过验证和真实性核查之后,以后编写脚本验证数据有效性就会容易很多。你甚至可以用在本书中学到的技巧(特别是第 14 章的内容)创建脚本来自动更新数据。
6.3 数据可读性、数据清洁度和数据寿命
如果你的数据集看起来非常难以读取,还有一种可能的方法:根据第 7 章学习的内容,你可以用代码清洗数据。幸运的是,如果是计算机创建的数据,很有可能可以被计算机读取。更大的难点在于,从“真实生活”中获取数据并读入计算机。在第 5 章中我们知道, PDF 和不常见的数据文件类型很难处理,但并非不可能。
我们可以用 Python 帮我们读取难以读取的数据,但难以读取可能意味着数据来源不佳。如果是计算机生成的大型数据集,那就存在一个问题——数据库转储(database dump)的格式一直都不美观。但如果你的数据是人工生成的,而且难以读取,那可能是数据清洁度和数据有效性的问题。
你面临的另一个问题是,数据是否已经被清洗过了。通过详细询问数据是如何采集、报告并更新的,你可以判断数据是否被清洗过。你应该能够确定以下内容。
数据的清洁度有多高?
是否有人给出了统计误差率,或者修改了错误的数据条目,或者误报了数据?
是否会发布进一步更新,这些更新是否会发送给你?
数据采集过程中使用了哪些方法,如何验证这些方法?
如果你的数据源使用的是标准化的、严谨的研究和采集方法,在未来的几年里,你的清洗脚本和报告脚本可能几乎不用修改就可以重复使用。那些系统通常不会定期发生变化(变化既费钱又费时)。一旦写好了清洗脚本,你可以轻松处理下一年的数据,直接进入数据分析阶段。
除了清洁度和可读性,你还要关注数据的寿命。你要处理的数据是定期采集并更新的吗?数据发布和更新的时间计划是什么样的?了解一个机构更新数据的频率,可以让你判断在未来几年内对该数据的应用能力。
6.4 寻找数据
就像验证数据源或编写 PDF 解析器脚本有不止一种方法一样,寻找数据也有很多种方法。本节会讲到你在线上和线下都可以使用的方法。
6.4.1 打电话
观察数据文件,并思考一个问题:数据是怎么变成现在这种格式的?通常来说,像 Excel、 PDF 甚至 Word 这样的文件类型都是人工处理的,这个人从数据源处获取数据。
如果你找到了采集数据的那个人,或许可以要到原始数据。原始数据可能是易于解析的文件格式,如 CSV 或数据库。你找到的那个人还可以回答关于采集方法和更新时间线的问题。
下面给出从数据文件中找人的一些技巧。
在文件中搜索联系人信息。
寻找署名——如果没有人名,那就寻找机构名。
在网络上搜索文档的文件名和标题。
右键单击文件,在 Windows 上选择“属性”(在 Mac 上选择“显示简介”),查看文件元数据。
去联系你能找到的每一个人。如果他不是创建文件的人,可以问他知不知道是谁创建的文件。不要害羞——你对他们的研究课题和工作感兴趣,就是对他们的恭维,他们会很乐意帮助你的。
与通信官打交道
如果你遇到这种情况——发布文件的机构希望你能和他们的通信代表谈一谈——这意味着时间可能会拖得很长。还记得一个叫作打电话的游戏吗:第一个人跟另一个人说了些什么,另一个人将所听到的内容复述给下一个人,如此这般,最后一个人的话已经与第一个人大相径庭?
要保证有效沟通,你可以做这两件事情。第一,努力建立信任。如果没有利益冲突,你可以分享你感兴趣的工作,并承诺会将该机构列为数据源。这表示你会间接宣传他们的工作,该机构也会在分享资料方面受到好评。第二,请求通信代表召开电话会议或有监督的讨论。通过电话而不是电子邮件沟通,你可以及时准确地得到问题的回答。
找到了要联系的人之后,尝试用电话联系他,或者亲自拜访。电子邮件很容易引起误会,通常时间也会拖得比较长。下面给出几个问题的例子,可以帮你思考要问什么样的问题。
你是如何获取第 6 页到第 200 页的数据的?
是否有其他格式的数据,比如 JSON、CSV、XML 或数据库?
数据是如何采集的?
能否描述一下数据采集的方法?
这些缩写是什么意思?
数据是否会更新?如何更新?何时更新?
是否有其他人能提供更多信息?
在等待回答的同时,你也可以开始做数据探索,这取决于项目的时间限制和目标。
6.4.2 美国政府数据
如果你对研究美国的现象感兴趣,奥巴马政府最近正在推行发布易于获取的在线数据,可以很容易找到政府机构的定期报告。快速浏览一下 Data.gov 网站,你就会发现暴雨数据(http://catalog.data.gov/dataset/ncdc-storm-events-database)、毕业率和辍学率(http://catalog.data.gov/dataset/edfacts-graduates-and-dropouts-201112)、濒危物种数据(http://catalog.data.gov/dataset/density-of-threatened-and-endangered-species)、犯罪统计(https://catalog.data.gov/dataset/total-crime-index-for-thenations-largest-cities-3a1aa)以及其他有趣的数据集。
除了联邦数据,州政府和地方政府也都有发布数据的网站,下面我们列出了其中几个:
人口普查数据(http://census.ire.org/)
劳工统计数据(http://www.bls.gov/)
如果在公开发布的信息里找不到你想要的,不要犹豫,直接给相应部门打电话,在电话里请求提供数据。许多政府部门都有实习生或工作人员负责处理公众获取信息的请求。
信息自由法案介绍
在美国,你可以向任意地方、州或联邦的政府机关提交信息自由法案(FOIA)申请。申请应简单明了。根据你请求的信息内容以及描述的详细程度,需要用的时间可能会有很大不同。
美国政府建立了 FOIA 网站(https://foiaonline.regulations.gov/foia/action/public/home),你可以在上面向特定部门提交申请并追踪,但大部分政府机构都有在自己的网站上如何提交 FOIA 申请的说明。你应该在申请中给出联系信息,描述你要找的数据记录,以及如果有复印费的话你愿意交多少钱。
好的做法是,尽可能详细描述你要找的数据记录,但又不过分限制搜索的范围。你可以这么想,搜索范围太宽泛,网站会返回数百万条记录(你需要手动挑选,可能还要付费)。另一方面,如果搜索过于具体,你可能会漏掉与话题密切相关的记录。当然了,根据你第一次申请找到的信息,你总可以提交更多的 FOIA 申请。搜索过程也很有意思,不是么?
如果你想要的是美国之外政府和机构的信息,维基百科给出了世界各国信息自由法律的列表(https://en.wikipedia.org/wiki/Freedom_of_information_laws_by_country)。想了解关于美国 FOIA 的更多内容,可参阅电子前沿基金会(Electronic Frontier Foundation)的建议(https://www.eff.org/issues/transparency/foia-how-to)。
6.4.3 全球政府和城市开放数据
获取政府数据有很多种方法,这取决于你想研究的国家,以及你是否生活在那个国家。由于我们更熟悉美国的政策,所以我们不会宣称这是一份全面的清单。如果你想要分享本书没有提到而又很有用的开放数据,请随时和我们联系!
我们建议对政府数据集也要做真实性核查,特别是对有侵犯人权历史的政府更要仔细核查。将所有的判断力用到所有数据上,果断给联系人打电话或发邮件,进一步咨询数据的采集方法。
- 欧盟和英国
如果你对欧盟或英国的数据感兴趣,可以找到许多数据门户网站。下面一些网站是由一些机构和开放数据爱好者创建的,如果你想寻找特定的数据集,可以和网站所有者直接联系。
欧盟开放数据(http://publicdata.eu/)
欧罗巴开放数据(http://opendata.europa.eu/)
全天开放关联数据(http://latc-project.eu/)
英国政府数据(https://data.gov.uk/)
- 非洲
如果你对非洲国家的数据感兴趣,有许多项目正在采集数据并构建 API,供开发人员使用。许多非洲国家也有自己的开放数据门户网站(<用谷歌一搜就可以找到>)。我们挑出了一些有用的区域性项目:
非洲开放数据(https://africaopendata.org/)
南非代码(http://code4sa.org/)
非洲的开放数据(http://opendataforafrica.org/)
- 亚洲
如果你对亚洲国家和地区的数据感兴趣,它们大多数都有自己的开放数据网站。我们找出了几个令人印象深刻的数据集,以及一些机构发布的区域性数据:
开放尼泊尔(http://data.opennepal.net/)
中国国家统计局(http://www.stats.gov.cn/english/)
香港开放数据(https://opendatahk.com/)
印尼政府开放数据(http://data.go.id/)
- 欧盟以外的欧洲、中亚、印度、中东和俄罗斯
在欧盟之外,许多中亚、中欧和中东的国家也有自己的政府开放数据网站。我们给出了其中一些网站,但如果你知道你想研究的国家和地区并希望用母语来访问相关数据,语言技能是最重要的(<谷歌 Chrome 浏览器会尝试自动翻译网页,所以即使语言不通也可以找到有用的数据>)。
俄罗斯政府数据网站(http://data.gov.ru/)
PakReport——巴基斯坦开放数据和地图(http://pakreport.org/)
印度开放数据(https://data.gov.in/)
土耳其开放统计数据(http://www.turkstat.gov.tr/Start.do)
- 南美和加拿大
许多南美国家都有自己的开放数据网站,通过搜索很容易找到。加拿大也有针对统计数据的开放数据门户网站。我们给出了其中一些网站,同时建议你去网上搜索,寻找你感兴趣的特定部门或政府。
加拿大开放数据(http://open.canada.ca/en)
巴西开放数据(http://dados.gov.br/)
墨西哥开放数据(http://datos.gob.mx/)
拉丁美洲开放数据(http://www.opendatalatinoamerica.org/)
发展中的加勒比地区(https://www.developingcaribbean.org/#/)
6.4.4 组织数据和非政府组织数据
无论是地方组织还是国际组织,都有大量跨州或跨国的数据集资源,比如气候变化数据、国际商贸数据和全球运输数据。如果政府并没有采集与你的主题相关的数据(关于宗教细节、吸毒、社区支持网络等的数据),或者政府数据不可靠,或者政府没有开放数据门户网站的话,你可以通过 NGO 或开放数据组织找到相关数据。下面列出了一些组织,但还有更多的组织在为数据的公开交换和访问而奋斗。
联合国开放数据(http://data.un.org/)
联合国发展计划署数据(http://open.undp.org/)
开放知识基金会(https://okfn.org/)
世界银行数据(http://data.worldbank.org/)
维基解密(https://wikileaks.org/)
国际援助透明度数据集(http://www.iatiregistry.org/)
DataHub(https://datahub.io/)
6.4.5 教育数据和大学数据
世界各地的大学和研究生部都在不断地研究并发布数据集,从生物科学的进展到本土文化与周边生态栖息地的关联性,涵盖范围很广。很难想象教育领域还没有讨论过某一主题,所以大学是获取最新专题数据的好去处。大多数研究者都乐于听到有人对他们的课题感兴趣,所以我们建议你直接联系合适的部门或作者,以获取更多信息。如果你不知道从哪里开始,下面有几个不错的选择。
Lexis Nexis(http://www.lexisnexis.com/)
谷歌学术搜索(https://scholar.google.com/)
康奈尔大学 arXiv 项目(http://arxiv.org/)
UCI 机器学习数据集(http://archive.ics.uci.edu/ml/)
通用数据集倡议(http://www.commondataset.org/)
6.4.6 医学数据和科学数据
与大学类似,科学和医学研究部门和组织也都拥有大量优质的数据资源。在科学研究中搜索是十分困难的,但不要气馁——如果你能找到用于研究的数据集,它们使用的研究术语往往并不相同。如果你想到某一个特定的研究者,我们建议直接联系他。下面列出了一些汇总的数据集:
世界卫生组织数据(http://www.who.int/gho/database/en/)
Broad 研究所开放数据(http://www.broadinstitute.org/scientific-community/data)
人类连接组项目(<神经通路映射>)(http://www.humanconnectomeproject.org/)
UNC 精神病基因组协会(http://www.med.unc.edu/pgc/)
社会科学数据集(http://3stages.org/idata/)
CDC 医学数据(http://www.cdc.gov/nchs/fastats/)
6.4.7 众包数据和API
如果你的想法或问题更适合众包,则可以利用互联网及大量的论坛、服务和社交媒体来创建自己的问题,并用数据挖掘方法找到这些问题的答案。像 Twitter 和 Instagram 这样的服务拥有数亿用户,上面还有好用的应用编程接口(API)。API 是一些协议或工具,允许用软件或代码与另一个系统交互。在我们的例子中,我们使用的一般是基于网络的 API,可以发送网络请求并从服务中获取数据。一般来说,不到一个小时的设置,API 访问就可以获取数百万条数据记录。
在第 13 章我们会更深入地介绍 API,现在,我们在表 6-1 中对比了使用 API 的一些基本优点和缺点。
表6-1:使用API
优点 | 缺点 |
---|---|
即时访问可用的数据 | 大量 API 系统不可靠(选择性偏差) |
数据量很大 | 数据过载 |
你不必担心存储问题,你可从服务的存储中访问数据 | 可靠性问题,依赖于 API 访问限制或停机时间 |
可以看到,API 的优点和缺点各占一半。如果找到一个你想用的 API,你可以制定一些规则,规定如何使用 API,以及 API 无法访问时应该怎么做(你可能希望把响应内容保存在本地,避免遇到停机问题)。长时间对响应内容进行采集,也可以消除研究中的一些选择性偏差。
除了社交网络服务之外,还有许多网站可以发布你的问题和想法,以寻求众包回答。选择与话题相关的专家论坛,还是自己发布调查并利用自己的频道传播,这由你自己决定,但如果用的是你自己的研究问题和方法,你一定要对样本大小和样本误差作出解释。想要做附带详细引文的抽样调查,更详细的介绍内容可优先参考威斯康星大学的调查指南(http://oqi.wisc.edu/resourcelibrary/uploads/resources/Survey_Guide.pdf)。
想了解其他方面的众包数据,可查看:
盖洛普民意调查(http://www.gallup.com/)
路透社民意调查(http://polling.reuters.com/)
可用的数据量是巨大的,在大量的噪声数据中,找出你能回答的问题并搞清楚应该如何回答这些问题,可不是一件容易的事情。下面我们讲几个案例研究,让你更好地了解如何寻找数据来回答自己的问题。
6.5 案例研究:数据调查实例
我们将简单介绍几个不同的兴趣领域和问题,这样你可以知道第一步该做些什么。
6.5.1 埃博拉病毒危机
比方说,你对调查西非的埃博拉病毒危机感兴趣。你会怎么开始调查?你可能很快会想到用谷歌搜索“Ebola crisis data”(埃博拉病毒危机数据)。你发现有许多国际组织致力于追踪病毒的传播,这些组织提供了许多工具,任你使用。首先,你会找到 WHO 的情况报告(http://apps.who.int/ebola/ebola-situation-reports)。WHO 网站上有关于最新病例和死亡的信息,还有交互式地图显示受影响的地区,以及应对措施的关键绩效指标,这些内容似乎都是每周更新。数据有 CSV 和 JSON 两种格式,是真实可靠、定期更新的信息来源。
你要不断挖掘寻找其他可用的资源,而不是在出现的第一个结果这里就止步不前。经过进一步搜索,我们找到 GitHub 用户 cmrivers 的仓库(https://github.com/cmrivers/ebola),里面是来自许多政府和媒体数据源的原始数据汇总。由于我们知道该用户,可以通过联系方式联系到他们,所以我们还可以核实数据最近一次的更新时间,并咨询任何与数据采集方法有关的问题。我们学过如何处理这些数据格式(CSV、PDF 文件),所以处理起来应该不成问题。
进一步深入挖掘,你可能会专注于一个具体的问题,比如:“在安全下葬方面采取了哪些预防措施?”你找到一份由 Sam Libby(https://data.humdata.org/user/libbys)维护的报告,报告内容是关于安全、庄严的葬礼的(https://data.humdata.org/dataset/safe-and-dignified-burial-teams)。太棒了!遇到任何问题你都可以直接联系 Sam。
你已经找到了一系列很好的初始数据源,并确认它们来自你信任的组织,同时还找到了联系人,在研究过程中可以向他寻求更多信息。下面我们来看另一个例子。
6.5.2 列车安全
再比方说,你对美国的列车安全感兴趣。你的问题可能是:有哪些影响列车安全的不利因素?首先,你可能看过之前关于列车安全的研究。你找到了联邦铁路管理局(FRA),其核心职责就是确保铁路安全可用。在 FRA 网站上(https://www.fra.dot.gov/)阅读了一些报告和情况简报后,你发现大部分报告都显示,列车事故发生的原因是轨道养护不佳或人为失误。
你对人为失误更感兴趣,所以决定深入挖掘这一点。你发现 FRA 在铁路员工和安全方面发布了大量的报告。你找到一份关于铁路工人睡眠类型的报告(http://catalog.data.gov/dataset/work-schedules-and-sleep-patterns-of-railroad-employees-train-and-engine-service),可以部分解释人为失误发生的原因。你还找到联邦法规关于对铁路员工做药物和酒精测试的一些资料(http://www.fra.dot.gov/eLib/details/L02699)。
现在你可能有更多的问题,你可以将范围缩小,详细阐述你真正想了解的问题。现在你的问题可能会变成“喝酒导致的铁路事故发生频率是多少”或者“火车工程师加班或劳累过度的频率是多少”。你已经有了初步的可信数据集,还可以在研究过程中致电 FRA 了解更多信息。
6.5.3 足球运动员的薪水
再比如说,你对足球(用脚踢的足球,不是猪皮做的橄榄球)运动员的薪水感兴趣。这些运动员能赚多少钱,每个运动员对球队的影响有多大?
初次搜索之后,你发现数据太杂,决定专注研究某一个联赛。比方说你选择英超联赛。你在一个可能从没听说过的网站上找到了英超俱乐部的薪水列表(http://www.tsmplug.com/football/premierleague-player-salaries-club-by-club/)。看来作者已经编辑好了每一支球队的列表,以及每一名球员的薪水列表(http://www.tsmplug.com/football/mancity-players-salaries-2014/)。为了更好地理解数据的来源,并保证数据源可信,你应该联系页面中给出的作者,以获取更多信息。
如果你同时搜索球员代言,可能会找到这个统计表(http://www.statista.com/statistics/266636/best-paid-soccer-players-in-the-2009-2010-season/),里面列出了顶薪足球运动员的代言费用和薪水数据。你可能也想去联系作者,询问是否有最新的代言费用数据,可以和最新的赛季作对比。
现在你已经有了薪水数据,你还想了解一些统计数据,看看顶薪运动员究竟有多优秀。你在英超联赛网站(http://www.premierleague.com/content/premierleague/en-gb/players/index.html)上找到一些球员统计数据。这可能是你只能用网络抓取来获取的数据(第 11 章会有更多关于网络抓取的内容),但你知道数据来源是可靠的。继续搜索球员统计数据,你可能会在 top assists 网站(http://www.espnfc.com/barclays-premier-league/23/statistics/assists)上找到更多数据。你还可以分析点球统计数据(http://eplreview.com/statistics-penalty.htm)。同样,你应该调查任何数据源的有效性,这一点并不容易验证。
现在你可以开始数据分析,计算每一名球员进球、红牌和点球的价值!
6.5.4 童工
最后,我们来探索一个本书后续章节将要回答的问题。我们将专注研究国际童工危机。当思考国际话题时,我们立刻想到要寻找国际组织。
我们发现 UNICEF 的开放数据网站致力于发布童工报告(http://data.unicef.org/child-protection/child-labour.html)。事实上,UNICEF 拥有全球妇女儿童健康状况的全部数据集(http://mics.unicef.org/)。这些数据集可能对回答类似“早婚对童工率是否有影响?”这样的问题很有帮助。
在寻找政府数据时,我们找到了美国劳工部关于全球童工的年度报告(https://www.dol.gov/agencies/ilab/resources/reports/childlabor)。这些报告可以用来与 UNICEF 的数据集相互对照。
另外,我们还找到国际劳工组织(ILO)关于童工的趋势报告(http://www.ilo.org/ipec/Informationresources/WCMS_IPEC_PUB_23015/lang—en/index.htm)。ILO 报告似乎给出了许多不同数据集的链接,应该是童工历史数据的很好参考。
我们还汇总了下面几章会用到的几个数据集。我们将这些数据集都放在数据仓库中(https://github.com/jackiekazil/datawrangling),以便后续使用。
前面已经探讨了如何发现问题并搜索资源,下面我们来看一下数据存储。
6.6 数据存储
找到数据之后,你需要把数据保存下来!有些时候,你得到的数据是干净的、易于访问的、机器可读的格式。其他时候,你可能想用另一种方法来保存数据。当你第一次从 CSV 或 PDF 中提取数据的时候,我们会讲到几种数据存储工具,或者,你可以等数据完全处理并清洗完成后再进行存储(我们会在第 7 章讲到数据清洗的内容)。
我应该把数据保存在哪里?
最开始的问题是,要将数据保存到其他地方,还是留在最开始提取的文件中。这有一系列问题可以帮你回答这个问题。
你能否用简单的文档阅读器(例如 Microsoft Word)打开数据集,同时不会造成计算机死机?
数据看起来是否具有良好的标签和结构,让你可以方便提取出每一段信息?
如果需要不止一台电脑来处理数据的话,数据的保存和移动是否方便?
能否利用 API 实时访问数据,这样你就能在线获取需要的数据?
如果所有问题的回答都是“是”,你可能不必担心保存数据的问题。如果你的回答有“是”有“否”的话,可能需要将数据保存在数据库或平面文件(flat file)中。如果所有问题的回答都是“否”,继续读下去,我的朋友,我们为你提供了解决方法!
假设你的数据集各不相同——这里的一个文件,那里的一份报告。其中一些很容易下载和访问,但其他的你可能需要从网络上复制或抓取。第 7 章和第 9 章中会讲到如何清洗与合并数据集,但现在我们来谈一谈如何将数据保存在共享位置。
如果你要用的数据集来自多台电脑,建议你把它们都保存在网络或互联网中(你好,云计算!),或者保存在移动硬盘或 U 盘中。当你和团队合作时,团队成员可能会从不同地点或不同电脑访问数据,一定要记住这一点。如果你在一台计算机上工作,一定要有数据备份策略。电脑丢失最糟糕的一点就是,你花几个月时间获取并清洗的数据也丢失了。
6.7 数据库简介
数据库——初学生爱,爱极生恨。作为开发人员,你可能会在学习和工作中用到各种类型的数据库。本节不会对数据库做全面介绍,但我们希望对数据库基本概念做一个简要介绍。如果你已经熟练掌握数据库的使用,可以大致浏览一下本节,继续阅读关于其他存储方案以及何时使用数据库的内容。
你用 Siri 查过手机里的电话号码么?你用过谷歌搜索么?你有没有点击过 Twitter 或 Instagram 里的标签?这些操作都涉及对数据库(或一系列数据库,或数据库缓存)的简单查询和响应。你有一个问题[在 YouTube 上新出了哪些关于猫(Maru)的有趣视频?],你向一个特定的数据库(YouTube 搜索)提问,得到有趣的响应——可以观赏的搜索结果列表。
在接下来的几节里,我们将简要讲述两种主要的数据库类型,强调了各自的利弊,并对比了二者的优点和缺点。对于数据处理来说,你绝对不需要使用数据库,然而,随着数据处理和分析变得更加复杂,数据库知识及其使用将变得更加重要,可以提高你存储和分析数据的能力。
如果你对数据库感兴趣,我们会讲到用 Python 处理数据库的几个技巧,但显然我们没有足够的时间全面讲述这个话题。我们强烈推荐你根据自己的兴趣去搜索更多的资料、视频和教程。
6.7.1 关系型数据库:MySQL和PostgreSQL
对于来源很多、同时还有各种层次关联性的数据,关系型数据库是很好用的。关系型数据库正如其名:如果你的数据连接类似于家谱,那么关系型数据库可能会适合你,比如 MySQL。
关系型数据库通常使用一系列唯一标识符来匹配数据集。在 SQL 里我们一般把这些标识符叫作 ID。这些 ID 可以被其他数据集所用,用来查询和匹配数据连接。在这些连接好的数据库中,我们可以进行 join 操作,在许多不同的数据库中同时访问连接的数据。我们来看一个例子。
我有一个特别厉害的朋友,叫 Meghan。她有一头黑发,在《纽约时报》工作。在工作之余,她喜欢跳舞、烹饪和教人如何编程。如果我有一个关于朋友的数据库,使用 SQL 代表他们的属性,我可能会这样分表:
**friend_table: ➊
friend_id ➋
friend_name
friend_date_of_birth
friend_current_location
friend_birthplace
friend_occupation_id
**friend_occupation_table:
friend_occupation_id
friend_occupation_name
friend_occupation_location
**friends_and_hobbies_table:
friend_id
hobby_id
**hobby_details_table:
hobby_id
hobby_name
hobby_level_of_awesome
❶ 在我的朋友数据库中,每一部分(以 **
表示)都是一个表。在关系型数据库中,表通常用来保存特定主题或特定对象的信息。
❷ 表中包含的每一条信息叫作字段。在这个例子中,friend_id
字段包含 friend_table
中每一位朋友的唯一 ID。
我可以向数据库提问:Meghan 的爱好是什么?想要获取这个信息,我需要对数据库说:“嘿,我要查询我的朋友 Meghan。她住在纽约,这是她的生日,你能告诉我她的 ID 吗?”对于这条查询,SQL 数据库返回的是她的 friend_id
。然后我可以向 friend_and_hobbies_table
提问(这个表正确匹配了朋友 ID 和爱好 ID),与这个朋友 ID 匹配的爱好是什么,它会返回由三个新的爱好 ID 组成的列表。
由于这些 ID 都是数字,我想进一步了解它们的含义。我向 hobby_details_table
提问:“你能告诉我关于这些爱好 ID 的更多内容吗?”它回答:“当然可以!一个是跳舞,一个是烹饪,一个是教人如何编程。”啊哈!只利用最开始的朋友描述,我就解开了这个谜题。
创建数据库并向其中导入数据可能涉及许多步骤,但如果你的数据库很复杂,有许多不同的关系,那么搞清楚如何连接这些数据并找到你想要的信息,步骤不应该很复杂。在构建关系型数据库时,花点时间研究关系和属性之间的映射,类似我们在朋友数据库所做的那样。都有哪些不同的数据类型,它们之间是如何映射的?
在关系型数据库架构中,通过思考数据的使用频率,我们知道要如何匹配数据。你希望向数据库请求的查询易于回答。由于我们可能会用职业来寻找对应的朋友,所以我们将 occupation_id
放在 friend_table
表中。
还需要注意的是,关系有许多不同的类型。例如,我有许多朋友的爱好都是烹饪。我们把这种情况称为多对多关系。如果我们再添加一个叫作 pets
的表,就会新增加一种关系类型——多对一关系。这是因为有些朋友养了不止一只宠物,但每只宠物只能有一个主人。我可以使用 friend_id
查询每一位朋友的所有宠物。
如果你有兴趣深入学习 SQL 和关系型数据库的内容,我们建议在 SQL 上多花点时间。入门 SQL 可以在“Learn SQL The Hard Way”(http://sql.learncodethehardway.org/)和“SQLZOO”(http://sqlzoo.net/)这两个网站上学习。PostgreSQL 和 MySQL 在语法上有一些细微的差别,但它们的基础知识相同,你可以自己选择学习哪一个。
- MySQL和Python
如果你熟悉 MySQL(或正在学习 MySQL),想要使用 MySQL 数据库,那么用 Python 连接 MySQL 是很容易的。你需要做的只有两步。第一步,你必须安装 MySQL 驱动程序。第二步,你应该用 Python 发送验证信息(用户名、密码、主机名、数据库名称)。这两步在 Stack Overflow 上都可以找到很多优质的回答(http://stackoverflow.com/questions/372885/how-do-i-connect-to-a-mysql-database-in-python)。
- PostgreSQL和Python
如果你熟悉 PostgreSQL(或正在学习 PostgreSQL),想要使用 PostgreSQL 数据库,那么用 Python 连接 PostgreSQL 也是很容易的。你也只需要做两步:安装驱动程序,用 Python 连接。
Python 的 PostgreSQL 驱动程序有很多(https://wiki.postgresql.org/wiki/Python),但最流行的是 Psycopg(http://initd.org/psycopg/)。在 Psycopg 的安装页面(http://initd.org/psycopg/docs/install.html)中详细介绍了如何在电脑上运行 Psycopg,在 PostgreSQL 网站上也有关于 Python 如何使用 Psycopg 的详细介绍(https://wiki.postgresql.org/wiki/Psycopg2_Tutorial)。
6.7.2 非关系型数据库:NoSQL
比方说,你喜欢使用数据库这个主意,但映射出所有关系会让你抓狂。可能只是因为你目前没有真正理解数据的连接方式,也可能是因为你用的是平面数据(flat data,也就是说,不必良好映射的无关系数据),或者也可能是因为你对学习 SQL 没有更强烈的兴趣。幸运的是,还有一种适合你的数据库。
NoSQL 以及其他非关系型数据库将数据保存成平面格式(flat format),通常是 JSON 格式。我们在第 3 章中说过,JSON 查找信息的方法很简单。回到上一节关于我朋友的数据,如果我只有保存在节点中的数据,通过这些节点可以查询该朋友的更多信息,那我应该怎么做?数据看起来可能是这样的:
{
'name': 'Meghan',
'occupation': { 'employer': 'NYT',
'role': 'design editor',
},
'birthplace': 'Ohio',
'hobbies': ['cooking', 'dancing', 'teaching'],
}
可以看出,我用一个简单列表就可以给出我朋友的所有属性,无需创建表。
你可能想知道,关系型数据的优点是什么?你问不同的人,得到的回答可能会完全不同——在计算机科学领域,在众多开发人员之中,这是一个激烈争论的话题。我们的观点是,当数据结构包含大量的关系网络时,SQL 对快速查询做出了许多改进。非关系型数据库在速度、可用性和复用方面做出了许多改进。
最后,如果你对学习某一种数据库有更强烈的兴趣,可以让兴趣帮你做决定,但不要现在就确定数据库的格式。如果你需要在关系型数据库和非关系型数据库之间迁移,有许多工具可以帮你完成这一任务 1。
1对于在 SQL 和 NoSQL 数据库之间的迁移,更多内容可查阅 Matt Asay 关于将 Foursquare 从关系型数据库迁移到 NoSQL 数据库的文章(http://www.techrepublic.com/blog/the-enterprise-cloud/migrating-from-a-relational-to-a-nosql-cloud-database/)。另外,Quora 上还有许多关于反向迁移的文章(https://www.quora.com/How-do-I-migrate-data-from-a-MongoDB-to-MySQL-database-Can-it-be-done-in-a-real-time-scenario-What-are-the-pros-and-cons-for-each-migration-Which-one-do-you-advice-What-is-your-experience-Any-reference-DB-expert-who-can-do-it)。
MongoDB和Python
如果你的数据具有非关系型数据库结构,或者你希望在实践中学习,那么用 Python 连接 NoSQL 数据库是非常简单的。虽然有很多选择,但最流行的 NoSQL 数据库框架之一是 MongoDB(http://mongodb.org/)。要使用 MongoDB,你需要首先安装驱动程序(http://docs.mongodb.org/ecosystem/drivers/python/),然后用 Python 来连接。在 PyCon 2012 上有一个很棒的演讲:“Getting Started with MongoDB”(https://github.com/behackett/presentations/tree/master/pycon_2012),你可以从这里开始学习 MongoDB 以及如何用 Python 连接。
6.7.3 用Python创建本地数据库
开始学习数据库和 Python 最简单的方法就是,使用一个简单的库帮你快速上手。对于本书来说,我们推荐学习 Dataset 库(http://dataset.readthedocs.io/)。Dataset 是一个包装库(wrapper library),可以将可读的 Python 代码翻译成要处理的数据库代码,以加快开发速度。
如果你已有一个 SQLite、PostgreSQL 或 MySQL 数据库,可以参考快速入门指南(https://dataset.readthedocs.io/en/latest/quickstart.html)直接连接。如果你还没有上述数据库之一,在使用这个工具时它会为你创建一个。我们来看一下如何让它在你的电脑上运行。
你要做的第一件事是安装 Dataset(http://dataset.readthedocs.io/en/latest/install.html)。如果你已经安装了 pip,那么只需要输入 pip install dataset
。
然后你需要确定用到的后端。如果你已经在用 PostgreSQL 或 MySQL,只需要用对应的语法创建一个新的数据库。如果你对数据库不太熟悉,那我们就用 SQLite。首先,下载操作系统对应的 SQLite 二进制文件(http://www.sqlite.org/download.html)。打开下载的文件,按照安装说明一步步安装。
打开终端,切换(cd
)到保存 Python 数据处理脚本的项目文件夹。输入以下代码来创建新的 SQLite 数据库:
sqlite3 data_wrangling.db
你应该会看到以 sqlite>
开头的提示符,提示你输入 SQL 语句。你已经确认电脑上可以运行 sqlite3,可以在终端输入 .q
退出 SQLite。退出后,列出当前文件夹的所有文件。现在你应该会看到一个名为 data_wrangling.db 的文件——那就是你的数据库!
安装好了 SQLite,运行了第一个数据库之后,现在要开始使用 Dataset 了。在 Python 中运行以下代码:
import dataset
db = dataset.connect('sqlite:///data_wrangling.db')
my_data_source = {
'url':
'http://www.tsmplug.com/football/premierleague-player-salaries-club-by-club/',
'description': 'Premier League Club Salaries',
'topic': 'football',
'verified': False,
} ➊
table = db['data_sources'] ➋
table.insert(my_data_source) ➌
another_data_source = {
'url':
'http://www.premierleague.com/content/premierleague/en-gb/players/index.html',
'description': 'Premier League Stats',
'topic': 'football',
'verified': True,
}
table.insert(another_data_source)
sources = db['data_sources'].all() ➍
print sources
❶ 创建一个 Python 字典,里面是我们要保存的数据。我们要保存的是足球研究的数据源。我们添加的信息有主题、描述、URL 以及我们是否对数据做过核实。
❷ 创建名为 data_sources
的新表。
❸ 将第一个数据源插入新表。
❹ 显示我们保存在 data_sources
表中的所有数据源。
你已经利用 SQLite 创建了第一个关系型表,并完成了 Python 与数据库之间的第一次交互。随着本书内容的深入,你将会向数据库中添加更多的数据和表。将所有数据保存到一处,可以让你数据结构清晰,让你的研究更加专注。
6.8 使用简单文件
如果你的数据集很小,很可能简单文件就可以满足要求,不必使用数据库。你可能想浏览一下第 7 章,在保存之前先用数据清洗技术处理一下,但把数据保存成 CSV 文件或其他简单文件格式是完全可以的。我们用来导入 CSV 的 csv
模块(见 3.1.1 节)也有许多好用的写入类(https://docs.python.org/2/library/csv.html#writer-objects)。
在使用简单文件时,你主要考虑的是确保访问和备份文件都比较方便。要满足这些需求,你可以将数据保存在共享网盘或云服务(Dropbox、Box、Amazon、Google Drive)中。这些服务通常都会提供备份选项和管理能力,同时还能够分享文件。在“哎呀,我把数据文件覆盖了”时,这是非常有用的。
6.8.1 云存储和Python
根据你选择的云存储方案,你应该研究一下用 Python 获取数据的最佳方法。Dropbox 对 Python 的支持很好,网站上的“Python 快速入门指南”(https://www.dropbox.com/developers-v1/core/start/python)很不错。Google Drive 要复杂一些,但“Python 快速上手指南”(https://github.com/googledrive/python-quickstart)可以帮你完成初步的设置。Google Drive 还有一些 Python API 包装器,比如 PyDrive(https://github.com/googledrive/PyDrive),可以让你在不太会用 Python 的情况下使用 Google Drive。要管理 Google Drive 上的电子表格,我们强烈推荐 GSpread(https://github.com/burnash/gspread)。
如果你有自己的云服务器,可能需要研究连接云服务器的最佳方法。Python 有内置的 URL 请求方法、FTP(文件传输协议)方法和 SSH/SCP(Secure Shell/Secure Copy)方法,都包含在 Python 标准库(stdlib)中。在第 14 章中我们还会讲到管理云服务的一些有用库。
6.8.2 本地存储和Python
数据存储最简单也是最直接的方法就是本地存储。用一行 Python 代码就可以打开文件系统中的文档(open
命令,https://docs.python.org/2/library/functions.html#open)。在处理数据时,你还可以用内置的 file.write
方法修改并保存为新文件。
6.9 其他数据存储方式
数据存储还有许多有趣的新方式,和前面讲过的都不一样。根据你的使用案例,存储数据可能有更好的方式。下面是两种有趣的存储方式。
- 层次型数据格式(HDF)
HDF 是基于文件的可扩展数据解决方案,可将大型数据库快速存储至文件系统(本地或其他位置)。如果你已经很熟悉 HDF,Python 有一个 HDF5 驱动程序 h5py(http://www.h5py.org/),可以将 Python 与 HDF5 相连接。
- Hadoop
Hadoop 是一个大数据分布式存储系统,可以跨集群存储并处理数据。如果你已经用过 Hadoop,或者熟悉 Hadoop,在 Cloudera 网站上有一篇“Hadoop 上 Python 框架指南”(http://blog.cloudera.com/blog/2013/01/a-guide-to-python-frameworks-for-hadoop/),还有一些容易上手的代码示例。
6.10 小结
恭喜!你已经搞定了项目面临的几个最大问题:我怎么能找到有用的数据?我怎么访问并保存数据?我们希望你对获取的数据源有信心,并相信你第一个数据集的真实性。我们也希望你对数据备份和数据存储有一个可靠的计划。
你可以将本章学习的技术应用到以后的数据集上,即使是在数据网站上花几个小时研究脑海中突然出现的问题。
现在你应该有信心做好以下事情:
判断你找到数据集的价值和用途
拿起电话寻求更多信息
要回答一个问题,知道首先去哪里寻找数据
轻松实现安全存储数据的方法
核实你找到的数据
构建数据的关系模型你还第一次接触到表 6-2 中的这些概念。
表6-2:Python编程新概念和新库
概念/库 | 作用 |
---|---|
关系型数据库(例如 MySQL 和 PostgreSQL) | 轻松存储关系型数据 |
非关系型数据库(例如 MongoDB) | 以平面方式存储数据 |
SQLite(https://www.sqlite.org/)安装和使用 | 基于 SQL 的易用存储,适用于简单项目 |
Dataset(https://dataset.readthedocs.org/en/latest/)安装和使用 | 易用的 Python 数据库包装器 |
在后续章节中,你还会更多地用到所有这些技术。在下一章里,你将学习清洗数据,利用代码发现异常,编写完整的脚本或程序,这样你就可以分析数据,并输出结果与全世界分享。