Jupyter 快捷鍵(命令模式下按h即可查看所有的快捷鍵)
Ctrl + Enter 運行代碼
'''
命令和編輯兩種鍵盤輸入模式。
'''
#命令模式是將鍵盤和筆記本層面的命令綁定起來,並且由帶有藍色左邊距的灰色單元邊框表示。
#編輯模式則讓你可以在活動單元中輸入文本(或代碼),用綠色單元邊框表示。
Esc和Enter用於切換命令模式和編輯模式
###############
####命令模式####
###############
a.會在活躍單元之上插入一個新的單元。
b.會在活躍單元之下插入一個新單元
dd.可以刪除一個單元
y.將當前活躍單元變成一個代碼單元
shift + 上/下箭頭.可以選擇多個單元
shift + M.多選模式下可以合並選擇的代碼塊
F.會彈出‘查找和替換’菜單
###############
####編輯模式####
###############
ctrl + home.到達單元起始位置。
ctrl + s.保存進度。
ctrl + enter.運行單元塊。
alt + enter.先運行單元塊,然后在下面添加一個新單元。
ctrl + shift + f.打開命令面板。
numpy
python的zip() 函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。
簡介:
Numpy是高性能科學計算和數據分析的基礎包。它也是pandas等其他數據分析的工具的基礎,基本所有數據分析的包都用過它。NumPy為Python帶來了真正的多維數組功能,並且提供了豐富的函數庫處理這些數組。
ndarray -多維數組對象
#生成對象
import numpy as np
li = [1, 2, 3]
np.array(li)
##注意(和python中列表的區別)
'''
數組對象內的元素類型必須相同
數組大小不可修改
'''
#常用屬性
T.轉置
dtype.數組元素的數據類型
size.數組元素的個數
ndim.數組的維數
shape.數組的維度大小(以元組形式)
#數組類型
布爾,整型,無符號整型,浮點型,復數型。
可以用astype()方法修改數組的數據類型
#######內置方法
1、arange():
np.arange(1.2,10,0.4)
執行結果:
array([1.2, 1.6, 2. , 2.4, 2.8, 3.2, 3.6, 4. , 4.4, 4.8, 5.2, 5.6, 6. ,
6.4, 6.8, 7.2, 7.6, 8. , 8.4, 8.8, 9.2, 9.6])
# 在進行數據分析的時候通常我們遇到小數的機會遠遠大於遇到整數的機會,這個方法與Python內置的range的使用方法一樣
-----------------------------------------------------------------
2、linspace()
np.linspace(1,10,20)
執行結果:
array([ 1. , 1.47368421, 1.94736842, 2.42105263, 2.89473684,
3.36842105, 3.84210526, 4.31578947, 4.78947368, 5.26315789,
5.73684211, 6.21052632, 6.68421053, 7.15789474, 7.63157895,
8.10526316, 8.57894737, 9.05263158, 9.52631579, 10. ])
# 這個方法與arange有一些區別,arange是顧頭不顧尾,而這個方法是顧頭又顧尾,在1到10之間生成的二十個數每個數字之間的距離相等的,前后兩個數做減法肯定相等
----------------------------------------------------------------
3、zeros()
np.zeros((3,4))
執行結果:
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
# 會用0生成三行四列的一個多維數組
---------------------------------------------------------------------
4、ones()
np.ones((3,4))
執行結果:
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
# 會用1生成三行四列的一個多維數組
------------------------------------------------------------------------
5、empty()
np.empty(10)
執行結果:
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
# 這個方法只申請內存,不給它賦值
-----------------------------------------------------------------------
6、eye()
np.eye(5)
執行結果:
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
#######切片和索引
1.數組和標量(數字)之間的運算
li1 = [
[1,2,3],
[4,5,6]
]
a = np.array(li1)
a * 2
運行結果:
array([[ 2, 4, 6],
[ 8, 10, 12]])
2.同樣大小數組之間的運算
# l2數組
l2 = [
[1,2,3],
[4,5,6]
]
a = np.array(l2)
# l3數組
l3 = [
[7,8,9],
[10,11,12]
]
b = np.array(l3)
a + b # 計算
執行結果:
array([[ 8, 10, 12],
[14, 16, 18]])
3.索引
# 將一維數組變成二維數組
arr = np.arange(30).reshape(5,6) # 后面的參數6可以改為-1,相當於占位符,系統可以自動幫忙算幾列
arr
# 將二維變一維
arr.reshape(30)
# 索引使用方法
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29]])
現在有這樣一組數據,需求:找到20
列表寫法:arr[3][2]
數組寫法:arr[3,2] # 中間通過逗號隔開就可以了
##布爾型索引
現在有這樣一個需求:給一個數組,選出數組種所有大於5的數。
'''
li = [random.randint(1,10) for _ in range(30)]
a = np.array(li)
a[a>5]
執行結果:
array([10, 7, 7, 9, 7, 9, 10, 9, 6, 8, 7, 6])
----------------------------------------------
原理:
a>5會對a中的每一個元素進行判斷,返回一個布爾數組
a > 5的運行結果:
array([False, True, False, True, True, False, True, False, False,
False, False, False, False, False, False, True, False, True,
False, False, True, True, True, True, True, False, False,
False, False, True])
----------------------------------------------
布爾型索引:將同樣大小的布爾數組傳進索引,會返回一個有True對應位置的元素的數組
'''
4.切片
arr數組
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29]])
arr[1:4,1:4] # 切片方式
執行結果:
array([[ 7, 8, 9],
[13, 14, 15],
[19, 20, 21]])
##切片不會拷貝,直接使用的原視圖,如果硬要拷貝,需要在后面加.copy()方法
'''
arr = np.arange(10) #隨機生成一個一維數組
arr
b = arr[5:] # 切片 5以后的
b
b[0] = 10 #修改切片之后的數據
arr
運行結果是,
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
'''
## 最后會發現修改切片后的數據影響的依然是原數據,是同一塊內存地址,因此屬於可變對象。
常見函數
## 一元函數
'''
函數 功能
abs、fabs 分別是計算整數和浮點數的絕對值
sqrt 計算各元素的平方根
square 計算各元素的平方
exp 計算各元素的指數e**x
log 計算自然對數
sign 計算各元素的正負號
ceil 計算各元素的ceiling值
floor 計算各元素floor值,即小於等於該值的最大整數
rint 計算各元素的值四舍五入到最接近的整數,保留dtype
modf 將數組的小數部分和整數部分以兩個獨立數組的形式返回,與Python的divmod方法類似
isnan 計算各元素的正負號
isinf 表示那些元素是無窮的布爾型數組
cos,sin,tan 普通型和雙曲型三角函數
'''
## 二元函數
'''
函數 功能
add 將數組中對應的元素相加
subtract 從第一個數組中減去第二個數組中的元素
multiply 數組元素相乘
divide、floor_divide 除法或向下圓整除法(舍棄余數)
power 對第一個數組中的元素A,根據第二個數組中的相應元素B計算A**B
maximum,fmax 計算最大值,fmax忽略NAN
miximum,fmix 計算最小值,fmin忽略NAN
mod 元素的求模計算(除法的余數)
'''
補充內容:浮點數特殊值
浮點數:float
浮點數有兩個特殊值:
1、nan(Not a Number):不等於任何浮點數(nan != nan)
---------------------------------------------
2、inf(infinity):比任何浮點數都大
---------------------------------------------
Numpy中創建特殊值:np.nan、np.inf
數據分析中,nan常被用作表示數據缺失值
## 數學統計方法
函數 功能
sum 求和
cumsum 求前綴和
mean 求平均數
std 求標准差
var 求方差
min 求最小值
max 求最大值
argmin 求最小值索引
argmax 求最大值索引
## 隨機數
隨機數生成函數在np.random的子包當中
函數 功能
rand 給定形狀產生隨機數組(0到1之間的數)
randint 給定形狀產生隨機整數
chocie 給定形狀產生隨機選擇
shuffle 與random.shuffle相同
uniform 給定形狀產生隨機數組
Pandas
簡介
pandas是一個強大的Python數據分析的工具包,它是基於Numpy構建的,正因pandas的出現,讓Python語言也成為使用最廣泛而且強大的數據分析環境之一。
主要功能
- 具備對其功能的數據結構DataFrame,Series
- 集成時間序列功能
- 提供豐富的數學運算和操作
- 靈活處理缺失數據
Series
Series是一種類似於一維數組的對象,由一組數據和一組與之相關的數據標簽(索引)組成
1、創建方法
第一種:
pd.Series([4,5,6,7,8])
執行結果:
0 4
1 5
2 6
3 7
4 8
dtype: int64
# 將數組索引以及數組的值打印出來,索引在左,值在右,由於沒有為數據指定索引,於是會自動創建一個0到N-1(N為數據的長度)的整數型索引,取值的時候可以通過索引取值,跟之前學過的數組和列表一樣
-----------------------------------------------
第二種:
c = pd.Series([4,5,6,7,8],index=['a','b','c','d','e'])
執行結果:
a 4
b 5
c 6
d 7
e 8
dtype: int64
# 自定義索引,index是一個索引列表,里面包含的是字符串,依然可以通過默認索引取值。
c[0] = c['a'] = 4
-----------------------------------------------
第三種:
pd.Series({"a":1,"b":2})
執行結果:
a 1
b 2
dtype: int64
# 指定索引
-----------------------------------------------
第四種:
pd.Series(0,index=['a','b','c'])
執行結果:
a 0
b 0
c 0
dtype: int64
# 創建一個值都是0的數組
-----------------------------------------------
對於Series,其實我們可以認為它是一個長度固定且有序的字典,因為它的索引和數據是按位置進行匹配的,像我們會使用字典的上下文,就肯定也會使用Series
2、缺失數據
- dropna() # 過濾掉值為NaN的行
- fill() # 填充缺失數據
- isnull() # 返回布爾數組,缺失值對應為True
- notnull() # 返回布爾數組,缺失值對應為False
# 第一步,創建一個字典,通過Series方式創建一個Series對象
st = {"sean":18,"yang":19,"bella":20,"cloud":21}
obj = pd.Series(st)
obj
運行結果:
sean 18
yang 19
bella 20
cloud 21
dtype: int64
------------------------------------------
# 第二步
a = {'sean','yang','cloud','rocky'} # 定義一個索引變量
------------------------------------------
#第三步
obj1 = pd.Series(st,index=a)
obj1 # 將第二步定義的a變量作為索引傳入
# 運行結果:
rocky NaN
cloud 21.0
sean 18.0
yang 19.0
dtype: float64
# 因為rocky沒有出現在st的鍵中,所以返回的是缺失值
通過上面的代碼演示,對於缺失值已經有了一個簡單的了解,接下來就來看看如何判斷缺失值
1、
obj1.isnull() # 是缺失值返回Ture
運行結果:
rocky True
cloud False
sean False
yang False
dtype: bool
2、
obj1.notnull() # 不是缺失值返回Ture
運行結果:
rocky False
cloud True
sean True
yang True
dtype: bool
3、過濾缺失值 # 布爾型索引
obj1[obj1.notnull()]
運行結果:
cloud 21.0
yang 19.0
sean 18.0
dtype: float64
3、Series特性
- 從ndarray創建Series:Series(arr)
- 與標量(數字):sr * 2
- 兩個Series運算
- 通用函數:np.ads(sr)
- 布爾值過濾:sr[sr>0]
- 統計函數:mean()、sum()、cumsum()
支持字典的特性:
- 從字典創建Series:Series(dic),
- In運算:'a'in sr、for x in sr
- 鍵索引:sr['a'],sr[['a','b','d']]
- 鍵切片:sr['a':'c']
- 其他函數:get('a',default=0)等
4、整數索引
pandas當中的整數索引對象可能會讓初次接觸它的人很懵逼,接下來通過代碼演示:
sr = pd.Series(np.arange(10))
sr1 = sr[3:].copy()
sr1
運行結果:
3 3
4 4
5 5
6 6
7 7
8 8
9 9
dtype: int32
# 到這里會發現很正常,一點問題都沒有,可是當使用整數索引取值的時候就會出現問題了。因為在pandas當中使用整數索引取值是優先以標簽解釋的,而不是下標
sr1[1]
解決方法:
- loc屬性 # 以標簽解釋
- iloc屬性 # 以下標解釋
sr1.iloc[1] # 以下標解釋
sr1.loc[3] # 以標簽解釋
5、Series數據對齊
pandas在運算時,會按索引進行對齊然后計算。如果存在不同的索引,則結果的索引是兩個操作數索引的並集。
sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a',])
sr1 + sr2
運行結果:
a 33
c 32
d 45
dtype: int64
# 可以通過這種索引對齊直接將兩個Series對象進行運算
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1 + sr3
運行結果:
a 33.0
b NaN
c 32.0
d 45.0
dtype: float64
# sr1 和 sr3的索引不一致,所以最終的運行會發現b索引對應的值無法運算,就返回了NaN,一個缺失值
將兩個Series對象相加時將缺失值設為0:
sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1.add(sr3,fill_value=0)
運行結果:
a 33.0
b 14.0
c 32.0
d 45.0
dtype: float64
# 將缺失值設為0,所以最后算出來b索引對應的結果為14
靈活的算術方法:add,sub,div,mul
DataFrame
DataFrame是一個表格型的數據結構,相當於是一個二維數組,含有一組有序的列。他可以被看做是由Series組成的字典,並且共用一個索引。
創建方式:
創建一個DataFrame數組可以有多種方式,其中最為常用的方式就是利用包含等長度列表或Numpy數組的字典來形成DataFrame:
第一種:
pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
# 產生的DataFrame會自動為Series分配所索引,並且列會按照排序的順序排列
運行結果:
one two
0 1 4
1 2 3
2 3 2
3 4 1
> 指定列
可以通過columns參數指定順序排列
data = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
pd.DataFrame(data,columns=['one','two'])
# 打印結果會按照columns參數指定順序
第二種:
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])})
運行結果:
one two
a 1 2
b 2 1
c 3 3
以上創建方法簡單了解就可以,因為在實際應用當中更多是讀數據,不需要自己手動創建
查看數據
常用屬性和方法:
- index 獲取行索引
- columns 獲取列索引
- T 轉置
- columns 獲取列索引
- values 獲取值索引
- describe 獲取快速統計
one two
a 1 2
b 2 1
c 3 3
# 這樣一個數組df
-----------------------------------------------------------------------------
df.index
運行結果:
Index(['a', 'b', 'c'], dtype='object')
----------------------------------------------------------------------------
df.columns
運行結果:
Index(['one', 'two'], dtype='object')
--------------------------------------------------------------------------
df.T
運行結果:
a b c
one 1 2 3
two 2 1 3
-------------------------------------------------------------------------
df.values
運行結果:
array([[1, 2],
[2, 1],
[3, 3]], dtype=int64)
------------------------------------------------------------------------
df.describe()
運行結果:
one two
count 3.0 3.0
mean 2.0 2.0
std 1.0 1.0
min 1.0 1.0
25% 1.5 1.5
50% 2.0 2.0
75% 2.5 2.5
max 3.0 3.0
## 注釋:
對於數值數據,結果的索引將包括計數,平均值,標准差,最小值,最大值以及較低的百分位數和50。默認情況下,較低的百分位數為25,較高的百分位數為75.50百分位數與中位數相同。
索引和切片
- DataFrame有行索引和列索引。
- DataFrame同樣可以通過標簽和位置兩種方法進行索引和切片。
DataFrame使用索引切片:
- 方法1:兩個中括號,先取列再取行。 df['A'][0]
- 方法2(推薦):使用loc/iloc屬性,一個中括號,逗號隔開,先取行再取列。
- loc屬性:解釋為標簽
- iloc屬性:解釋為下標
- 向DataFrame對象中寫入值時只使用方法2
- 行/列索引部分可以是常規索引、切片、布爾值索引、花式索引任意搭配。(注意:兩部分都是花式索引時結果可能與預料的不同)
時間對象處理
時間序列類型
- 時間戳:特定時刻
- 固定時期:如2019年1月
- 時間間隔:起始時間-結束時間
Python庫:datatime
- date、time、datetime、timedelta
- dt.strftime()
- strptime()
靈活處理時間對象:dateutil包
- dateutil.parser.parse()
import dateutil
dateutil.parser.parse("2019 Jan 2nd") # 這中間的時間格式一定要是英文格式
運行結果:
datetime.datetime(2019, 1, 2, 0, 0)
成組處理時間對象:pandas
- pd.to_datetime(['2018-01-01', '2019-02-02'])
pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])
運行結果:
DatetimeIndex(['2018-03-01', '2019-02-03', '2019-08-12'], dtype='datetime64[ns]', freq=None) # 產生一個DatetimeIndex對象
# 轉換時間索引
ind = pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])
sr = pd.Series([1,2,3],index=ind)
sr
運行結果:
2018-03-01 1
2019-02-03 2
2019-08-12 3
dtype: int64
通過以上方式就可以將索引轉換為時間
補充:
pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019']).to_pydatetime()
運行結果:
array([datetime.datetime(2018, 3, 1, 0, 0),
datetime.datetime(2019, 2, 3, 0, 0),
datetime.datetime(2019, 8, 12, 0, 0)], dtype=object)
# 通過to_pydatetime()方法將其轉換為array數組
產生時間對象數組:data_range
- start 開始時間
- end 結束時間
- periods 時間長度
- freq 時間頻率,默認為'D',可選H(our),W(eek),B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year),…
pd.date_range("2019-1-1","2019-2-2")
運行結果:
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
'2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
'2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12',
'2019-01-13', '2019-01-14', '2019-01-15', '2019-01-16',
'2019-01-17', '2019-01-18', '2019-01-19', '2019-01-20',
'2019-01-21', '2019-01-22', '2019-01-23', '2019-01-24',
'2019-01-25', '2019-01-26', '2019-01-27', '2019-01-28',
'2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01',
'2019-02-02'],
dtype='datetime64[ns]', freq='D')
時間序列
時間序列就是以時間對象為索引的Series或DataFrame。datetime對象作為索引時是存儲在DatetimeIndex對象中的。
# 轉換時間索引
dt = pd.date_range("2019-01-01","2019-02-02")
a = pd.DataFrame({"num":pd.Series(random.randint(-100,100) for _ in range(30)),"date":dt})
# 先生成一個帶有時間數據的DataFrame數組
a.index = pd.to_datetime(a["date"])
# 再通過index修改索引
特殊功能:
- 傳入“年”或“年月”作為切片方式
- 傳入日期范圍作為切片方式
- 豐富的函數支持:resample(), strftime(), ……
- 批量轉換為datetime對象:to_pydatetime()
a.resample("3D").mean() # 計算每三天的均值
a.resample("3D").sum() # 計算每三天的和
...
數據分組和聚合
在數據分析當中,我們有時需要將數據拆分,然后在每一個特定的組里進行運算,這些操作通常也是數據分析工作中的重要環節。
本章學習內容:
- 分組(GroupBY機制)
- 聚合(組內應用某個函數)
- apply
- 透視表和交叉表
5.1、分組(GroupBY機制)
pandas對象(無論Series、DataFrame還是其他的什么)當中的數據會根據提供的一個或者多個鍵被拆分為多組,拆分操作實在對象的特定軸上執行的。就比如DataFrame可以在他的行上或者列上進行分組,然后將一個函數應用到各個分組上並產生一個新的值。最后將所有的執行結果合並到最終的結果對象中。
分組鍵的形式:
- 列表或者數組,長度與待分組的軸一樣
- 表示DataFrame某個列名的值。
- 字典或Series,給出待分組軸上的值與分組名之間的對應關系
- 函數,用於處理軸索引或者索引中的各個標簽嗎
后三種只是快捷方式,最終仍然是為了產生一組用於拆分對象的值。
首先,通過一個很簡單的DataFrame數組嘗試一下:
df = pd.DataFrame({'key1':['x','x','y','y','x',
'key2':['one','two','one',',two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
df
運行結果:
key1 key2 data1 data2
0 x one 0.951762 1.632336
1 x two -0.369843 0.602261
2 y one 1.512005 1.331759
3 y ,two 1.383214 1.025692
4 x one -0.475737 -1.182826
訪問data1,並根據key1調用groupby:
f1 = df['data1'].groupby(df['key1'])
f1
運行結果:
<pandas.core.groupby.groupby.SeriesGroupBy object at 0x00000275906596D8>
上述運行是沒有進行任何計算的,但是我們想要的中間數據已經拿到了,接下來,就可以調用groupby進行任何計算
f1.mean() # 調用mean函數求出平均值
運行結果:
key1
x 0.106183
y 2.895220
Name: data1, dtype: float64
以上數據經過分組鍵(一個Series數組)進行了聚合,產生了一個新的Series,索引就是key1
列中的唯一值。這些索引的名稱就為key1
。接下來就嘗試一次將多個數組的列表傳進來
f2 = df['data1'].groupby([df['key1'],df['key2']])
f2.mean()
運行結果:
key1 key2
x one 0.083878
two 0.872437
y one -0.665888
two -0.144310
Name: data1, dtype: float64
傳入多個數據之后會發現,得到的數據具有一個層次化的索引,key1對應的x\y;key2對應的one\two.
f2.mean().unstack()
運行結果:
key2 one two
key1
x 0.083878 0.872437
y -0.665888 -0.144310
# 通過unstack方法就可以讓索引不堆疊在一起了
補充:
- 1、分組鍵可以是任意長度的數組
- 2、分組時,對於不是數組數據的列會從結果中排除,例如key1、key2這樣的列
- 3、GroupBy的size方法,返回一個含有分組大小的Series
# 以上面的f2測試
f2.size()
運行結果:
key1 key2
x one 2
two 1
y one 1
two 1
Name: data1, dtype: int64
5.2、聚合(組內應用某個函數)
聚合是指任何能夠從數組產生標量值的數據轉換過程。剛才上面的操作會發現使用GroupBy並不會直接得到一個顯性的結果,而是一個中間數據,可以通過執行類似mean、count、min等計算得出結果,常見的還有一些:
函數名 | 描述 | |
---|---|---|
sum | 非NA值的和 | |
median | 非NA值的算術中位數 | |
std、var | 無偏(分母為n-1)標准差和方差 | |
prod | 非NA值的積 | |
first、last | 第一個和最后一個非NA值 |
自定義聚合函數
不僅可以使用這些常用的聚合運算,還可以自己自定義。
# 使用自定義的聚合函數,需要將其傳入aggregate或者agg方法當中
def peak_to_peak(arr):
return arr.max() - arr.min()
f1.aggregate(peak_to_peak)
運行結果:
key1
x 3.378482
y 1.951752
Name: data1, dtype: float64
多函數聚合:
f1.agg(['mean','std'])
運行結果:
mean std
key1
x -0.856065 0.554386
y -0.412916 0.214939
最終得到的列就會以相應的函數命名生成一個DataFrame數組
5.3、apply
GroupBy當中自由度最高的方法就是apply,它會將待處理的對象拆分為多個片段,然后各個片段分別調用傳入的函數,最后將它們組合到一起。
df.apply(
['func', 'axis=0', 'broadcast=None', 'raw=False', 'reduce=None', 'result_type=None', 'args=()', '**kwds']
func:傳入一個自定義函數
axis:函數傳入參數當axis=1就會把一行數據作為Series的數據
# 分析NBA總冠軍
import pandas as pd
url = "https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin" #nba總冠軍
nba_champions = pd.read_html(url) #獲取數據
a1 = nba_champions[0] #取出歷史上的總冠軍名單
a1.columns = a1.loc[0] #使用第一行數據替換為默認的橫向索引
a1.drop(0, inplace=True) #將第一行數據刪除
a1.drop('比賽日期', axis=1, inplace=True)
# a1.head()
# a1.tail()
a1
a1.groupby('冠軍').groups #按冠軍分組,給索引
a1.groupby('冠軍').size().sort_values() #默認按冠軍次數升序
a1.groupby('冠軍').size().sort_values(ascending=False) #按冠軍次數降序
a1.groupby(['冠軍', 'FMVP']).size() # 按冠軍和FMVP進行分組
其他常用方法
pandas常用方法(適用Series和DataFrame)
- mean(axis=0,skipna=False)
- sum(axis=1)
- sort_index(axis, …, ascending) # 按行或列索引排序
- sort_values(by, axis, ascending) # 按值排序
- apply(func, axis=0) # 將自定義函數應用在各行或者各列上,func可返回標量或者Series
- applymap(func) # 將函數應用在DataFrame各個元素上
- map(func) # 將函數應用在Series各個元素上
Matplotlib(繪圖和可視化)
簡介
Matplotlib是一個強大的Python繪圖和數據可視化的工具包。數據可視化也是我們數據分析的最重要的工作之一,可以幫助我們完成很多操作,例如:找出異常值、必要的一些數據轉換等。完成數據分析的最終結果也許就是做一個可交互的數據可視化。
簡單繪制線形圖
plt.plot() # 繪圖函數
plt.show() # 顯示圖像
在jupyter notebook中不執行這條語句也是可以將圖形展示出來
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(10)
plt.plot(data)
plt.show() # 顯示圖像,在notebook中不執行這一句也可以
執行結果:
雖然seaborn這些庫和pandas的內置繪圖函數能夠處理許多普通的繪圖任務,如果需要自定義一些高級功能的話就必須要matplotlib API.
plot函數
plot函數:繪制折線圖
- 線型linestyle(-,-.,--,..)
- 點型marker(v,^,s,*,H,+,X,D,O,...)
- 顏色color(b,g,r,y,k,w,...)
plt.plot([0,3,9,15,30],linestyle = '-.',color = 'r',marker = 'o')
圖像標注
方法 | 描述 | |
---|---|---|
plt.title() | 設置圖像標題 | |
plt.xlabel() | 設置x軸名稱 | |
plt.ylabel() | 設置y軸名稱 | |
plt.xlim() | 設置x軸范圍 | |
plt.ylim() | 設置y軸范圍 | |
plt.xticks() | 設置x軸刻度 | |
plt.yticks() | 設置y軸刻度 | |
plt.legend() | 設置曲線圖例 |
plt.plot([0,3,9,15,30],linestyle = '-.',color = 'r',marker = 'o',label="A")
plt.plot([1,3,16,23,30],[30,23,13,25,30],label='B')
#第一個數組是index,第二個數組是values
#設置字體(在同一個文件夾下面)
#font1 = matplotlib.font_manager.FontProperties(fname='msyh.ttc')
plt.title("Title", fontproperties=font1, fontsize=100) # 標題,設置字體樣式和字體大小
plt.xlabel('X') # x軸名稱
plt.ylabel('Y') # y軸名稱
plt.xticks(np.arange(0,10,2)) # x軸刻度
plt.xlim(-0,2,10) # x軸范圍
plt.legend() # 曲線圖例
運行圖例:
繪制數學函數
使用Matplotlib模塊在一個窗口中繪制數學函數y=x, y=x**2,y=sinx的圖像,使用不同顏色的線加以區別,並使用圖例說明各個線代表什么函數。
x = np.arange(-100,100)
y1 = x
y2 = x ** 2
y3 = np.sin(x)
-----------------------
plt.plot(x,y1,label="y=x")
plt.plot(x,y2,label="y=x^2")
plt.plot(x,y3,label="y=sin(x)")
plt.ylim(-100,100)
plt.legend()
4、支持的圖類型
函數 | 說明 | |
---|---|---|
plt.plot(x,y,fmt) | 坐標系 | |
plt.boxplot(data,notch,position) | 箱型圖 | |
plt.bar(left,height,width,bottom) | 柱狀圖 | |
plt.barh(width,bottom,left,height) | 橫向柱狀圖 | |
plt.polar(theta,r) | 極坐標系 | |
plt.pie(data,explode) | 餅圖 | |
plt.psd(x,NFFT=256,pad_to,Fs) | 功率譜密度圖 | |
plt.specgram(x,NFFT=256,pad_to,F) | 譜圖 | |
plt.cohere(x,y,NFFT=256,Fs) | X-Y相關性函數 | |
plt.scatter(x,y) | 散點圖 | |
plt.step(x,y,where) | 步階圖 | |
plt.hist(x,bins,normed) | 直方圖 |
# 柱狀圖
data = [12,34,23,54]
labels = ['Jan','Fed','Mar','Apr']
plt.xticks([0,1,2,3],labels) # 設置x軸刻度
plt.bar([0,1,2,3],data)
# 橫向柱狀圖
data = [12,34,23,54]
labels = ['Jan','Fed','Mar','Apr']
plt.yticks([0,1,2,3],labels)
plt.barh([0,1,2,3],data)
# DataFrame數組圖
df = pd.DataFrame({
'Jan':pd.Series([1,2,3],index=['a','b','c']),
'Fed':pd.Series([4,5,6],index=['b','a','c']),
'Mar':pd.Series([7,8,9],index=['b','a','c']),
'Apr':pd.Series([2,4,6],index=['b','a','c'])
})
df.plot.bar() # 水平柱狀圖,將每一行中的值分組到並排的柱子中的一組
df.plot.barh(stacked=True,alpha=0.5) # 橫向柱狀圖,將每一行的值堆積到一起,#前者控制是否堆積在同一行,后者控制透明度
# 餅圖
plt.pie([10,20,30,40],labels=list('abcd'),autopct="%.2f%%",explode=[0.1,0,0,0]) # 餅圖,第一個字母(即‘a’)突出0.1
plt.axis("equal")#控制是個正圓,否則是一個橢圓
plt.show()
# 散點圖
import random
x = np.random.randn(100)
y = np.random.randn(100)
plt.scatter(x,y)
5、保存圖表到文件
plt.savafig('文件名.拓展名')
文件類型是通過文件擴展名推斷出來的。因此,如果你使用的是.pdf,就會得到一個PDF文件。
plt.savefig('123.pdf')
savefig並非一定要寫入磁盤,也可以寫入任何文件型的對象,比如BytesIO:
from io import BytesIO
buffer = BytesIO()
plt.savefig(buffer)
plot_data = buffer.getvalue()
參數 | 說明 | |
---|---|---|
fname | 含有文件路徑的字符串或者Python的文件型對象。 | |
dpi | 圖像分辨率,默認為100 | |
format | 顯示設置文件格式("png","jpg","pdf","svg","ps",...) | |
facecolor、edgecolor | 背景色,默認為"W"(白色) | |
bbox_inches | 圖表需要保存的部分。設置為”tight“,則嘗試剪除圖表周圍空白部分 |