Pandas 是 Wes McKinney 在2008年開發的一個強大的分析結構化資料的工具集。Pandas 以 NumPy 為基礎(實現資料儲存和運算)
提供了專門用於資料分析的型別、方法和函式,對資料分析和資料探勘提供了很好的支援;
同時 pandas 還可以跟資料視覺化工具 matplotlib 很好的整合在一起,非常輕鬆愉快的實現資料視覺化呈現。
Pandas 核心的資料型別是Series(資料系列)、DataFrame(資料窗/資料框),分別用於處理一維和二維的資料
除此之外,還有一個名為Index的型別及其子型別,它們為Series和DataFrame提供了索引功能。
日常工作中DataFrame使用得最為廣泛,因為二維的資料結構剛好可以對應有行有列的表格。
Series和DataFrame都提供了大量的處理資料的方法,資料分析師以此為基礎,可以實現對資料的篩選、合併、拼接、清洗、預處理、聚合、透視和視覺化等各種操作
Series 物件
# -*- coding: utf-8 -*-
#建立Series物件""
#Pandas 庫中的Series物件可以用來表示一維資料結構,但是多了索引和一些額外的功能。
#Series型別的內部結構包含了兩個陣列,其中一個用來儲存資料,另一個用來儲存資料的索引。我們可以透過列表或陣列建立Series物件
import numpy
import pandas
#說明:Series構造器中的data參數列示資料,index參數列示資料的索引,相當於資料對應的標籤。
ser1 = pandas.Series(data=[120, 380, 250, 360], index=['一季度', '二季度', '三季度', '四季度'])
print(ser1)
'''
一季度 120
二季度 380
三季度 250
四季度 360
dtype: int64
'''
print('---------------------------------------------')
#透過字典建立Series物件。
#說明:透過字典建立Series物件時,字典的鍵就是資料的標籤(索引),鍵對應的值就是資料。
ser2 = pandas.Series({'一季度': 320, '二季度': 380, '三季度': 250, '四季度': 360})
print(ser2)
print('---------------------------------------------')
#Series物件的運算
#標量運算
#我們嘗試給剛才的ser1每個季度加上10,程式碼如下所示。
ser1 += 10
print(ser1, '\n')
'''
一季度 130
二季度 390
三季度 260
四季度 370
dtype: int64
'''
#向量運算
#我們嘗試把ser1和ser2對應季度的資料加起來,程式碼如下所示。
ser3 = ser1 + ser2
print(ser3, '\n')
'''
一季度 450
二季度 770
三季度 510
四季度 730
dtype: int64
'''
#索引運算
#跟陣列一樣,Series物件也可以進行索引和切片操作,不同的是Series物件因為內部維護了一個儲存索引的陣列
#所以除了可以使用整數索引檢索資料外,還可以透過自己設定的索引(標籤)獲取對應的資料。
#使用整數索引
print(ser1[2]) #260
#使用自定義索引。
print(ser1['三季度']) #260
#賦值
ser1['一季度'] = 100
print(ser1)
'''
一季度 100
二季度 390
三季度 260
四季度 370
dtype: int64
'''
print('---------------------------------------------')
#切片索引
#Series物件的切片操作跟列表、陣列類似,透過給出起始和結束索引,從原來的Series物件中取出或修改部分資料
# 這裡也可以使用整數索引和自定義的索引
print(ser2[1:3], '\n') #[1:3] 表示從索引為1(包含)到索引為3(不包含)的資料
'''
二季度 380
三季度 250
dtype: int64
'''
#提示:在使用自定義索引進行切片時,結束索引對應的元素也是可以取到的。
print(ser2['二季度':'三季度'], '\n')
'''
二季度 380
三季度 250
dtype: int64
'''
#修改
ser2[1:3] = 400, 500
print(ser2, '\n')
'''
一季度 320
二季度 400
三季度 500
四季度 360
dtype: int64
'''
print('---------------------------------------------')
#花式索引
#取值
print(ser2[['二季度', '四季度']], '\n') # = ser2['二季度':'四季度']
'''
二季度 400
四季度 360
dtype: int64
'''
#修改值
ser2[['二季度', '四季度']] = 600, 520
print(ser2, '\n')
'''
一季度 320
二季度 600
三季度 500
四季度 520
dtype: int64
'''
print('---------------------------------------------')
#布林索引
print(ser2[ser2 >= 500])
'''
二季度 600
三季度 500
四季度 520
dtype: int64
'''
Series 物件的屬性和方法
Series物件的屬性和方法非常多,看下面的表格,它展示了Series物件常用的屬性。
屬性 | 說明 |
---|---|
dtype / dtypes |
返回Series 物件的資料型別 |
hasnans |
判斷Series 物件中有沒有空值 |
at / iat |
透過索引訪問Series 物件中的單個值 |
loc / iloc |
透過索引訪問Series 物件中的單個值或一組值 |
index |
返回Series 物件的索引(Index 物件) |
is_monotonic |
判斷Series 物件中的資料是否單調 |
is_monotonic_increasing |
判斷Series 物件中的資料是否單調遞增 |
is_monotonic_decreasing |
判斷Series 物件中的資料是否單調遞減 |
is_unique |
判斷Series 物件中的資料是否獨一無二 |
size |
返回Series 物件中元素的個數 |
values |
以ndarray 的方式返回Series 物件中的值(ndarray 物件 |
我們可以透過下面的程式碼來了解Series物件的屬性。
#Series物件的屬性和方法
print(ser2.dtype) #資料型別
print(ser2.hasnans) #判斷有無空值
print(ser2.index) #索引
print(ser2.values) #值
print(ser2.is_monotonic_increasing) #判斷索引是否是單調遞增
print(ser2.is_unique) #判斷索引是否唯一
'''
int64
False
Index(['一季度', '二季度', '三季度', '四季度'], dtype='object')
[320 600 500 520]
False
True
'''
print('----------------------------------------------')
#統計相關
#Series物件支援各種獲取描述性統計資訊的方法。
print(ser2.count()) #統計非空值的個數
print(ser2.sum()) #統計所有值的和
print(ser2.mean()) #統計所有值的平均值
print(ser2.median()) #統計所有值的中位數
print(ser2.max())
print(ser2.min())
print(ser2.std()) #統計所有值的標準差
print(ser2.var()) #統計所有值的方差
'''
4
1940
485.0
510.0
600
320
118.18065267490557
13966.666666666666
'''
print('----------------------------------------------')
#Series物件還有一個名為describe()的方法,可以獲得上述所有的描述性統計資訊
print(ser2.describe())
'''
count 4.000000
mean 485.000000
std 118.180653
min 320.000000
25% 455.000000
50% 510.000000
75% 540.000000
max 600.000000
dtype: float64
'''
#提示:因為describe()返回的也是一個Series物件
#所以也可以用ser2.describe()['mean']來獲取平均值,用ser2.describe()[['max', 'min']]來獲取最大值和最小值。
print(ser2.describe()['mean'])
print('----------------------------------------------')
#統計重複項
#如果Series物件有重複的值,我們可以使用unique()方法獲得由獨一無二的值構成的陣列;
# 可以使用nunique()方法統計不重複值的數量;如果想要統計每個值重複的次數,可以使用value_counts()方法,這個方法會返回一個Series物件,
# 它的索引就是原來的Series物件中的值,而每個值出現的次數就是返回的Series物件中的資料,在預設情況下會按照出現次數做降序排列,如下所示
#value_counts:統計重複項
ser3 = pandas.Series(data=['apple', 'banana', 'pitaya', 'apple', 'pitaya', 'durian'])
print(ser3.value_counts())
'''
apple 2
pitaya 2
banana 1
durian 1
Name: count, dtype: int64
'''
#nunique(): 統計不重複值、不重複值數量
print(ser3.nunique()) #4
#對於ser3,我們還可以用mode()方法來找出資料的眾數,由於眾數可能不唯一,所以mode()方法的返回值仍然是一個Series物件。
print(ser3.mode())
'''
0 apple
1 pitaya
dtype: object
'''
print('----------------------------------------------')
#處理資料
#Series物件的isna()和isnull()方法可以用於空值的判斷,notna()和notnull()方法可以用於非空值的判斷,程式碼如下所示。
ser4 = pandas.Series(data=[10, 20, numpy.nan, 30, numpy.nan])
print(ser4.isna())
'''
0 False
1 False
2 True
3 False
4 True
dtype: bool
'''
#說明:np.nan是一個IEEE 754標準的浮點小數,專門用來表示“不是一個數”
# 在上面的程式碼中我們用它來代表空值;當然,也可以用 Python 中的None來表示空值,在 pandas 中None也會被處理為np.nan
#判斷非空值
print(ser4.notna())
'''
0 True
1 True
2 False
3 True
4 False
dtype: bool
'''
print('----------------------------------------------')
#Series物件的dropna()和fillna()方法分別用來刪除空值和填充空值,具體的用法如下所示。
#刪除空值
print(ser4.dropna())
'''
0 10.0
1 20.0
3 30.0
dtype: float64
'''
#填充空值
print(ser4.fillna(value=40)) #填充值為40
'''
0 10.0
1 20.0
2 40.0
3 30.0
4 40.0
dtype: float64
'''
#需要提醒大家注意的是,dropna()和fillna()方法都有一個名為inplace的引數,
# 它的預設值是False,表示刪除空值或填充空值不會修改原來的Series物件,而是返回一個新的Series物件。
# 如果將inplace引數的值修改為True,那麼刪除或填充空值會就地操作,直接修改原來的Series物件,此時方法的返回值是None。
# 後面我們會接觸到的很多方法,包括DataFrame物件的很多方法都會有這個引數,它們的意義跟這裡是一樣的。
print('----------------------------------------------')
#Series物件的mask()和where()方法可以將滿足或不滿足條件的值進行替換,如下所示。
#和where()方法
ser5 = pandas.Series(range(5))
print(ser5.where(ser5 > 0))
print(ser5.where(ser5 > 1, 10))
#mask()方法
print(ser5.mask(ser5 > 1, 10))
print('----------------------------------------------')
#Series物件的duplicated()方法可以幫助我們找出重複的資料,而drop_duplicates()方法可以幫我們刪除重複資料。
# print(ser3)
print(ser3.duplicated()) #找出重複資料
print(ser3.drop_duplicates()) #刪除重複資料
print('----------------------------------------------')
#Series物件的apply()和map()方法非常重要,它們可以透過字典或者指定的函式來處理資料,把資料對映或轉換成我們想要的樣子。
# 這兩個方法在資料準備階段非常重要,我們先來試一試這個名為map的方法。
ser6 = pandas.Series(['cat', 'dog', numpy.nan, 'rabbit'])
# print(ser6)
# map()方法
#說明:透過字典給出的對映規則對資料進行處理。
# map()方法返回一個新的Series物件,而不是修改原來的Series物件。
print(ser6.map({'cat': 'kitten', 'dog': 'puppy'}))
'''
0 I am a cat
1 I am a dog
2 NaN
3 I am a rabbit
dtype: object
'''
#說明:將指定字串的format方法作用到資料系列的資料上,忽略掉所有的空值。
print(ser6.map('I am a {}'.format, na_action='ignore'))
'''
0 I am a cat
1 I am a dog
2 I am a numpy.nan
3 I am a rabbit
dtype: object
'''
print('----------------------------------------------')
#apply()
ser7 = pandas.Series([20, 21, 12], index=['London', 'New York', 'Helsinki'])
# print(ser7)
#說明:將求平方的函式作用到資料系列的資料上,也可以將引數np.square替換為lambda x: x ** 2。
print(ser7.apply(numpy.square))
'''
London 400
New York 441
Helsinki 144
dtype: int64
'''
#注意:apply方法中的lambda函式有兩個引數,第一個引數是資料系列中的資料,而第二個引數需要我們傳入,
# 所以我們給apply方法增加了args引數,用於給lambda函式的第二個引數傳值。
print(ser7.apply(lambda x, value: x - value, args=(5, )))
'''
London 15
New York 16
Helsinki 7
dtype: int64
'''
print('----------------------------------------------')
#取頭部值和排序
#Series物件的sort_index()和sort_values()方法可以用於對索引和資料的排序,排序方法有一個名為ascending的布林型別引數,
# 該引數用於控制排序的結果是升序還是降序;而名為kind的引數則用來控制排序使用的演算法,
# 預設使用了quicksort,也可以選擇mergesort或heapsort;
# 如果存在空值,那麼可以用na_position引數空值放在最前還是最後,預設是last,程式碼如下所示
ser8 = pandas.Series(
data=[35, 96, 12, 57, 25, 89],
index=['grape', 'banana', 'pitaya', 'apple', 'peach', 'orange']
)
print(ser8.sort_values()) #按值從小到大排序
'''
pitaya 12
peach 25
grape 35
apple 57
orange 89
banana 96
dtype: int64
'''
print(ser8.sort_index(ascending=False)) ## 按索引從大到小排序 ascending: True 升序,False 降序
print('----------------------------------------------')
#如果要從Series物件中找出元素中最大或最小的“Top-N”,我們不需要對所有的值進行排序的,
# 可以使用nlargest()和nsmallest()方法來完成
print(ser8.nlargest(3)) #找出3個最大值
'''
banana 96
orange 89
apple 57
dtype: int64
'''
#找出2個最小的值
print(ser8.nsmallest(2))
'''
pitaya 12
peach 25
dtype: int64
'''
繪製圖表
Series物件有一個名為plot的方法可以用來生成圖表,如果選擇生成折線圖、餅圖、柱狀圖等,預設會使用Series物件的索引作為橫座標,使用Series物件的資料作為縱座標
# -*- coding: utf-8 -*-
#繪製圖表""
import numpy
import pandas
import matplotlib.pyplot as plt
#建立Series物件
ser9 = pandas.Series({'Q1': 400, 'Q2': 520, 'Q3': 600, 'Q4': 800})
#透過plot方法的kind指定圖表型別位柱狀圖
ser9.plot(kind='bar')
#定製縱軸的取值範圍
plt.ylim(0, 1000)
#定製橫軸刻度(旋轉到0度)
plt.xticks(rotation=0)
#為柱子新增資料標籤
#ser9.size獲取柱子的個數
print(range(ser9.size)) #range(0, 4)
for i in range(ser9.size):
#獲取柱子的位置和長度
#plt.text(x, y, text, ha='center')
plt.text(i, ser9[i] + 5, ser9[i], ha='center')
print(i, ser9[i] + 5, ser9[i])
#顯示
plt.show()
繪製餅圖
#繪製餅圖
import numpy
import pandas
import matplotlib.pyplot as plt
#建立Series物件
ser9 = pandas.Series({'Q1': 400, 'Q2': 520, 'Q3': 600, 'Q4': 800})
# plot方法的kind引數指定了圖表型別為餅圖
# autopct會自動計算並顯示百分比
# pctdistance用來控制百分比到圓心的距離
ser9.plot(kind='pie', autopct='%1.1f%%', pctdistance=0.65)
#顯示
plt.show()