Pandas資料結構詳解 | 輕鬆玩轉Pandas(1)

王偉同學發表於2019-03-03

教你學會 Pandas 不是我的目的,教你輕鬆玩轉 Pandas 才是我的目的。我會通過一系列例項來帶入 Pandas 的知識點,讓你在學習 Pandas 的路上不再枯燥。

宣告:我所寫的輕鬆玩轉 Pandas 教程都是免費的,如果對你有幫助,你可以持續關注我。

Pandas資料結構詳解 | 輕鬆玩轉Pandas(1)

Pandas 有很多高階的功能,但是想要掌握高階功能前,需要先掌握它的基礎知識,Pandas 中的資料結構算是非常基礎的知識之一了。

Pandas 常用的資料結構有兩種:Series 和 DataFrame。這些資料結構構建在 Numpy 陣列之上,這意味著它們效率很高。我們來分別看看這些資料結構都長什麼樣子吧。

# 匯入相關庫
import numpy as np
import pandas as pd
複製程式碼

Series

簡介

Series 是一個帶有 名稱 和索引的一維陣列,既然是陣列,肯定要說到的就是陣列中的元素型別,在 Series 中包含的資料型別可以是整數、浮點、字串、Python物件等。

假定有一個場景是:儲存一些使用者的資訊,暫時只包括年齡資訊。

我們可以通過 Series 來儲存,這裡我們通過 Series 儲存了四個年齡:18/30/25/40,只需將要儲存的資料構建成一個陣列,然後賦值給data引數即可

# 儲存了 4 個年齡:18/30/25/40
user_age = pd.Series(data=[18, 30, 25, 40])
user_age
複製程式碼
0    18
1    30
2    25
3    40
dtype: int64
複製程式碼

可以看到,已經正確將多個年齡儲存到 Series 中了,你可能會想,單獨儲存了年齡有什麼用,我怎麼知道這個年齡屬於哪個使用者呢?

我們可以通過 Series 的 index(索引)來解決這個問題。由於有四個年齡,自然地也需要四個姓名,所以我們需要構建一個與 data 長度相同的陣列,然後通過下面的操作即可滿足要求。

user_age.index = ["Tom", "Bob", "Mary", "James"]
user_age
複製程式碼
Tom      18
Bob      30
Mary     25
James    40
dtype: int64
複製程式碼

你看,現在姓名與年齡已經完全對應上了。雖然說我們自己知道 Tom/Bob 這些是姓名,但是別人不知道啊,我們怎麼告訴他人呢?

要想讓別人知道,我們可以為 index 起個名字。

user_age.index.name = "name"
user_age
複製程式碼
name
Tom      18
Bob      30
Mary     25
James    40
dtype: int64
複製程式碼

可能你還會想,如果別人在看我寫的程式碼,怎麼能快速的知道我這寫的到底是什麼玩意呢?

別急,就像我們給index起名字一樣,我們也可以給 Series 起個名字。

user_age.name="user_age_info"
user_age
複製程式碼
name
Tom      18
Bob      30
Mary     25
James    40
Name: user_age_info, dtype: int64
複製程式碼

通過上面一系列的操作,我們對 Series 的結構上有了基本的瞭解,簡單來說,一個 Series 包括了 data、index 以及 name

上面的操作非常方便做演示來使用,如果想要快速實現上面的功能,可以通過以下方式來實現。

# 構建索引
name = pd.Index(["Tom", "Bob", "Mary", "James"], name="name")
# 構建 Series
user_age = pd.Series(data=[18, 30, 25, 40], index=name, name="user_age_info")
user_age
複製程式碼
name
Tom      18
Bob      30
Mary     25
James    40
Name: user_age_info, dtype: int64
複製程式碼

另外,需要說明的是我們在構造 Series 的時候,並沒有設定每個元素的資料型別,這個時候,Pandas 會自動判斷一個資料型別,並作為 Series 的型別。

當然了,我們也可以自己手動指定資料型別。

# 指定型別為浮點型
user_age = pd.Series(data=[18, 30, 25, 40], index=name, name="user_age_info", dtype=float)
user_age
複製程式碼
name
Tom      18.0
Bob      30.0
Mary     25.0
James    40.0
Name: user_age_info, dtype: float64
複製程式碼

Series 像什麼

Series 包含了 dict 的特點,也就意味著可以使用與 dict 類似的一些操作。我們可以將 index 中的元素看成是 dict 中的 key。

# 獲取 Tom 的年齡
user_age["Tom"]
複製程式碼
18.0
複製程式碼

此外,可以通過 get 方法來獲取。通過這種方式的好處是當索引不存在時,不會丟擲異常。

user_age.get("Tom")
複製程式碼
18.0
複製程式碼

Series 除了像 dict 外,也非常像 ndarray,這也就意味著可以採用切片操作。

# 獲取第一個元素
user_age[0]
複製程式碼
18.0
複製程式碼
# 獲取前三個元素
user_age[:3]
複製程式碼
name
Tom     18.0
Bob     30.0
Mary    25.0
Name: user_age_info, dtype: float64
複製程式碼
# 獲取年齡大於30的元素
user_age[user_age > 30]
複製程式碼
name
James    40.0
Name: user_age_info, dtype: float64
複製程式碼
# 獲取第4個和第二個元素
user_age[[3, 1]]
複製程式碼
name
James    40.0
Bob      30.0
Name: user_age_info, dtype: float64
複製程式碼

可以看到,無論我們通過切片如何操作 Series ,它都能夠自動對齊 index。

Series 的向量化操作

Series 與 ndarray 一樣,也是支援向量化操作的。同時也可以傳遞給大多數期望 ndarray 的 NumPy 方法。

user_age + 1
複製程式碼
name
Tom      19.0
Bob      31.0
Mary     26.0
James    41.0
Name: user_age_info, dtype: float64
複製程式碼
np.exp(user_age)
複製程式碼
name
Tom      6.565997e+07
Bob      1.068647e+13
Mary     7.200490e+10
James    2.353853e+17
Name: user_age_info, dtype: float64
複製程式碼

DataFrame

DataFrame 是一個帶有索引的二維資料結構,每列可以有自己的名字,並且可以有不同的資料型別。你可以把它想象成一個 excel 表格或者資料庫中的一張表,DataFrame 是最常用的 Pandas 物件。

我們繼續使用之前的例項來講解 DataFrame,在儲存使用者資訊時,除了年齡之外,我還想儲存使用者所在的城市。如何通過 DataFrame 實現呢?

可以構建一個 dict,key 是需要儲存的資訊,value 是資訊列表。然後將 dict 傳遞給 data 引數

index = pd.Index(data=["Tom", "Bob", "Mary", "James"], name="name")

data = {
    "age": [18, 30, 25, 40],
    "city": ["BeiJing", "ShangHai", "GuangZhou", "ShenZhen"]
}

user_info = pd.DataFrame(data=data, index=index)
user_info
複製程式碼
age city
name
Tom 18 BeiJing
Bob 30 ShangHai
Mary 25 GuangZhou
James 40 ShenZhen

可以看到,我們成功構建了一個 DataFrame,這個 DataFrame 的索引是使用者性別,還有兩列分別是使用者的年齡和城市資訊。

除了上面這種傳入 dict 的方式構建外,我們還可以通過另外一種方式來構建。這種方式是先構建一個二維陣列,然後再生成一個列名稱列表

data = [[18, "BeiJing"], 
        [30, "ShangHai"], 
        [25, "GuangZhou"], 
        [40, "ShenZhen"]]
columns = ["age", "city"]

user_info = pd.DataFrame(data=data, index=index, columns=columns)
user_info
複製程式碼
age city
name
Tom 18 BeiJing
Bob 30 ShangHai
Mary 25 GuangZhou
James 40 ShenZhen

訪問行

在生成了 DataFrame 之後,可以看到,每一行就表示某一個使用者的資訊,假如我想要訪問 Tom 的資訊,我該如何操作呢?

一種辦法是通過索引名來訪問某行,這種辦法需要藉助 loc 方法。

user_info.loc["Tom"]
複製程式碼
age          18
city    BeiJing
Name: Tom, dtype: object
複製程式碼

除了直接通過索引名來訪問某一行資料之外,還可以通過這行所在的位置來選擇這一行。

user_info.iloc[0]
複製程式碼
age          18
city    BeiJing
Name: Tom, dtype: object
複製程式碼

現在能夠訪問某一個使用者的資訊了,那麼我如何訪問多個使用者的資訊呢?也就是如何訪問多行呢?

藉助行切片可以輕鬆完成,來看這裡。

user_info.iloc[1:3]
複製程式碼
age city
name
Bob 30 ShangHai
Mary 25 GuangZhou

訪問列

學會了如何訪問行資料之外,自然而然會想到如何訪問列。我們可以通過屬性(“.列名”)的方式來訪問該列的資料,也可以通過[column]的形式來訪問該列的資料。

假如我想獲取所有使用者的年齡,那麼可以這樣操作。

user_info.age
複製程式碼
name
Tom      18
Bob      30
Mary     25
James    40
Name: age, dtype: int64
複製程式碼
user_info["age"]
複製程式碼
name
Tom      18
Bob      30
Mary     25
James    40
Name: age, dtype: int64
複製程式碼

如果想要同時獲取年齡和城市該如何操作呢?

# 可以變換列的順序
user_info[["city", "age"]]
複製程式碼
city age
name
Tom BeiJing 18
Bob ShangHai 30
Mary GuangZhou 25
James ShenZhen 40

新增/刪除列

在生成了 DataFrame 之後,突然你發現好像缺失了使用者的性別這個資訊,那麼如何新增呢?

如果所有的性別都一樣,我們可以通過傳入一個標量,Pandas 會自動幫我們廣播來填充所有的位置。

user_info["sex"] = "male"
user_info
複製程式碼
age city sex
name
Tom 18 BeiJing male
Bob 30 ShangHai male
Mary 25 GuangZhou male
James 40 ShenZhen male

如果想要刪除某一列,可以使用 pop 方法來完成。

user_info.pop("sex")
user_info
複製程式碼
age city
name
Tom 18 BeiJing
Bob 30 ShangHai
Mary 25 GuangZhou
James 40 ShenZhen

如果使用者的性別不一致的時候,我們可以通過傳入一個 like-list 來新增新的一列。

user_info["sex"] = ["male", "male", "female", "male"]
user_info
複製程式碼
age city sex
name
Tom 18 BeiJing male
Bob 30 ShangHai male
Mary 25 GuangZhou female
James 40 ShenZhen male

通過上面的例子可以看出,我們建立新的列的時候都是在原有的 DataFrame 上修改的,也就是說如果新增了新的一列之後,原有的 DataFrame 會發生改變。

如果想要保證原有的 DataFrame 不改變的話,我們可以通過 assign 方法來建立新的一列。

user_info.assign(age_add_one = user_info["age"] + 1)
複製程式碼
age city sex age_add_one
name
Tom 18 BeiJing male 19
Bob 30 ShangHai male 31
Mary 25 GuangZhou female 26
James 40 ShenZhen male 41
user_info.assign(sex_code = np.where(user_info["sex"] == "male", 1, 0))
複製程式碼
age city sex sex_code
name
Tom 18 BeiJing male 1
Bob 30 ShangHai male 1
Mary 25 GuangZhou female 0
James 40 ShenZhen male 1

想要學習更多關於人工智慧的知識,請關注公眾號:AI派

qrcode_for_gh_60cef389e81c_258.jpg

這裡我將整篇文章的內容整理成了pdf,想要pdf檔案的可以在公眾號後臺回覆關鍵字:pandas01

更多Pandas知識見:輕鬆玩轉Pandas

相關文章