A place for study and research

Python 100 Days Day70 Introduction to Pandas-1

|

author: jackfrued

Pandas的應用-1

Pandas是Wes McKinney在2008年開發的一個強大的分析結構化數據的工具集。Pandas以NumPy為基礎(數據表示和運算),提供了用於數據處理的函數和方法,對數據分析和數據挖掘提供了很好的支持;同時Pandas還可以跟數據可視化工具Matplotlib很好的整合在一起,非常輕松愉快的實現數據的可視化展示。

Pandas核心的數據類型是Series(數據系列)、DataFrame(數據表/數據框),分別用於處理一維和二維的數據,除此之外還有一個名為Index的類型及其子類型,它為SeriesDataFrame提供了索引功能。日常工作中以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,也可以選擇mergesortheapsort;如果存在空值,那麽可以用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對象的數據作為縱坐標。

首先導入matplotlibpyplot模塊並進行必要的配置。

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