Python 資料處理系列部落格來啦!
本系列將以《Python資料處理》這本書為基礎,以書中每章一篇部落格的形式帶大家一起學習 Python 資料處理。書中有些地方講的不太詳細,我會查閱其他資料來補充,力爭每篇部落格都把知識點涵蓋全且通俗易懂。
這本書主要講了如何用 Python 處理各種型別的檔案,如 JSON、XML、CSV、Excel、PDF 等。後面幾章還會講資料清洗、網頁抓取、自動化和規模化等使用技能。我也是 Python 初學者,將以初學者的角度寫文章,所以部落格對初學者比較友好。
python 基礎如果你還不熟練,可以先看看我的另一篇部落格:十分鐘快速入門 Python
100
多位經驗豐富的開發者參與,在 Github 上獲得了近1000
個star
的全棧全平臺開源專案想了解或參與嗎?
專案地址:github.com/cachecats/c…
前言
以易於機器理解的方式來儲存資料的檔案格式,通常被稱作機器可讀的 (machine readable)。常見的機器可讀格式包括:
- 逗號分隔值(Comma-Separated Values,CSV)
- JavaScript 物件符號(JavaScript Object Notation,JSON)
- 可擴充套件標記語言(eXtensible Markup Language,XML)
在口語和書面語中,提到這些資料格式時通常使用它們的短名字(如 CSV)。 我們將使用這些縮寫 。
一、CSV資料
CSV 檔案(簡稱為 CSV)是指將資料列用逗號分隔的檔案。檔案的副檔名是 .csv。
另一種資料型別,叫作製表符分隔值(tab-separated values,TSV)資料,有時也與 CSV歸為一類。TSV 與 CSV 唯一的不同之處在於,資料列之間的分隔符是製表符(tab),而不是逗號。檔案的副檔名通常是 .tsv,但有時也用 .csv 作為副檔名。從本質上來看,.tsv 檔案與 .csv 檔案在Python 中的作用是相同的。
我們採用的資料來源是從世界衛生組織(www.who.int/zh/home)中下載…
開啟世衛組織官網後,點選“健康主題”,“資料和統計” 就能找到很多資料。
這裡下載了關於嬰幼兒護理的統計資料,並重新命名為 data.csv
。
csv 檔案可以直接用 Excel 開啟直觀的看到,我們用 Excel 開啟如下圖:
接下來就要用 Python 來簡單的處理這些資料。
以列表的形式讀取csv資料
編寫一個讀取 csv 檔案的程式:
import csv
csvfile = open('./data.csv', 'r')
reader = csv.reader(csvfile)
for row in reader:
print(row)
複製程式碼
import csv
將匯入 Python 自帶的 csv 模組。csvfile = open('./data.csv', 'r')
以只讀的形式開啟資料檔案並儲存到變數 csvfile
中。然後呼叫 csv 的 reader()
方法將輸出儲存在 reader
變數中,再用 for 迴圈將資料輸出。
執行程式,控制檯輸出:
可以看到跟 Excel 開啟的內容一致。
以字典的形式讀取csv資料
改一下程式碼,以字典的形式讀取 csv
import csv
csvfile = open('./data.csv', 'r')
reader = csv.DictReader(csvfile)
for row in reader:
print(row)
複製程式碼
控制檯輸出:
二、JSON資料
同樣在世衛組織官網下載資料來源,重新命名為 data.json
。用格式化工具開啟 json
檔案如下:
編寫程式對 json 進行解析
import json
# 將 json 檔案讀取成字串
json_data = open('./data.json').read()
# 對json資料解碼
data = json.loads(json_data)
# data 的型別是 字典dict
print(type(data))
# 直接列印 data
print(data)
# 遍歷字典
for k, v in data.items():
print(k + ':' + str(v))
複製程式碼
控制檯輸出:
Python3 中可以使用 json 模組來對 JSON 資料進行編解碼,它包含了兩個函式:
- json.dumps(): 對資料進行編碼。
- json.loads(): 對資料進行解碼。
在json的編解碼過程中,python 的原始型別與json型別會相互轉換,具體的轉化對照如下:
Python 編碼為 JSON 型別轉換對應表:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int- & float-derived Enums | number |
True | true |
False | false |
None | null |
JSON 解碼為 Python 型別轉換對應表:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
三、XML 資料
XML 格式的資料既便於機器讀取,也便於人工讀取。但是對於本章的資料集來說,預覽並理解 CSV 檔案和 JSON 檔案要比 XML 檔案容易得多。
xml 格式說明:
- Tag: 使用<和>包圍的部分;
- Element:被Tag包圍的部分,如 2003,可以認為是一個節點,它可以有子節點;
- Attribute:在Tag中可能存在的 name/value 對,如示例中的 title="Enemy Behind",一般表示屬性。
世衛組織的資料不好理解,我們們用個簡單的能看得懂的電影資料來做演示:
<?xml version="1.0" encoding="UTF-8"?>
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title="Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>
複製程式碼
這個資料相對來說比較簡單,只有三層。但原理掌握了,幾層資料都能搞定。
下面編寫程式碼對上面的 xml 進行解析,解析之後再分別格式化成字典和 json 格式的資料輸出:
from xml.etree import ElementTree as ET
import json
tree = ET.parse('./resource/movie.xml')
root = tree.getroot()
all_data = []
for movie in root:
# 儲存電影資料的字典
movie_data = {}
# 儲存屬性的字典
attr_data = {}
# 取出 type 標籤的值
movie_type = movie.find('type')
attr_data['type'] = movie_type.text
# 取出 format 標籤的值
movie_format = movie.find('format')
attr_data['format'] = movie_format.text
# 取出 year 標籤的值
movie_year = movie.find('year')
if movie_year:
attr_data['year'] = movie_year.text
# 取出 rating 標籤的值
movie_rating = movie.find('rating')
attr_data['rating'] = movie_rating.text
# 取出 stars 標籤的值
movie_stars = movie.find('stars')
attr_data['stars'] = movie_stars.text
# 取出 description 標籤的值
movie_description = movie.find('description')
attr_data['description'] = movie_description.text
# 獲取電影名字,以電影名為字典的鍵,屬性資訊為字典的值
movie_title = movie.attrib.get('title')
movie_data[movie_title] = attr_data
# 存入列表中
all_data.append(movie_data)
print(all_data)
# all_data 此時是一個列表物件,用 json.dumps() 將python物件轉換為 json 字串
json_str = json.dumps(all_data)
print(json_str)
複製程式碼
註釋寫的比較詳細,下面介紹下 ElementTree
提供的方法。
3.1 解析的三種方法
ElementTree
解析 xml 有三種方法:
-
呼叫parse()方法,返回解析樹
tree = ET.parse('./resource/movie.xml') root = tree.getroot() 複製程式碼
-
呼叫from_string(),返回解析樹的根元素
data = open('./resource/movie.xml').read() root = ET.fromstring(data) 複製程式碼
-
呼叫 ElementTree 類的
ElementTree(self, element=None, file=None)
方法tree = ET.ElementTree(file="./resource/movie.xml") root = tree.getroot() 複製程式碼
3.2 Element 物件
class xml.etree.ElementTree.Element(tag, attrib={}, **extra)
Element 物件的屬性
- tag: 標籤
- text: 去除標籤,獲得標籤中的內容。
- attrib: 獲取標籤中的屬性和屬性值。
- tail: 這個屬性可以用來儲存與元素相關聯的附加資料。它的值通常是字串,但可能是特定於應用程式的物件。
Element 物件的方法
-
clear()
:清除所有子元素和所有屬性,並將文字和尾部屬性設定為None。 -
get(attribute_name, default=None)
:通過指定屬性名獲取屬性值。 -
items()
:以鍵值對的形式返回元素屬性。 -
keys()
:以列表的方式返回元素名。 -
set(attribute_name,attribute_value)
:在某標籤中設定屬性和屬性值。 -
append(subelement)
:將元素子元素新增到元素的子元素內部列表的末尾。 -
extend(subelements)
:追加子元素。 -
find(match, namespaces=None)
:找到第一個匹配的子元素,match可以是標籤名或者path。返回Elememt例項或None。 -
findall(match, namespaces=None)
:找到所有匹配的子元素,返回的是一個元素列表。 -
findtext(match, default=None, namespaces=None)
:找到匹配第一個子元素的文字。返回的是匹配元素中的文字內容。 -
getchildren()
:Python3.2後使用list(elem)
或 iteration. -
getiterator(tag=None)
:Python3.2後使用Element.iter()
-
iter(tag=None)
:以當前元素為根建立樹迭代器。迭代器遍歷這個元素和它下面的所有元素(深度優先順序)。如果標籤不是None或’*’,那麼只有標籤等於標籤的元素才會從迭代器返回。如果在迭代過程中修改樹結構,則結果是未定義的。 -
iterfind(match, namespaces=None)
: 匹配滿足條件的子元素,返回元素。
3.3 ElementTree 物件
class xml.etree.ElementTree.ElementTree(element=None, file=None)
ElementTree是一個包裝器類,這個類表示一個完整的元素層次結構,併為標準XML的序列化新增了一些額外的支援。
-
setroot(element)
:替換根元素,原來的根元素中的內容會消失。 -
find(match, namespaces=None)
:從根元素開始匹配和 Element.find()作用一樣。 -
findall(match, namespaces=None)
:從根元素開始匹配和 Element.findall()作用一樣。 -
findtext(match, default=None, namespaces=None)
:從根元素開始匹配和 Element.findtext()作用一樣。 -
getiterator(tag=None)
:Python3.2後使用 ElementTree.iter() 代替。 -
iter(tag=None)
:迭代所有元素 -
iterfind(match, namespaces=None)
:從根元素開始匹配和 Element.iterfind()作用一樣。 -
parse(source, parser=None)
:解析xml文字,返回根元素。 -
write(file, encoding=”us-ascii”, xml_declaration=None, default_namespace=None, method=”xml”, *, short_empty_elements=True)
:寫出XML文字。
對 JSON、XML、CSV三種格式資料的處理就講完啦,下期講如何處理 Excel 檔案,歡迎關注。
全棧全平臺開源專案 CodeRiver
CodeRiver 是一個免費的專案協作平臺,願景是打通 IT 產業上下游,無論你是產品經理、設計師、程式設計師或是測試,還是其他行業人員,只要有好的創意、想法,都可以來 CodeRiver 免費釋出專案,召集志同道合的隊友一起將夢想變為現實!
CodeRiver 本身還是一個大型開源專案,致力於打造全棧全平臺企業級精品開源專案。涵蓋了 React、Vue、Angular、小程式、ReactNative、Android、Flutter、Java、Node 等幾乎所有主流技術棧,主打程式碼質量。
目前已經有近 100
名優秀開發者參與,github 上的 star
數量將近 1000
個。每個技術棧都有多位經驗豐富的大佬坐鎮,更有兩位架構師指導專案架構。無論你想學什麼語言處於什麼技術水平,相信都能在這裡學有所獲。
通過 高質量原始碼 + 部落格 + 視訊
,幫助每一位開發者快速成長。
您的鼓勵是我們前行最大的動力,歡迎點贊,歡迎送小星星✨ ~