當(dāng)你開始接觸豐富多彩的開放數(shù)據(jù)集時(shí),CSV油额、JSON和XML等格式名詞就會奔涌而來。如何用Python高效地讀取它們刻帚,為后續(xù)的整理和分析做準(zhǔn)備呢潦嘶?本文為你一步步展示過程,你自己也可以動手實(shí)踐崇众。
需求
人工智能的算法再精妙掂僵,離開數(shù)據(jù)也是“巧婦難為無米之炊”航厚。
數(shù)據(jù)是寶貴的,開放數(shù)據(jù)尤其珍貴锰蓬。無論是公眾號幔睬、微博還是朋友圈里,許多人一聽見“開放數(shù)據(jù)”芹扭、“數(shù)據(jù)資源”麻顶、“數(shù)據(jù)鏈接”這些關(guān)鍵詞就興奮不已。
好不容易拿到了夢寐以求的數(shù)據(jù)鏈接冯勉,你會發(fā)現(xiàn)下載下來的這些數(shù)據(jù)澈蚌,可能有各種稀奇古怪的格式。
最常見的灼狰,是以下幾種:
- CSV
- XML
- JSON
你希望自己能調(diào)用Python來清理和分析它們宛瞄,從而完成自己的“數(shù)據(jù)煉金術(shù)”。
第一步交胚,你先得學(xué)會如何用Python讀取這些開放數(shù)據(jù)格式份汗。
這篇文章,咱們就用實(shí)際的開放數(shù)據(jù)樣例蝴簇,分別為你介紹如何把CSV杯活、XML和JSON這三種常見的網(wǎng)絡(luò)開放數(shù)據(jù)格式讀取到Python中,形成結(jié)構(gòu)化數(shù)據(jù)框熬词,方便你的后續(xù)分析操作旁钧。
是不是躍躍欲試了?
數(shù)據(jù)
我們選擇的開放數(shù)據(jù)平臺互拾,是Quandl歪今。
Quandl是一個(gè)金融和經(jīng)濟(jì)數(shù)據(jù)平臺。其中既包括價(jià)格不菲的收費(fèi)數(shù)據(jù)颜矿,也有不少免費(fèi)開放數(shù)據(jù)寄猩。
你需要在Quandl免費(fèi)注冊一個(gè)賬戶,這樣才可以正常訪問其免費(fèi)數(shù)據(jù)集合骑疆。
注冊過程田篇,只需要填寫上面這個(gè)表格。注冊完畢后箍铭,用新賬戶和密碼登錄泊柬。
登錄后,點(diǎn)擊首頁上的“Core Financial Data”欄目中的“Search Data”诈火。
你馬上就看到讓你眼花繚亂的數(shù)據(jù)集合了兽赁。
不要高興得太早。仔細(xì)看數(shù)據(jù)集合右側(cè)的標(biāo)簽,第一頁里基本上都是“Premium”(只限會員)闸氮,只有付費(fèi)用戶才能使用的。
你不需要自己翻頁去查找免費(fèi)開放數(shù)據(jù)教沾。點(diǎn)擊頁面左側(cè)上方的過濾器(Filter)下的“免費(fèi)”(Free)選項(xiàng)蒲跨。
這次顯示的全都是免費(fèi)數(shù)據(jù)了。
這些數(shù)據(jù)都包含什么內(nèi)容授翻?如果你感興趣的話或悲,歡迎自己花點(diǎn)兒時(shí)間瀏覽一下。
咱們使用其中的“Zillow Real Estate Research”堪唐,這是一個(gè)非常龐大的房地產(chǎn)數(shù)據(jù)集巡语。
Zillow房地產(chǎn)數(shù)據(jù)都來自于美國城市。你可以根據(jù)自己的愛好淮菠,選擇感興趣的城市男公。我選擇的是肯塔基州的萊克星頓(Lexington)市。
為什么不選紐約合陵、洛杉磯枢赔,卻要選它呢?
因?yàn)槲以诿绹L學(xué)的時(shí)候拥知,周末經(jīng)常去那里踏拜。
我訪問的大學(xué)坐落在村子里。本地沒有華人超市低剔,一些常見的食品和調(diào)料都買不到速梗。
要想去華人超市,就得到最近的“大城市”萊克星頓襟齿。
從學(xué)校到那里地距離姻锁,跟天津到北京差不多。
我自己沒有買車蕊唐,公共交通又不方便屋摔,一開始很是苦惱。
好在留學(xué)生同胞們周末時(shí)常要去萊克星頓逛商場替梨。我總是跟著蹭車钓试。
一個(gè)半小時(shí)開車進(jìn)城,我們先去真正的中餐館吃一頓自助午餐副瀑,然后去商場弓熏。他們逛2個(gè)小時(shí)左右,我找個(gè)咖啡館或者休息區(qū)閉目養(yǎng)神糠睡,戴著耳機(jī)聽羅胖講故事挽鞠。
等他們逛完了,我們一起去華人超市采購。
這個(gè)有大商場信认、有正牌中餐館材义、有多路公交,甚至還有華人超市的“大城市”當(dāng)初給我留下了難忘的美好回憶嫁赏。
就拿它當(dāng)樣例吧其掂。
獲取
搜索“l(fā)exington ky”,返回的結(jié)果還真不少潦蝇。
我們選擇其中的“Zillow Home Value Index (Metro): Home Sales (SA) - Lexington, KY”款熬,點(diǎn)擊后可以看到這個(gè)數(shù)據(jù)集的頁面。
這是萊克星頓房屋銷售價(jià)格的中位數(shù)(median)在不同時(shí)間的記錄攘乒。
Quandl已經(jīng)很周到地幫我們用折線圖繪制了歷史價(jià)格信息的變化贤牛。選擇“TABLE”標(biāo)簽頁,我們可以查看原始數(shù)據(jù)则酝。
下面我們把數(shù)據(jù)下載到本地殉簸。右上方有個(gè)Download按鈕,我們點(diǎn)擊它沽讹。
可以看到喂链,Quandl提供了我們4種格式的數(shù)據(jù),分別是
- CSV
- Excel
- JSON
- XML
這里咱們先不講Excel(因?yàn)樗俏④浀膶俑袷剑┩兹灰来蜗螺d其他3個(gè)類別的數(shù)據(jù)椭微。
我們在對應(yīng)的數(shù)據(jù)類別上點(diǎn)擊鼠標(biāo)右鍵,在彈出的瀏覽器菜單中選擇“鏈接另存為”盲链,然后存儲到本地蝇率。
我已經(jīng)為你下載好了相關(guān)的3種數(shù)據(jù)格式,并且存儲在了一個(gè)Github項(xiàng)目中刽沾。請?jiān)L問這個(gè)鏈接本慕,下載壓縮包后,解壓查看侧漓。
壓縮包里锅尘,就是萊克星頓市房地產(chǎn)交易信息的三種不同格式了。從這張圖里布蔗,可以看到同樣的數(shù)據(jù)內(nèi)容藤违,csv文件占用空間最小,JSON次之纵揍;占空間最大的格式是XML顿乒。
數(shù)據(jù)有了,下面我們準(zhǔn)備一下Python編程環(huán)境泽谨。
環(huán)境
我們使用Python集成運(yùn)行環(huán)境Anaconda璧榄。
請到這個(gè)網(wǎng)址 下載最新版的Anaconda特漩。下拉頁面,找到下載位置骨杂。根據(jù)你目前使用的系統(tǒng)涂身,網(wǎng)站會自動推薦給你適合的版本下載。我使用的是macOS搓蚪,下載文件格式為pkg访得。
下載頁面區(qū)左側(cè)是Python 3.6版,右側(cè)是2.7版陕凹。請選擇2.7版本。
雙擊下載后的pkg文件鳄炉,根據(jù)中文提示一步步安裝即可杜耙。
安裝好Anaconda后,我們還需要確保安裝幾個(gè)必要的軟件包拂盯。
請到你的“終端”(Linux, macOS)或者“命令提示符”(Windows)下面佑女,進(jìn)入咱們剛剛下載解壓后的樣例目錄。
執(zhí)行以下命令:
pip install json
pip install bs4
安裝完畢后谈竿,執(zhí)行:
jupyter notebook
這樣就進(jìn)入到了Jupyter筆記本環(huán)境团驱。我們新建一個(gè)Python 2筆記本。
這樣就出現(xiàn)了一個(gè)空白筆記本空凸。
點(diǎn)擊左上角筆記本名稱嚎花,修改為有意義的筆記本名“demo-python-read-open-data-formats”。
至此呀洲,準(zhǔn)備工作做完紊选,下面我們就可以開始用Python讀取不同格式的數(shù)據(jù)了。
CSV
我們先從最為簡單的CSV格式開始道逗。
所謂CSV兵罢,是英文“Comma Separated Values”(逗號分割數(shù)值)的簡寫。
我們先回到Jupyter Notebook的根目錄滓窍。
打開咱們的樣例csv文件卖词,ZILLOW-M550_SALES.csv
來看看。
可以看到吏夯,第一行是表頭此蜈,說明每一列的名稱。之后每一行都是數(shù)據(jù)噪生,分別是日期和對應(yīng)的售價(jià)中位數(shù)取值舶替。
每一行的兩列數(shù)據(jù),都是用逗號來分割的杠园。
我們可以用Excel來打開csv數(shù)據(jù)顾瞪,更直觀來看看效果。
如圖所示,當(dāng)我們用Excel打開csv數(shù)據(jù)時(shí)陈醒,Excel自動將其識別為數(shù)據(jù)表單惕橙。逗號不見了,變成了分割好的兩列若干行數(shù)據(jù)钉跷。
下面我們使用Python弥鹦,將該csv數(shù)據(jù)文件讀入,并且可視化爷辙。
讀入Pandas工具包彬坏。它可以幫助我們處理數(shù)據(jù)框,是Python數(shù)據(jù)分析的基礎(chǔ)工具膝晾。
import pandas as pd
然后栓始,為了讓圖像可以在Jupyter Notebook上正確顯示,我們使用以下語句血当,允許頁內(nèi)嵌入圖像幻赚。
%matplotlib inline
下面我們讀入csv文件。Pandas對csv數(shù)據(jù)最為友好臊旭,提供了read_csv
命令落恼,可以直接讀取csv數(shù)據(jù)。
df = pd.read_csv("ZILLOW-M550_SALES.csv")
我們把csv數(shù)據(jù)存儲到了數(shù)據(jù)框變量df离熏。下面顯示一下數(shù)據(jù)讀取效果佳谦。
df.head()
可以看到,日期和交易價(jià)格中位數(shù)記錄都正確讀入滋戳。
下面我們編制一個(gè)函數(shù)吠昭,幫我們整理數(shù)據(jù)框。它主要實(shí)現(xiàn)以下功能:
- 把列名變成小寫的“date”和“value”胧瓜;
- 按照時(shí)間順序矢棚,排列數(shù)據(jù)。把最舊的日期和對應(yīng)的數(shù)值放在第一行府喳,最新的日期和對應(yīng)的數(shù)值置于末尾蒲肋;
- 把時(shí)間設(shè)置為數(shù)據(jù)框的索引,這主要是便于后面繪圖的時(shí)候钝满,橫軸正確顯示日期數(shù)據(jù)兜粘。
def arrange_time_dataframe(df):
df.columns = ['date', 'value']
df.sort_values(by='date', inplace=True)
df.set_index('date', inplace=True)
return df
下面我們調(diào)用這個(gè)函數(shù),整理數(shù)據(jù)框變量df弯蚜。
df = arrange_time_dataframe(df)
我們展示一下df的前5行孔轴。
df.head()
你會看到,日期數(shù)據(jù)變成了索引碎捺,而且按照升序排列路鹰。
下面我們該繪圖了贷洲。數(shù)據(jù)框工具Pandas給我們提供了非常方便的時(shí)間序列圖形繪制功能。
為了顯示更為美觀晋柱,我們把圖形的長寬比例做了設(shè)置优构。
df.plot(figsize=(16, 6))
對比一下我們自己繪制的圖像和Quandl的示例圖形,是不是一致呢雁竞?
JSON
JSON是JavaScript Object Notation(JavaScript對象標(biāo)記)的縮寫钦椭,是一種輕量級的數(shù)據(jù)交換格式。它跟CSV一樣碑诉,也是文本文件彪腔。
我們在Jupyter Notebook中打開下載的JSON文件,檢視其內(nèi)容:
我們需要的數(shù)據(jù)都在里面进栽,下面我們回到Python筆記本文件ipynb中德挣,嘗試讀取JSON數(shù)據(jù)內(nèi)容。
首先我們讀取json工具包泪幌。
import json
打開咱們下載的M550_SALES.json
文件,讀取數(shù)據(jù)到變量data署照。
with open("M550_SALES.json") as f:
data = json.load(f)
為了看得更為直觀祸泪,咱們把JSON正確縮進(jìn)后輸出。這里我們只展示前面的一些行建芙。
print(json.dumps(data, indent=2))
{
"dataset": {
"dataset_code": "M550_SALES",
"column_names": [
"Date",
"Value"
],
"newest_available_date": "2016-06-30",
"description": "The Zillow Home Value Index is Zillow's estimate of the median market value of home sales (nsa) within the metro of Morehead City, NC. This data is calculated by Zillow Real Estate Research (www.zillow.com/research) using their database of 110 million homes.",
"end_date": "2016-06-30",
"data": [
[
"2016-06-30",
64.0
],
[
"2016-05-31",
163.0
],
可以看到没隘,JSON文件就像是一個(gè)大的字典(dictionary)。我們選擇其中的某個(gè)索引禁荸,就能獲得對應(yīng)的數(shù)據(jù)右蒲。
我們選擇“dataset”:
data['dataset']
下面是結(jié)果的前幾行。
{u'collapse': None,
u'column_index': None,
u'column_names': [u'Date', u'Value'],
u'data': [[u'2016-06-30', 64.0],
[u'2016-05-31', 163.0],
[u'2016-04-30', 118.0],
我們關(guān)心的數(shù)據(jù)在“data”下面赶熟。繼續(xù)來:
data['dataset']['data']
還是只展示前幾行:
[[u'2016-06-30', 64.0],
[u'2016-05-31', 163.0],
[u'2016-04-30', 118.0],
這不就是我們想要讀取的數(shù)據(jù)嗎瑰妄?
為了和csv數(shù)據(jù)做出區(qū)分,我們這次將數(shù)據(jù)讀取后存儲在df1變量映砖。
df1 = pd.DataFrame(data['dataset']['data'])
顯示一下前幾行:
df1.head()
數(shù)據(jù)都對间坐,可是列名稱怪怪的。
沒關(guān)系邑退,我們剛才不是編制了整理函數(shù)嗎竹宋?不管多么奇怪的列名稱,都可以整理好地技。
df1 = arrange_time_dataframe(df1)
整理之后蜈七,咱們再次調(diào)用繪圖函數(shù),繪制df1的數(shù)據(jù):
df1.plot(figsize=(16, 6))
繪圖正確莫矗,證明我們的JSON數(shù)據(jù)讀取成功飒硅。
XML
XML是擴(kuò)展標(biāo)記語言(eXtensible Markup Language)的縮寫砂缩。它看起來有些像我們上網(wǎng)時(shí)每天都要用到的HTML源碼,但是有區(qū)別狡相。它的設(shè)計(jì)初衷梯轻,不是為了展示W(wǎng)eb頁面,而是為了數(shù)據(jù)交換尽棕。
我們在Jupyter Notebook中打開下載的XML文件喳挑。
在頁面下方,我們看到了自己感興趣的數(shù)據(jù)部分滔悉,但是數(shù)據(jù)是用很多標(biāo)簽來包裹的伊诵。
下面我們嘗試使用Python來提取和整理XML數(shù)據(jù)。
首先回官,我們讀入網(wǎng)頁分析工具Beautifulsoup曹宴。
from bs4 import BeautifulSoup
這是一個(gè)非常重要的網(wǎng)頁信息提取工具,是Python爬蟲編寫的基礎(chǔ)技能之一歉提。
本文只會用到Beautifulsoup的一些簡單命令笛坦。所以即便你之前從未接觸過Beautifulsoup,也沒有關(guān)系苔巨,跟著先做一遍版扩,獲得一些感性認(rèn)知和經(jīng)驗(yàn)。后面再系統(tǒng)學(xué)習(xí)侄泽。
我建議的系統(tǒng)學(xué)習(xí)方法礁芦,是到Beautifulsoup的文檔頁面認(rèn)真閱讀和學(xué)習(xí)。
如果你閱讀英文文檔有一些困難悼尾,可以看翻譯好的中文文檔柿扣,地址在這里。
然后闺魏,我們讀入下載好的XML數(shù)據(jù)未状,存入變量data。
with open("M550_SALES.xml") as f:
data = f.read()
下面我們用“l(fā)xml”工具分析解析data數(shù)據(jù)析桥,并且存儲到soup變量里面娩践。
soup = BeautifulSoup(data, "lxml")
解析之后,我們就可以利用Beautifulsoup的強(qiáng)大搜索功能了烹骨。
這里我們觀察XML文件:
可以看到翻伺,我們關(guān)心的日期和交易中位數(shù)記錄存放在datum標(biāo)簽下。
其中沮焕,日期數(shù)據(jù)的類型為“date”吨岭,交易價(jià)格中位數(shù)的類型為“float”。
我們先來嘗試使用Beautifulsoup的find_all
函數(shù)峦树,提取所有的日期數(shù)據(jù):
dates = soup.find_all('datum', type='date')
我們看看提取結(jié)果的前5行:
dates[:5]
[<datum type="date">2016-06-30</datum>,
<datum type="date">2016-05-31</datum>,
<datum type="date">2016-04-30</datum>,
<datum type="date">2016-03-31</datum>,
<datum type="date">2016-02-29</datum>]
很好辣辫,數(shù)據(jù)正確提取出來旦事。問題是還有標(biāo)簽數(shù)據(jù)在前后,此時(shí)我們不需要它們急灭。
我們處理一下姐浮。對列表每一項(xiàng),使用Beautifulsoup的text屬性提取內(nèi)容葬馋。
dates = [item.text for item in dates]
再看看這次的提取結(jié)果:
dates[:5]
[u'2016-06-30', u'2016-05-31', u'2016-04-30', u'2016-03-31', u'2016-02-29']
好的卖鲤,沒問題了。
下面我們用同樣的方式處理交易價(jià)格中位數(shù)記錄:
values= soup.find_all('datum', type='float')
顯示一下結(jié)果:
values[:5]
[<datum type="float">64.0</datum>,
<datum type="float">163.0</datum>,
<datum type="float">118.0</datum>,
<datum type="float">110.0</datum>,
<datum type="float">83.0</datum>]
這次還是有標(biāo)簽畴嘶,需要去掉蛋逾。
注意這里我們希望把結(jié)果存儲為浮點(diǎn)數(shù),所以除了用text屬性提取數(shù)值以外窗悯,還用float()
函數(shù)做了轉(zhuǎn)換区匣。
values = [float(item.text) for item in values]
顯示一下前5行:
values[:5]
[64.0, 163.0, 118.0, 110.0, 83.0]
數(shù)據(jù)被正確轉(zhuǎn)換成了浮點(diǎn)數(shù)。
我們手里蒋院,分別有了日期和交易價(jià)格中位數(shù)記錄列表亏钩。下面我們將其轉(zhuǎn)換成為Pandas數(shù)據(jù)框,并且存儲于df2變量里欺旧。
df2 = pd.DataFrame({'dates':dates, 'values':values})
看看df2的前幾行:
df2.head()
數(shù)據(jù)我們有了姑丑,下面也用我們的自編函數(shù)整理一下:
df2 = arrange_time_dataframe(df2)
然后我們嘗試對df2繪圖:
df2.plot(figsize=(16, 6))
XML數(shù)據(jù)讀取和檢視成功。
小結(jié)
至此切端,你已經(jīng)嘗試了如何把CSV彻坛、JSON和XML數(shù)據(jù)讀入到Pandas數(shù)據(jù)框顷啼,并且做最基本的時(shí)間序列可視化展示踏枣。
你可能會有以下疑問:
既然CSV文件這么小巧,Pandas讀取起來也方便钙蒙,為什么還要費(fèi)勁去學(xué)那么難用的JSON和XML數(shù)據(jù)讀取方法呢茵瀑?
這是個(gè)好問題!
我能想到的躬厌,至少有兩個(gè)原因马昨。
首先,咱們找到的Quandl平臺扛施,全方位提供數(shù)據(jù)的下載格式鸿捧,幾乎涵蓋了全部常見數(shù)據(jù)格式類別。但這只是特例疙渣。大多數(shù)的開放數(shù)據(jù)平臺匙奴,是不提供這么多種數(shù)據(jù)格式供你下載的。因此妄荔,當(dāng)你拿到的數(shù)據(jù)只有JSON或者XML格式時(shí)泼菌,了解如何讀取它們谍肤,就很重要。
其次哗伯,JSON或XML附加的那些內(nèi)容荒揣,絕不是無意義的。它們可以幫助你檢查數(shù)據(jù)的完整性和合法性焊刹。你甚至還可以自行定義語義標(biāo)準(zhǔn)系任,以便和他人進(jìn)行高效的數(shù)據(jù)交換。
如果你對JSON和XML格式感興趣伴澄,希望系統(tǒng)學(xué)習(xí)赋除,那我推薦你到Stanford Online這個(gè)MOOC平臺上學(xué)習(xí)數(shù)據(jù)庫課程。
祝進(jìn)步非凌!
討論
你平時(shí)從哪些開放數(shù)據(jù)平臺下載過數(shù)據(jù)举农?都接觸過哪些數(shù)據(jù)格式?你用什么工具來整理和分析它們呢敞嗡?有沒有比本文更高效的方法颁糟?歡迎留言,把你的經(jīng)驗(yàn)和思考分享給大家喉悴,我們一起交流討論棱貌。
喜歡請點(diǎn)贊。還可以微信關(guān)注和置頂我的公眾號“玉樹芝蘭”(nkwangshuyi)箕肃。
如果你對數(shù)據(jù)科學(xué)感興趣婚脱,不妨閱讀我的系列教程索引貼《如何高效入門數(shù)據(jù)科學(xué)?》勺像,里面還有更多的有趣問題及解法障贸。