Python 100 Days Day70 Introduction to Pandas-1
26 Sep 2022 | beginner pythonauthor: jackfrued
Pandas的應用-1
Pandas是Wes McKinney在2008年開發的一個強大的分析結構化數據的工具集。Pandas以NumPy為基礎(數據表示和運算),提供了用於數據處理的函數和方法,對數據分析和數據挖掘提供了很好的支持;同時Pandas還可以跟數據可視化工具Matplotlib很好的整合在一起,非常輕松愉快的實現數據的可視化展示。
Pandas核心的數據類型是Series(數據系列)、DataFrame(數據表/數據框),分別用於處理一維和二維的數據,除此之外還有一個名為Index的類型及其子類型,它為Series和DataFrame提供了索引功能。日常工作中以DataFrame使用最為廣泛,因為二維的數據本質就是一個有行有列的表格(想一想Excel電子表格和關系型數據庫中的二維表)。上述這些類型都提供了大量的處理數據的方法,數據分析師可以以此為基礎實現對數據的各種常規處理。
Series的應用
Pandas庫中的Series對象可以用來表示一維數據結構,跟數組非常類似,但是多了一些額外的功能。Series的內部結構包含了兩個數組,其中一個用來保存數據,另一個用來保存數據的索引。
創建Series對象
提示:在執行下面的代碼之前,請先導入
pandas以及相關的庫文件,具體的做法可以參考上一章。
方法1:通過列表或數組創建Series對象
代碼:
# data參數表示數據,index參數表示數據的索引(標簽)
# 如果沒有指定index屬性,默認使用數字索引
ser1 = pd.Series(data=[320, 180, 300, 405], index=['一季度', '二季度', '三季度', '四季度'])
ser1
輸出:
一季度 320
二季度 180
三季度 300
四季度 405
dtype: int64
方法2:通過字典創建Series對象。
代碼:
# 字典中的鍵就是數據的索引(標簽),字典中的值就是數據
ser2 = pd.Series({'一季度': 320, '二季度': 180, '三季度': 300, '四季度': 405})
ser2
輸出:
一季度 320
二季度 180
三季度 300
四季度 405
dtype: int64
索引和切片
跟數組一樣,Series對象也可以進行索引和切片操作,不同的是Series對象因為內部維護了一個保存索引的數組,所以除了可以使用整數索引通過位置檢索數據外,還可以通過自己設置的索引標簽獲取對應的數據。
使用整數索引
代碼:
print(ser2[0], ser[1], ser[2], ser[3])
ser2[0], ser2[3] = 350, 360
print(ser2)
輸出:
320 180 300 405
一季度 350
二季度 180
三季度 300
四季度 360
dtype: int64
提示:如果要使用負向索引,必須在創建
Series對象時通過index屬性指定非數值類型的標簽。
使用自定義的標簽索引
代碼:
print(ser2['一季度'], ser2['三季度'])
ser2['一季度'] = 380
print(ser2)
輸出:
350 300
一季度 380
二季度 180
三季度 300
四季度 360
dtype: int64
切片操作
代碼:
print(ser2[1:3])
print(ser2['二季度':'四季度'])
輸出:
二季度 180
三季度 300
dtype: int64
二季度 500
三季度 500
四季度 520
dtype: int64
代碼:
ser2[1:3] = 400, 500
ser2
輸出:
一季度 380
二季度 400
三季度 500
四季度 360
dtype: int64
花式索引
代碼:
print(ser2[['二季度', '四季度']])
ser2[['二季度', '四季度']] = 500, 520
print(ser2)
輸出:
二季度 400
四季度 360
dtype: int64
一季度 380
二季度 500
三季度 500
四季度 520
dtype: int64
布爾索引
代碼:
ser2[ser2 >= 500]
輸出:
二季度 500
三季度 500
四季度 520
dtype: int64
####屬性和方法
Series對象的常用屬性如下表所示。
| 屬性 | 說明 |
|---|---|
dtype / dtypes |
返回Series對象的數據類型 |
hasnans |
判斷Series對象中有沒有空值 |
at / iat |
通過索引訪問Series對象中的單個值 |
loc / iloc |
通過一組索引訪問Series對象中的一組值 |
index |
返回Series對象的索引 |
is_monotonic |
判斷Series對象中的數據是否單調 |
is_monotonic_increasing |
判斷Series對象中的數據是否單調遞增 |
is_monotonic_decreasing |
判斷Series對象中的數據是否單調遞減 |
is_unique |
判斷Series對象中的數據是否獨一無二 |
size |
返回Series對象中元素的個數 |
values |
以ndarray的方式返回Series對象中的值 |
Series對象的方法很多,我們通過下面的代碼為大家介紹一些常用的方法。
統計相關的方法
Series對象支持各種獲取描述性統計信息的方法。
代碼:
# 求和
print(ser2.sum())
# 求均值
print(ser2.mean())
# 求最大
print(ser2.max())
# 求最小
print(ser2.min())
# 計數
print(ser2.count())
# 求標準差
print(ser2.std())
# 求方差
print(ser2.var())
# 求中位數
print(ser2.median())
Series對象還有一個名為describe()的方法,可以獲得上述所有的描述性統計信息,如下所示。
代碼:
ser2.describe()
輸出:
count 4.000000
mean 475.000000
std 64.031242
min 380.000000
25% 470.000000
50% 500.000000
75% 505.000000
max 520.000000
dtype: float64
提示:因為
describe()返回的也是一個Series對象,所以也可以用ser2.describe()['mean']來獲取平均值。
如果Series對象有重覆的值,我們可以使用unique()方法獲得去重之後的Series對象;可以使用nunique()方法統計不重覆值的數量;如果想要統計每個值重覆的次數,可以使用value_counts()方法,這個方法會返回一個Series對象,它的索引就是原來的Series對象中的值,而每個值出現的次數就是返回的Series對象中的數據,在默認情況下會按照出現次數做降序排列。
代碼:
ser3 = pd.Series(data=['apple', 'banana', 'apple', 'pitaya', 'apple', 'pitaya', 'durian'])
ser3.value_counts()
輸出:
apple 3
pitaya 2
durian 1
banana 1
dtype: int64
代碼:
ser3.nunique()
輸出:
4
數據處理的方法
Series對象的isnull()和notnull()方法可以用於空值的判斷,代碼如下所示。
代碼:
ser4 = pd.Series(data=[10, 20, np.NaN, 30, np.NaN])
ser4.isnull()
輸出:
0 False
1 False
2 True
3 False
4 True
dtype: bool
代碼:
ser4.notnull()
輸出:
0 True
1 True
2 False
3 True
4 False
dtype: bool
Series對象的dropna()和fillna()方法分別用來刪除空值和填充空值,具體的用法如下所示。
代碼:
ser4.dropna()
輸出:
0 10.0
1 20.0
3 30.0
dtype: float64
代碼:
# 將空值填充為40
ser4.fillna(value=40)
輸出:
0 10.0
1 20.0
2 40.0
3 30.0
4 40.0
dtype: float64
代碼:
# backfill或bfill表示用後一個元素的值填充空值
# ffill或pad表示用前一個元素的值填充空值
ser4.fillna(method='ffill')
輸出:
0 10.0
1 20.0
2 20.0
3 30.0
4 30.0
dtype: float64
需要提醒大家注意的是,dropna()和fillna()方法都有一個名為inplace的參數,它的默認值是False,表示刪除空值或填充空值不會修改原來的Series對象,而是返回一個新的Series對象來表示刪除或填充空值後的數據系列,如果將inplace參數的值修改為True,那麽刪除或填充空值會就地操作,直接修改原來的Series對象,那麽方法的返回值是None。後面我們會接觸到的很多方法,包括DataFrame對象的很多方法都會有這個參數,它們的意義跟這里是一樣的。
Series對象的mask()和where()方法可以將滿足或不滿足條件的值進行替換,如下所示。
代碼:
ser5 = pd.Series(range(5))
ser5.where(ser5 > 0)
輸出:
0 NaN
1 1.0
2 2.0
3 3.0
4 4.0
dtype: float64
代碼:
ser5.where(ser5 > 1, 10)
輸出:
0 10
1 10
2 2
3 3
4 4
dtype: int64
代碼:
ser5.mask(ser5 > 1, 10)
輸出:
0 0
1 1
2 10
3 10
4 10
dtype: int64
Series對象的duplicated()方法可以幫助我們找出重覆的數據,而drop_duplicates()方法可以幫我們刪除重覆數據。
代碼:
ser3.duplicated()
輸出:
0 False
1 False
2 True
3 False
4 True
5 True
6 False
dtype: bool
代碼:
ser3.drop_duplicates()
輸出:
0 apple
1 banana
3 pitaya
6 durian
dtype: object
Series對象的apply()和map()方法非常重要,它們可以用於數據處理,把數據映射或轉換成我們期望的樣子,這個操作在數據分析的數據準備階段非常重要。
代碼:
ser6 = pd.Series(['cat', 'dog', np.nan, 'rabbit'])
ser6
輸出:
0 cat
1 dog
2 NaN
3 rabbit
dtype: object
代碼:
ser6.map({'cat': 'kitten', 'dog': 'puppy'})
輸出:
0 kitten
1 puppy
2 NaN
3 NaN
dtype: object
代碼:
ser6.map('I am a {}'.format, na_action='ignore')
輸出:
0 I am a cat
1 I am a dog
2 NaN
3 I am a rabbit
dtype: object
代碼:
ser7 = pd.Series([20, 21, 12], index=['London', 'New York', 'Helsinki'])
ser7
輸出:
London 20
New York 21
Helsinki 12
dtype: int64
代碼:
ser7.apply(np.square)
輸出:
London 400
New York 441
Helsinki 144
dtype: int64
代碼:
ser7.apply(lambda x, value: x - value, args=(5, ))
輸出:
London 15
New York 16
Helsinki 7
dtype: int64
排序和取頭部值的方法
Series對象的sort_index()和sort_values()方法可以用於對索引和數據的排序,排序方法有一個名為ascending的布爾類型參數,該參數用於控制排序的結果是升序還是降序;而名為kind的參數則用來控制排序使用的算法,默認使用了quicksort,也可以選擇mergesort或heapsort;如果存在空值,那麽可以用na_position參數空值放在最前還是最後,默認是last,代碼如下所示。
代碼:
ser8 = pd.Series(
data=[35, 96, 12, 57, 25, 89],
index=['grape', 'banana', 'pitaya', 'apple', 'peach', 'orange']
)
# 按值從小到大排序
ser8.sort_values()
輸出:
pitaya 12
peach 25
grape 35
apple 57
orange 89
banana 96
dtype: int64
代碼:
# 按索引從大到小排序
ser8.sort_index(ascending=False)
輸出:
pitaya 12
peach 25
orange 89
grape 35
banana 96
apple 57
dtype: int64
如果要從Series對象中找出元素中最大或最小的“Top-N”,實際上是不需要對所有的值進行排序的,可以使用nlargest()和nsmallest()方法來完成,如下所示。
代碼:
# 值最大的3個
ser8.nlargest(3)
輸出:
banana 96
orange 89
apple 57
dtype: int64
代碼:
# 值最小的2個
ser8.nsmallest(2)
輸出:
pitaya 12
peach 25
dtype: int64
繪制圖表
Series對象有一個名為plot的方法可以用來生成圖表,如果選擇生成折線圖、餅圖、柱狀圖等,默認會使用Series對象的索引作為橫坐標,使用Series對象的數據作為縱坐標。
首先導入matplotlib中pyplot模塊並進行必要的配置。
import matplotlib.pyplot as plt
# 配置支持中文的非襯線字體(默認的字體無法顯示中文)
plt.rcParams['font.sans-serif'] = ['SimHei', ]
# 使用指定的中文字體時需要下面的配置來避免負號無法顯示
plt.rcParams['axes.unicode_minus'] = False
創建Series對象並繪制對應的柱狀圖。
ser9 = pd.Series({'一季度': 400, '二季度': 520, '三季度': 180, '四季度': 380})
# 通過Series對象的plot方法繪圖(kind='bar'表示繪制柱狀圖)
ser9.plot(kind='bar', color=['r', 'g', 'b', 'y'])
# x軸的坐標旋轉到0度(中文水平顯示)
plt.xticks(rotation=0)
# 在柱狀圖的柱子上繪制數字
for i in range(4):
plt.text(i, ser9[i] + 5, ser9[i], ha='center')
# 顯示圖像
plt.show()

繪制反映每個季度占比的餅圖。
# autopct參數可以配置在餅圖上顯示每塊餅的占比
ser9.plot(kind='pie', autopct='%.1f%%')
# 設置y軸的標簽(顯示在餅圖左側的文字)
plt.ylabel('各季度占比')
plt.show()

Comments