如何用Python讀取開放數據?

當你開始接觸豐富多彩的開放數據集時,CSV、JSON和XML等格式名詞就會奔涌而來。如何用Python高效地讀取它們,爲後續的整理和分析作準備呢?本文爲你一步步展現過程,你本身也能夠動手實踐。html

需求

人工智能的算法再精妙,離開數據也是「巧婦難爲無米之炊」。python

數據是寶貴的,開放數據尤爲珍貴。不管是公衆號、微博仍是朋友圈裏,許多人一聽見「開放數據」、「數據資源」、「數據連接」這些關鍵詞就興奮不已。git

好不容易拿到了求之不得的數據連接,你會發現下載下來的這些數據,可能有各類稀奇古怪的格式。github

最多見的,是如下幾種:算法

  • CSV
  • XML
  • JSON

你但願本身能調用Python來清理和分析它們,從而完成本身的「數據鍊金術」。數據庫

第一步,你先得學會如何用Python讀取這些開放數據格式。編程

這篇文章,我們就用實際的開放數據樣例,分別爲你介紹如何把CSV、XML和JSON這三種常見的網絡開放數據格式讀取到Python中,造成結構化數據框,方便你的後續分析操做。json

是否是躍躍欲試了?瀏覽器

數據

咱們選擇的開放數據平臺,是Quandl。微信

Quandl是一個金融和經濟數據平臺。其中既包括價格不菲的收費數據,也有很多免費開放數據

你須要在Quandl免費註冊一個帳戶,這樣才能夠正常訪問其免費數據集合。

註冊過程,只須要填寫上面這個表格。註冊完畢後,用新帳戶和密碼登陸。

登陸後,點擊首頁上的「Core Financial Data」欄目中的「Search Data」。

你立刻就看到讓你眼花繚亂的數據集合了。

不要高興得太早。仔細看數據集合右側的標籤,第一頁裏基本上都是「Premium」(只限會員),只有付費用戶才能使用的。

你不須要本身翻頁去查找免費開放數據。點擊頁面左側上方的過濾器(Filter)下的「免費」(Free)選項。

此次顯示的全都是免費數據了。

這些數據都包含什麼內容?若是你感興趣的話,歡迎本身花點兒時間瀏覽一下。

我們使用其中的「Zillow Real Estate Research」,這是一個很是龐大的房地產數據集。

Zillow房地產數據都來自於美國城市。你能夠根據本身的愛好,選擇感興趣的城市。我選擇的是肯塔基州的萊剋星頓(Lexington)市。

爲何不選紐約、洛杉磯,卻要選它呢?

由於我在美國訪學的時候,週末常常去那裏。

我訪問的大學坐落在村子裏。本地沒有華人超市,一些常見的食品和調料都買不到。

要想去華人超市,就獲得最近的「大城市」萊剋星頓。

從學校到那裏地距離,跟天津到北京差很少。

我本身沒有買車,公共交通又不方便,一開始非常苦惱。

好在留學生同胞們週末時常要去萊剋星頓逛商場。我老是跟着蹭車。

一個半小時開車進城,咱們先去真正的中餐館吃一頓自助午飯,而後去商場。他們逛2個小時左右,我找個咖啡館或者休息區閉目養神,戴着耳機聽羅胖講故事。

等他們逛完了,咱們一塊兒去華人超市採購。

這個有大商場、有正牌中餐館、有多路公交,甚至還有華人超市的「大城市」當初給我留下了難忘的美好回憶。

就拿它當樣例吧。

獲取

搜索「lexington ky」,返回的結果還真很多。

咱們選擇其中的「Zillow Home Value Index (Metro): Home Sales (SA) - Lexington, KY」,點擊後能夠看到這個數據集的頁面。

這是萊剋星頓房屋銷售價格的中位數(median)在不一樣時間的記錄。

Quandl已經很周到地幫咱們用折線圖繪製了歷史價格信息的變化。選擇「TABLE」標籤頁,咱們能夠查看原始數據。

下面咱們把數據下載到本地。右上方有個Download按鈕,咱們點擊它。

能夠看到,Quandl提供了咱們4種格式的數據,分別是

  • CSV
  • Excel
  • JSON
  • XML

這裏我們先不講Excel(由於它是微軟的專屬格式),只依次下載其餘3個類別的數據。

咱們在對應的數據類別上點擊鼠標右鍵,在彈出的瀏覽器菜單中選擇「連接另存爲」,而後存儲到本地。

我已經爲你下載好了相關的3種數據格式,而且存儲在了一個Github項目中。請訪問這個連接,下載壓縮包後,解壓查看。

壓縮包裏,就是萊剋星頓市房地產交易信息的三種不一樣格式了。從這張圖裏,能夠看到一樣的數據內容,csv文件佔用空間最小,JSON次之;佔空間最大的格式是XML。

數據有了,下面咱們準備一下Python編程環境。

環境

咱們使用Python集成運行環境Anaconda。

請到這個網址 下載最新版的Anaconda。下拉頁面,找到下載位置。根據你目前使用的系統,網站會自動推薦給你適合的版本下載。我使用的是macOS,下載文件格式爲pkg。

下載頁面區左側是Python 3.6版,右側是2.7版。請選擇2.7版本。

雙擊下載後的pkg文件,根據中文提示一步步安裝便可。

安裝好Anaconda後,咱們還須要確保安裝幾個必要的軟件包。

請到你的「終端」(Linux, macOS)或者「命令提示符」(Windows)下面,進入我們剛剛下載解壓後的樣例目錄。

執行如下命令:

pip install json
pip install bs4
複製代碼

安裝完畢後,執行:

jupyter notebook
複製代碼

這樣就進入到了Jupyter筆記本環境。咱們新建一個Python 2筆記本。

這樣就出現了一個空白筆記本。

點擊左上角筆記本名稱,修改成有意義的筆記本名「demo-python-read-open-data-formats」。

至此,準備工做作完,下面咱們就能夠開始用Python讀取不一樣格式的數據了。

CSV

咱們先從最爲簡單的CSV格式開始。

所謂CSV,是英文「Comma Separated Values」(逗號分割數值)的簡寫。

咱們先回到Jupyter Notebook的根目錄。

打開我們的樣例csv文件,ZILLOW-M550_SALES.csv來看看。

能夠看到,第一行是表頭,說明每一列的名稱。以後每一行都是數據,分別是日期和對應的售價中位數取值。

每一行的兩列數據,都是用逗號來分割的。

咱們能夠用Excel來打開csv數據,更直觀來看看效果。

如圖所示,當咱們用Excel打開csv數據時,Excel自動將其識別爲數據表單。逗號不見了,變成了分割好的兩列若干行數據。

下面咱們使用Python,將該csv數據文件讀入,而且可視化。

讀入Pandas工具包。它能夠幫助咱們處理數據框,是Python數據分析的基礎工具。

import pandas as pd
複製代碼

而後,爲了讓圖像能夠在Jupyter Notebook上正確顯示,咱們使用如下語句,容許頁內嵌入圖像。

%matplotlib inline
複製代碼

下面咱們讀入csv文件。Pandas對csv數據最爲友好,提供了read_csv命令,能夠直接讀取csv數據。

df = pd.read_csv("ZILLOW-M550_SALES.csv")
複製代碼

咱們把csv數據存儲到了數據框變量df。下面顯示一下數據讀取效果。

df.head()
複製代碼

能夠看到,日期和交易價格中位數記錄都正確讀入。

下面咱們編制一個函數,幫咱們整理數據框。它主要實現如下功能:

  • 把列名變成小寫的「date」和「value」;
  • 按照時間順序,排列數據。把最舊的日期和對應的數值放在第一行,最新的日期和對應的數值置於末尾;
  • 把時間設置爲數據框的索引,這主要是便於後面繪圖的時候,橫軸正確顯示日期數據。
def arrange_time_dataframe(df):
    df.columns = ['date', 'value']
    df.sort_values(by='date', inplace=True)
    df.set_index('date', inplace=True)
    return df
複製代碼

下面咱們調用這個函數,整理數據框變量df。

df = arrange_time_dataframe(df)
複製代碼

咱們展現一下df的前5行。

df.head()
複製代碼

你會看到,日期數據變成了索引,並且按照升序排列。

下面咱們該繪圖了。數據框工具Pandas給咱們提供了很是方便的時間序列圖形繪製功能。

爲了顯示更爲美觀,咱們把圖形的長寬比例作了設置。

df.plot(figsize=(16, 6))
複製代碼

png

對比一下咱們本身繪製的圖像和Quandl的示例圖形,是否是一致呢?

JSON

JSON是JavaScript Object Notation(JavaScript對象標記)的縮寫,是一種輕量級的數據交換格式。它跟CSV同樣,也是文本文件。

咱們在Jupyter Notebook中打開下載的JSON文件,檢視其內容:

咱們須要的數據都在裏面,下面咱們回到Python筆記本文件ipynb中,嘗試讀取JSON數據內容。

首先咱們讀取json工具包。

import json
複製代碼

打開我們下載的M550_SALES.json文件,讀取數據到變量data。

with open("M550_SALES.json") as f:
    data = json.load(f)
複製代碼

爲了看得更爲直觀,我們把JSON正確縮進後輸出。這裏咱們只展現前面的一些行。

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文件就像是一個大的字典(dictionary)。咱們選擇其中的某個索引,就能得到對應的數據。

咱們選擇「dataset」:

data['dataset']
複製代碼

下面是結果的前幾行。

{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],
複製代碼

咱們關心的數據在「data」下面。繼續來:

data['dataset']['data']
複製代碼

仍是隻展現前幾行:

[[u'2016-06-30', 64.0],
 [u'2016-05-31', 163.0],
 [u'2016-04-30', 118.0],
複製代碼

這不就是咱們想要讀取的數據嗎?

爲了和csv數據作出區分,咱們此次將數據讀取後存儲在df1變量。

df1 = pd.DataFrame(data['dataset']['data'])
複製代碼

顯示一下前幾行:

df1.head()
複製代碼

數據都對,但是列名稱怪怪的。

不要緊,咱們剛纔不是編制了整理函數嗎?無論多麼奇怪的列名稱,均可以整理好。

df1 = arrange_time_dataframe(df1)
複製代碼

整理以後,我們再次調用繪圖函數,繪製df1的數據:

df1.plot(figsize=(16, 6))
複製代碼

png

繪圖正確,證實咱們的JSON數據讀取成功。

XML

XML是擴展標記語言(eXtensible Markup Language)的縮寫。它看起來有些像咱們上網時天天都要用到的HTML源碼,可是有區別。它的設計初衷,不是爲了展現Web頁面,而是爲了數據交換。

咱們在Jupyter Notebook中打開下載的XML文件。

在頁面下方,咱們看到了本身感興趣的數據部分,可是數據是用不少標籤來包裹的。

下面咱們嘗試使用Python來提取和整理XML數據。

首先,咱們讀入網頁分析工具Beautifulsoup。

from bs4 import BeautifulSoup
複製代碼

這是一個很是重要的網頁信息提取工具,是Python爬蟲編寫的基礎技能之一。

本文只會用到Beautifulsoup的一些簡單命令。因此即使你以前從未接觸過Beautifulsoup,也沒有關係,跟着先作一遍,得到一些感性認知和經驗。後面再系統學習。

我建議的系統學習方法,是到Beautifulsoup的文檔頁面認真閱讀和學習。

若是你閱讀英文文檔有一些困難,能夠看翻譯好的中文文檔,地址在這裏

而後,咱們讀入下載好的XML數據,存入變量data。

with open("M550_SALES.xml") as f:
    data = f.read()
複製代碼

下面咱們用「lxml」工具分析解析data數據,而且存儲到soup變量裏面。

soup = BeautifulSoup(data, "lxml")
複製代碼

解析以後,咱們就能夠利用Beautifulsoup的強大搜索功能了。

這裏咱們觀察XML文件:

能夠看到,咱們關心的日期和交易中位數記錄存放在datum標籤下。

其中,日期數據的類型爲「date」,交易價格中位數的類型爲「float」。

咱們先來嘗試使用Beautifulsoup的find_all函數,提取全部的日期數據:

dates = soup.find_all('datum', type='date')
複製代碼

咱們看看提取結果的前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>]
複製代碼

很好,數據正確提取出來。問題是還有標籤數據在先後,此時咱們不須要它們。

咱們處理一下。對列表每一項,使用Beautifulsoup的text屬性提取內容。

dates = [item.text for item in dates]
複製代碼

再看看此次的提取結果:

dates[:5]
複製代碼
[u'2016-06-30', u'2016-05-31', u'2016-04-30', u'2016-03-31', u'2016-02-29']
複製代碼

好的,沒問題了。

下面咱們用一樣的方式處理交易價格中位數記錄:

values= soup.find_all('datum', type='float')
複製代碼

顯示一下結果:

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>]
複製代碼

此次仍是有標籤,須要去掉。

注意這裏咱們但願把結果存儲爲浮點數,因此除了用text屬性提取數值之外,還用float()函數作了轉換。

values = [float(item.text) for item in values]
複製代碼

顯示一下前5行:

values[:5]
複製代碼
[64.0, 163.0, 118.0, 110.0, 83.0]
複製代碼

數據被正確轉換成了浮點數。

咱們手裏,分別有了日期和交易價格中位數記錄列表。下面咱們將其轉換成爲Pandas數據框,而且存儲於df2變量裏。

df2 = pd.DataFrame({'dates':dates, 'values':values})
複製代碼

看看df2的前幾行:

df2.head()
複製代碼

數據咱們有了,下面也用咱們的自編函數整理一下:

df2 = arrange_time_dataframe(df2)
複製代碼

而後咱們嘗試對df2繪圖:

df2.plot(figsize=(16, 6))
複製代碼

png

XML數據讀取和檢視成功。

小結

至此,你已經嘗試瞭如何把CSV、JSON和XML數據讀入到Pandas數據框,而且作最基本的時間序列可視化展現。

你可能會有如下疑問:

既然CSV文件這麼小巧,Pandas讀取起來也方便,爲何還要費勁去學那麼難用的JSON和XML數據讀取方法呢?

這是個好問題!

我能想到的,至少有兩個緣由。

首先,我們找到的Quandl平臺,全方位提供數據的下載格式,幾乎涵蓋了所有常見數據格式類別。但這只是特例。大多數的開放數據平臺,是不提供這麼多種數據格式供你下載的。所以,當你拿到的數據只有JSON或者XML格式時,瞭解如何讀取它們,就很重要。

其次,JSON或XML附加的那些內容,毫不是無心義的。它們能夠幫助你檢查數據的完整性合法性。你甚至還能夠自行定義語義標準,以便和他人進行高效的數據交換。

若是你對JSON和XML格式感興趣,但願系統學習,那我推薦你到Stanford Online這個MOOC平臺上學習數據庫課程

祝進步!

討論

你平時從哪些開放數據平臺下載過數據?都接觸過哪些數據格式?你用什麼工具來整理和分析它們呢?有沒有比本文更高效的方法?歡迎留言,把你的經驗和思考分享給你們,咱們一塊兒交流討論。

喜歡請點贊。還能夠微信關注和置頂個人公衆號「玉樹芝蘭」(nkwangshuyi)

若是你對數據科學感興趣,不妨閱讀個人系列教程索引貼《如何高效入門數據科學?》,裏面還有更多的有趣問題及解法。

相關文章
相關標籤/搜索