系統(tǒng)性的學(xué)會(huì) Pandas, 看這一篇就夠了!
1、Pandas數(shù)據(jù)結(jié)構(gòu)作者:Ma Sizhou
https://blog.csdn.net/weixin_45901519/article/details/112980822

- 2008年WesMcKinney開(kāi)發(fā)出的庫(kù)
- 專門用于數(shù)據(jù)挖掘的開(kāi)源python庫(kù)
- 以Numpy為基礎(chǔ),借力Numpy模塊在計(jì)算方面性能高的優(yōu)勢(shì)
- 基于matplotlib,能夠簡(jiǎn)便的畫圖
- 獨(dú)特的數(shù)據(jù)結(jié)構(gòu)
1.1 為什么使用Pandas
Numpy已經(jīng)能夠幫助我們處理數(shù)據(jù),能夠結(jié)合matplotlib解決部分?jǐn)?shù)據(jù)展示等問(wèn)題,那么pandas學(xué)習(xí)的目的在什么地方呢?
(1)增強(qiáng)圖表可讀性
在numpy當(dāng)中創(chuàng)建學(xué)生成績(jī)表樣式:
返回結(jié)果:
array([[92,?55,?78,?50,?50],
???????[71,?76,?50,?48,?96],
???????[45,?84,?78,?51,?68],
???????[81,?91,?56,?54,?76],
???????[86,?66,?77,?67,?95],
???????[46,?86,?56,?61,?99],
???????[46,?95,?44,?46,?56],
???????[80,?50,?45,?65,?57],
???????[41,?93,?90,?41,?97],
???????[65,?83,?57,?57,?40]])
如果數(shù)據(jù)展示為這樣,可讀性就會(huì)更友好:
- (2)便捷的數(shù)據(jù)處理能力

- (3)讀取文件方便
- (4)封裝了Matplotlib、Numpy的畫圖和計(jì)算
1.2 Pandas數(shù)據(jù)結(jié)構(gòu)
Pandas中一共有三種數(shù)據(jù)結(jié)構(gòu),分別為:Series、DataFrame和MultiIndex(老版本中叫Panel )。
其中Series是一維數(shù)據(jù)結(jié)構(gòu),DataFrame是二維的表格型數(shù)據(jù)結(jié)構(gòu),MultiIndex是三維的數(shù)據(jù)結(jié)構(gòu)。
1.2.1 Series
Series是一個(gè)類似于一維數(shù)組的數(shù)據(jù)結(jié)構(gòu),它能夠保存任何類型的數(shù)據(jù),比如整數(shù)、字符串、浮點(diǎn)數(shù)等,主要由一組數(shù)據(jù)和與之相關(guān)的索引兩部分構(gòu)成。
(1)Series的創(chuàng)建
#?導(dǎo)入pandas
import?pandas?as?pd
pd.Series(data=None,?index=None,?dtype=None)
- 參數(shù):
- data:傳入的數(shù)據(jù),可以是ndarray、list等
- index:索引,必須是唯一的,且與數(shù)據(jù)的長(zhǎng)度相等。如果沒(méi)有傳入索引參數(shù),則默認(rèn)會(huì)自動(dòng)創(chuàng)建一個(gè)從0-N的整數(shù)索引。
- dtype:數(shù)據(jù)的類型
通過(guò)已有數(shù)據(jù)創(chuàng)建:
- (1)指定內(nèi)容,默認(rèn)索引:
pd.Series(np.arange(10))
#?運(yùn)行結(jié)果
0????0
1????1
2????2
3????3
4????4
5????5
6????6
7????7
8????8
9????9
dtype:?int64
- (2)指定索引:
pd.Series([6.7,5.6,3,10,2],?index=[1,2,3,4,5])
#?運(yùn)行結(jié)果
1?????6.7
2?????5.6
3?????3.0
4????10.0
5?????2.0
dtype:?float64
- (3)通過(guò)字典數(shù)據(jù)創(chuàng)建
color_count?=?pd.Series({'red':100,?'blue':200,?'green':?500,?'yellow':1000})
color_count
#?運(yùn)行結(jié)果
blue???????200
green??????500
red????????100
yellow????1000
dtype:?int64
(2)Series的屬性
為了更方便地操作Series對(duì)象中的索引和數(shù)據(jù),Series中提供了兩個(gè)屬性index和values:
- index:
color_count?=?pd.Series({'red':100,?'blue':200,?'green':?500,?'yellow':1000})
color_count.index
#?結(jié)果
Index(['blue',?'green',?'red',?'yellow'],?dtype='object')
- values:
color_count.values
#?結(jié)果
array([?200,??500,??100,?1000])
也可以使用索引來(lái)獲取數(shù)據(jù):
color_count[2]
#?結(jié)果
100
1.2.2 DataFrame
DataFrame是一個(gè)類似于二維數(shù)組或表格(如excel)的對(duì)象,既有行索引,又有列索引:
- 行索引,表明不同行,橫向索引,叫index,0軸,axis=0
- 列索引,表名不同列,縱向索引,叫columns,1軸,axis=1

(1)DataFrame的創(chuàng)建
#?導(dǎo)入pandas
import?pandas?as?pd
pd.DataFrame(data=None,?index=None,?columns=None)
參數(shù):
- index:行標(biāo)簽。如果沒(méi)有傳入索引參數(shù),則默認(rèn)會(huì)自動(dòng)創(chuàng)建一個(gè)從0-N的整數(shù)索引。
- columns:列標(biāo)簽。如果沒(méi)有傳入索引參數(shù),則默認(rèn)會(huì)自動(dòng)創(chuàng)建一個(gè)從0-N的整數(shù)索引。
通過(guò)已有數(shù)據(jù)創(chuàng)建
舉例一:
pd.DataFrame(np.random.randn(2,3))
結(jié)果:
舉例二:創(chuàng)建學(xué)生成績(jī)表
使用np創(chuàng)建的數(shù)組顯示方式,比較兩者的區(qū)別。
#?生成10名同學(xué),5門功課的數(shù)據(jù)
score?=?np.random.randint(40,?100,?(10,?5))#均勻分布
#?結(jié)果
array([[92,?55,?78,?50,?50],
???????[71,?76,?50,?48,?96],
???????[45,?84,?78,?51,?68],
???????[81,?91,?56,?54,?76],
???????[86,?66,?77,?67,?95],
???????[46,?86,?56,?61,?99],
???????[46,?95,?44,?46,?56],
???????[80,?50,?45,?65,?57],
???????[41,?93,?90,?41,?97],
???????[65,?83,?57,?57,?40]])
但是這樣的數(shù)據(jù)形式很難看到存儲(chǔ)的是什么的樣的數(shù)據(jù),可讀性比較差!!
問(wèn)題:如何讓數(shù)據(jù)更有意義的顯示?
#?使用Pandas中的數(shù)據(jù)結(jié)構(gòu)
score_df?=?pd.DataFrame(score)
結(jié)果:
給分?jǐn)?shù)數(shù)據(jù)增加行列索引,顯示效果更佳:
- 增加行、列索引:
#?構(gòu)造行索引序列
subjects?=?["語(yǔ)文",?"數(shù)學(xué)",?"英語(yǔ)",?"政治",?"體育"]
#?構(gòu)造列索引序列
stu?=?['同學(xué)'?+?str(i)?for?i?in?range(score_df.shape[0])]
#?添加行索引
data?=?pd.DataFrame(score,?columns=subjects,?index=stu)
結(jié)果:

(2)DataFrame的屬性
- (1)shape
data.shape
#?結(jié)果
(10,?5)
- (2)index
DataFrame的行索引列表
data.index
#?結(jié)果
Index(['同學(xué)0',?'同學(xué)1',?'同學(xué)2',?'同學(xué)3',?'同學(xué)4',?'同學(xué)5',?'同學(xué)6',?'同學(xué)7',?'同學(xué)8',?'同學(xué)9'],?dtype='object')
- (3)columns
DataFrame的列索引列表
data.columns
#?結(jié)果
Index(['語(yǔ)文',?'數(shù)學(xué)',?'英語(yǔ)',?'政治',?'體育'],?dtype='object')
- (4)values
直接獲取其中array的值
array([[54,?82,?62,?81,?47],
???????[50,?58,?73,?72,?48],
???????[88,?89,?49,?99,?83],
???????[79,?81,?69,?45,?87],
???????[87,?64,?62,?74,?85],
???????[68,?56,?58,?77,?53],
???????[77,?49,?82,?48,?82],
???????[96,?49,?67,?94,?71],
???????[98,?77,?44,?99,?41],
???????[71,?52,?74,?90,?44]])
- (5)T
轉(zhuǎn)置
data.T
結(jié)果:
- (6)head(5):顯示前5行內(nèi)容
如果不補(bǔ)充參數(shù),默認(rèn)5行。填入?yún)?shù)N則顯示前N行
data.head(5)
結(jié)果:
- (7)tail(5):顯示后5行內(nèi)容
如果不補(bǔ)充參數(shù),默認(rèn)5行。填入?yún)?shù)N則顯示后N行
data.tail(5)
結(jié)果:

(3)DatatFrame索引的設(shè)置
現(xiàn)在要將下圖的行索引改變,變成下下圖所示樣子,怎么做呢?

- (1)修改行列索引值
stu?=?["學(xué)同學(xué)_"?+?str(i)?for?i?in?range(score_df.shape[0])]
#?必須整體全部修改
data.index?=?stu
注意:以下修改方式是錯(cuò)誤的,說(shuō)明不能單獨(dú)修改
#?錯(cuò)誤修改方式,不能單個(gè)修改
data.index[3]?=?'學(xué)生_3'
(2)重設(shè)索引
- 設(shè)置新的下標(biāo)索引
- drop:默認(rèn)為False,不刪除原來(lái)索引,如果為True,刪除原來(lái)的索引值
- reset_index(drop=False)
#?重置索引,drop=False
data.reset_index()
結(jié)果:
#?重置索引,drop=True
data.reset_index()
結(jié)果:
- (3)以某列值設(shè)置為新的索引
- set_index(keys, drop=True)
- keys : 列索引名成或者列索引名稱的列表
- drop : boolean, default True.當(dāng)做新的索引,刪除原來(lái)的列
設(shè)置新索引案例:
1、創(chuàng)建
df?=?pd.DataFrame({'month':?[1,?4,?7,?10],
????????????????????'year':?[2012,?2014,?2013,?2014],
????????????????????'sale':[55,?40,?84,?31]})
???month??sale??year
0??1??????55????2012
1??4??????40????2014
2??7??????84????2013
3??10?????31????2014
2、以月份設(shè)置新的索引
df.set_index('month')
???????sale??year
month
1??????55????2012
4??????40????2014
7??????84????2013
10?????31????2014
3、設(shè)置多個(gè)索引,以年和月份
df?=?df.set_index(['year',?'month'])
df
????????????sale
year??month
2012??1?????55
2014??4?????40
2013??7?????84
2014??10????31
注:通過(guò)剛才的設(shè)置,這樣DataFrame就變成了一個(gè)具有MultiIndex的DataFrame。
1.2.3 MultiIndex與Panel
(1)MultiIndex
MultiIndex是三維的數(shù)據(jù)結(jié)構(gòu);
多級(jí)索引(也稱層次化索引)是pandas的重要功能,可以在Series、DataFrame對(duì)象上擁有2個(gè)以及2個(gè)以上的索引。
- (1)multiIndex的特性
打印剛才的df的行索引結(jié)果
df
????????????sale
year??month
2012??1?????55
2014??4?????40
2013??7?????84
2014??10????31
df.index
MultiIndex(levels=[[2012,?2013,?2014],?[1,?4,?7,?10]],
???????????labels=[[0,?2,?1,?2],?[0,?1,?2,?3]],
???????????names=['year',?'month'])
多級(jí)或分層索引對(duì)象。
- index屬性
- names:levels的名稱
- levels:每個(gè)level的元組值
df.index.names
#?FrozenList(['year',?'month'])
df.index.levels
#?FrozenList([[2012,?2013,?2014],?[1,?4,?7,?10]])
- (2)multiIndex的創(chuàng)建
arrays?=?[[1,?1,?2,?2],?['red',?'blue',?'red',?'blue']]
pd.MultiIndex.from_arrays(arrays,?names=('number',?'color'))
#?結(jié)果
MultiIndex(levels=[[1,?2],?['blue',?'red']],
???????????codes=[[0,?0,?1,?1],?[1,?0,?1,?0]],
???????????names=['number',?'color'])
(2)Panel
- (1)panel的創(chuàng)建
作用:存儲(chǔ)3維數(shù)組的Panel結(jié)構(gòu)
參數(shù):
data : ndarray或者dataframe
items : 索引或類似數(shù)組的對(duì)象,axis=0
major_axis : 索引或類似數(shù)組的對(duì)象,axis=1
minor_axis : 索引或類似數(shù)組的對(duì)象,axis=2
class pandas.Panel(data=None, items=None, major_axis=None, minor_axis=None)
p?=?pd.Panel(data=np.arange(24).reshape(4,3,2),
?????????????????items=list('ABCD'),
?????????????????major_axis=pd.date_range('20130101',?periods=3),
?????????????????minor_axis=['first',?'second'])
#?結(jié)果
<class?'pandas.core.panel.Panel'>
Dimensions:?4?(items)?x?3?(major_axis)?x?2?(minor_axis)
Items?axis:?A?to?D
Major_axis?axis:?2013-01-01?00:00:00?to?2013-01-03?00:00:00
Minor_axis?axis:?first?to?second
- (2)查看panel數(shù)據(jù)
p[:,:,"first"]
p["B",:,:]
2、基本數(shù)據(jù)操作注:Pandas從版本0.20.0開(kāi)始棄用:推薦的用于表示3D數(shù)據(jù)的方法是通過(guò)DataFrame上的MultiIndex方法。
為了更好的理解這些基本操作,我們將讀取一個(gè)真實(shí)的股票數(shù)據(jù)。關(guān)于文件操作,后面在介紹,這里只先用一下API。
#?讀取文件
data?=?pd.read_csv("./data/stock_day.csv")
#?刪除一些列,讓數(shù)據(jù)更簡(jiǎn)單些,再去做后面的操作
data?=?data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"],?axis=1)

2.1 索引操作
Numpy當(dāng)中我們已經(jīng)講過(guò)使用索引選取序列和切片選擇,pandas也支持類似的操作,也可以直接使用列名、行名稱,甚至組合使用。
2.2.1 直接使用行列索引(先列后行)
獲取’2018-02-27’這天的’open’的結(jié)果:
#?直接使用行列索引名字的方式(先列后行)
data['open']['2018-02-27']
23.53
#?不支持的操作
#?錯(cuò)誤
data['2018-02-27']['open']
#?錯(cuò)誤
data[:1,?:2]
2.2.2 結(jié)合loc或者iloc使用索引
獲取從’2018-02-27’到’2018-02-22’,'open’的結(jié)果:
#?使用loc:只能指定行列索引的名字
data.loc['2018-02-27':'2018-02-22',?'open']
2018-02-27????23.53
2018-02-26????22.80
2018-02-23????22.88
Name:?open,?dtype:?float64
#?使用iloc可以通過(guò)索引的下標(biāo)去獲取
#?獲取前3天數(shù)據(jù),前5列的結(jié)果
data.iloc[:3,?:5]
????????????open????high????close????low
2018-02-27????23.53????25.88????24.16????23.53
2018-02-26????22.80????23.78????23.53????22.80
2018-02-23????22.88????23.37????22.82????22.71
2.2.3 使用ix組合索引(混合索引:下標(biāo)和名稱)
獲取行第1天到第4天,[‘open’, ‘close’, ‘high’, ‘low’]這個(gè)四個(gè)指標(biāo)的結(jié)果:
#?使用ix進(jìn)行下表和名稱組合做引
data.ix[0:4,?['open',?'close',?'high',?'low']]
#?推薦使用loc和iloc來(lái)獲取的方式
data.loc[data.index[0:4],?['open',?'close',?'high',?'low']]
data.iloc[0:4,?data.columns.get_indexer(['open',?'close',?'high',?'low'])]
????????????open????close????high????low
2018-02-27????23.53????24.16????25.88????23.53
2018-02-26????22.80????23.53????23.78????22.80
2018-02-23????22.88????22.82????23.37????22.71
2018-02-22????22.25????22.28????22.76????22.02
2.2 賦值操作
對(duì)DataFrame當(dāng)中的close列進(jìn)行重新賦值為1。
#?直接修改原來(lái)的值
data['close']?=?1?#?這一列都變成1
#?或者
data.close?=?1
2.3 排序
排序有兩種形式,一種對(duì)于索引進(jìn)行排序,一種對(duì)于內(nèi)容進(jìn)行排序:
2.3.1 DataFrame排序
- (1)使用
df.sort_values(by=, ascending=)- by:指定排序參考的鍵
- ascending:默認(rèn)升序
- ascending=False:降序
- ascending=True:升序
- 單個(gè)鍵或者多個(gè)鍵進(jìn)行排序,
- 參數(shù):
如下:
例一:
#?按照開(kāi)盤價(jià)大小進(jìn)行排序?,?使用ascending指定按照大小排序
data.sort_values(by="open",?ascending=True).head()
結(jié)果:
例二:
#?按照多個(gè)鍵進(jìn)行排序
data.sort_values(by=['open',?'high'])
結(jié)果:
- (2)使用
df.sort_index(ascending=)給索引進(jìn)行排序
這個(gè)股票的日期索引原來(lái)是從大到小,現(xiàn)在重新排序,從小到大:
#?對(duì)索引進(jìn)行排序
data.sort_index()
結(jié)果:
2.3.2 Series排序
- (1)使用
series.sort_values(ascending=True)進(jìn)行排序
series排序時(shí),只有一列,不需要參數(shù)
data['p_change'].sort_values(ascending=True).head()
2015-09-01???-10.03
2015-09-14???-10.02
2016-01-11???-10.02
2015-07-15???-10.02
2015-08-26???-10.01
Name:?p_change,?dtype:?float64
- (2)使用
series.sort_index()進(jìn)行排序
與df一致
#?對(duì)索引進(jìn)行排序
data['p_change'].sort_index().head()
2015-03-02????2.62
2015-03-03????1.44
2015-03-04????1.57
2015-03-05????2.02
2015-03-06????8.51
Name:?p_change,?dtype:?float64
2.4 總結(jié)
3、DataFrame運(yùn)算3.1 算術(shù)運(yùn)算
- (1)
add(other)
比如進(jìn)行數(shù)學(xué)運(yùn)算加上具體的一個(gè)數(shù)字
data['open'].head().add(1)
2018-02-27????24.53
2018-02-26????23.80
2018-02-23????23.88
2018-02-22????23.25
2018-02-14????22.49
Name:?open,?dtype:?float64
- (2)
sub(other)
整個(gè)列減一個(gè)數(shù)
data.open.head().sub(2)
2018-02-27????21.53
2018-02-26????20.80
2018-02-23????20.88
2018-02-22????20.25
2018-02-14????19.49
Name:?open,?dtype:?float64
3.2 邏輯運(yùn)算
3.2.1 邏輯運(yùn)算符號(hào)
- 例如篩選data[“open”] > 23的日期數(shù)據(jù)
- data[“open”] > 23返回邏輯結(jié)果
data["open"]?>?23
2018-02-27?????True
2018-02-26????False
2018-02-23????False
2018-02-22????False
2018-02-14????False
#?邏輯判斷的結(jié)果可以作為篩選的依據(jù)
data[data["open"]?>?23].head()
結(jié)果:
- 完成多個(gè)邏輯判斷:
data[(data["open"]?>?23)?&?(data["open"]?<?24)].head()

3.2.2 邏輯運(yùn)算函數(shù)
- (1)
query(expr)- expr:查詢字符串
通過(guò)query使得剛才的過(guò)程更加方便簡(jiǎn)單,下面是使用的例子:
data.query("open<24?&?open>23").head()
結(jié)果:
- (2)
isin(values)
例如判斷’open’是否為23.53和23.85:
#?可以指定值進(jìn)行一個(gè)判斷,從而進(jìn)行篩選操作
data[data["open"].isin([23.53,?23.85])]

3.2.3 統(tǒng)計(jì)運(yùn)算
(1)describe
綜合分析: 能夠直接得出很多統(tǒng)計(jì)結(jié)果,count, mean, std, min, max 等
#?計(jì)算平均值、標(biāo)準(zhǔn)差、最大值、最小值
data.describe()

(2)統(tǒng)計(jì)函數(shù)
看一下min(最小值), max(最大值), mean(平均值), median(中位數(shù)), var(方差), std(標(biāo)準(zhǔn)差),mode(眾數(shù))是怎么操作的:

對(duì)于單個(gè)函數(shù)去進(jìn)行統(tǒng)計(jì)的時(shí)候,坐標(biāo)軸還是按照默認(rèn)列“columns” (axis=0, default),如果要對(duì)行“index” 需要指定(axis=1)。
- (1)
max()、min()
#?使用統(tǒng)計(jì)函數(shù):0?代表列求結(jié)果, 1 代表行求統(tǒng)計(jì)結(jié)果
data.max(axis=0)?#?最大值
open???????????????????34.99
high???????????????????36.35
close??????????????????35.21
low????????????????????34.01
volume?????????????501915.41
price_change????????????3.03
p_change???????????????10.03
turnover???????????????12.56
my_price_change?????????3.41
dtype:?float64
- (2)
std()、var()
#?方差
data.var(axis=0)
open???????????????1.545255e+01
high???????????????1.662665e+01
close??????????????1.554572e+01
low????????????????1.437902e+01
volume?????????????5.458124e+09
price_change???????8.072595e-01
p_change???????????1.664394e+01
turnover???????????4.323800e+00
my_price_change????6.409037e-01
dtype:?float64
#?標(biāo)準(zhǔn)差
data.std(axis=0)
open???????????????????3.930973
high???????????????????4.077578
close??????????????????3.942806
low????????????????????3.791968
volume?????????????73879.119354
price_change???????????0.898476
p_change???????????????4.079698
turnover???????????????2.079375
my_price_change????????0.800565
dtype:?float64
- (3)
median():中位數(shù)
中位數(shù)為將數(shù)據(jù)從小到大排列,在最中間的那個(gè)數(shù)為中位數(shù)。如果沒(méi)有中間數(shù),取中間兩個(gè)數(shù)的平均值。
data.median(axis=0)
open???????????????21.44
high???????????????21.97
close??????????????10.00
low????????????????20.98
volume??????????83175.93
price_change????????0.05
p_change????????????0.26
turnover????????????2.50
dtype:?float64
- (4)
idxmax()、idxmin()
#?求出最大值的位置
data.idxmax(axis=0)
open???????????????2015-06-15
high???????????????2015-06-10
close??????????????2015-06-12
low????????????????2015-06-12
volume?????????????2017-10-26
price_change???????2015-06-09
p_change???????????2015-08-28
turnover???????????2017-10-26
my_price_change????2015-07-10
dtype:?object
#?求出最小值的位置
data.idxmin(axis=0)
open???????????????2015-03-02
high???????????????2015-03-02
close??????????????2015-09-02
low????????????????2015-03-02
volume?????????????2016-07-06
price_change???????2015-06-15
p_change???????????2015-09-01
turnover???????????2016-07-06
my_price_change????2015-06-15
dtype:?object
(3)累計(jì)統(tǒng)計(jì)函數(shù)

那么這些累計(jì)統(tǒng)計(jì)函數(shù)怎么用?
以上這些函數(shù)可以對(duì)series和dataframe操作,這里我們按照時(shí)間的從前往后來(lái)進(jìn)行累計(jì)
- 排序
#?排序之后,進(jìn)行累計(jì)求和
data?=?data.sort_index()
- 對(duì)p_change進(jìn)行求和
stock_rise?=?data['p_change']
stock_rise.cumsum()
2015-03-02??????2.62
2015-03-03??????4.06
2015-03-04??????5.63
2015-03-05??????7.65
2015-03-06?????16.16
2015-03-09?????16.37
2015-03-10?????18.75
2015-03-11?????16.36
2015-03-12?????15.03
2015-03-13?????17.58
2015-03-16?????20.34
2015-03-17?????22.42
2015-03-18?????23.28
2015-03-19?????23.74
2015-03-20?????23.48
2015-03-23?????23.74
那么如何讓這個(gè)連續(xù)求和的結(jié)果更好的顯示呢?
如果要使用plot函數(shù),需要導(dǎo)入matplotlib.下面是繪圖代碼:
import?matplotlib.pyplot?as?plt
#?plot顯示圖形,?plot方法集成了直方圖、條形圖、餅圖、折線圖
stock_rise.cumsum().plot()
#?需要調(diào)用show,才能顯示出結(jié)果
plt.show()
結(jié)果:
關(guān)于plot,稍后會(huì)介紹API的選擇。
(4)自定義運(yùn)算
apply(func, axis=0)- func:自定義函數(shù)
- axis=0:默認(rèn)是列,axis=1為行進(jìn)行運(yùn)算
- 定義一個(gè)對(duì)列,最大值-最小值的函數(shù)
下面看個(gè)例子:
data[['open',?'close']].apply(lambda?x:?x.max()?-?x.min(),?axis=0)
open?????22.74
close????22.85
dtype:?float64
4、Pandas畫圖特定需求需要用這個(gè)。
4.1 pandas.DataFrame.plot
DataFrame.plot(kind='line')- ‘line’ : 折線圖
- ‘bar’ : 條形圖
- ‘barh’ : 橫放的條形圖
- ‘hist’ : 直方圖
- ‘pie’ : 餅圖
- ‘scatter’ : 散點(diǎn)圖
- kind : str,需要繪制圖形的種類
關(guān)于“barh”的解釋:
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.barh.html
更多細(xì)節(jié):https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html?highlight=plot#pandas.DataFrame.plot
看個(gè)例子:
import?matplotlib.pyplot?as?plt
#?plot顯示圖形,?plot方法集成了直方圖、條形圖、餅圖、折線圖
stock_rise.cumsum().plot(kind="line")
#?需要調(diào)用show,才能顯示出結(jié)果
plt.show()
結(jié)果:
4.2 pandas.Series.plot
更多細(xì)節(jié):https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.plot.html?highlight=plot#pandas.Series.plot
5、文件讀取與存儲(chǔ)注:使用的時(shí)候查看。
我們的數(shù)據(jù)大部分存在于文件當(dāng)中,所以pandas會(huì)支持復(fù)雜的IO操作,pandas的API支持眾多的文件格式,如CSV、SQL、XLS、JSON、HDF5。
注:最常用的HDF5和CSV文件

接下來(lái)重點(diǎn)看一下,應(yīng)用CSV方式、HDF方式和json方式實(shí)現(xiàn)文件的讀取和存儲(chǔ)。
5.1 CSV
5.1.1 read_csv
pandas.read_csv(filepath_or_buffer, sep =',', usecols )- filepath_or_buffer:文件路徑
- sep :分隔符,默認(rèn)用","隔開(kāi)
- usecols:指定讀取的列名,列表形式
舉例:讀取之前的股票的數(shù)據(jù):
#?讀取文件,并且指定只獲取'open',?'close'指標(biāo)
data?=?pd.read_csv("./data/stock_day.csv",?usecols=['open',?'close'])
????????????open????close
2018-02-27????23.53????24.16
2018-02-26????22.80????23.53
2018-02-23????22.88????22.82
2018-02-22????22.25????22.28
2018-02-14????21.49????21.92
5.1.2 to_csv
DataFrame.to_csv(path_or_buf=None, sep=', ’, columns=None, header=True, index=True, mode='w', encoding=None)- path_or_buf :文件路徑
- sep :分隔符,默認(rèn)用","隔開(kāi)
- columns :選擇需要的列索引
- header :boolean or list of string, default True,是否寫進(jìn)列索引值
- index:是否寫進(jìn)行索引
- mode:‘w’:重寫, ‘a(chǎn)’ 追加
舉例:保存讀取出來(lái)的股票數(shù)據(jù)
保存’open’列的數(shù)據(jù),然后讀取查看結(jié)果:
#?選取10行數(shù)據(jù)保存,便于觀察數(shù)據(jù)
data[:10].to_csv("./data/test.csv",?columns=['open'])
#?讀取,查看結(jié)果
pd.read_csv("./data/test.csv")
?????Unnamed:?0????open
0????2018-02-27????23.53
1????2018-02-26????22.80
2????2018-02-23????22.88
3????2018-02-22????22.25
4????2018-02-14????21.49
5????2018-02-13????21.40
6????2018-02-12????20.70
7????2018-02-09????21.20
8????2018-02-08????21.79
9????2018-02-07????22.69
會(huì)發(fā)現(xiàn)將索引存入到文件當(dāng)中,變成單獨(dú)的一列數(shù)據(jù)。如果需要?jiǎng)h除,可以指定index參數(shù),刪除原來(lái)的文件,重新保存一次。
下面例子把index指定為False,那么保存的時(shí)候就不會(huì)保存行索引了:
#?index:存儲(chǔ)不會(huì)將索引值變成一列數(shù)據(jù)
data[:10].to_csv("./data/test.csv",?columns=['open'],?index=False)
當(dāng)然我們也可以這么做,就是把索引保存到文件中,讀取的時(shí)候變成了一列,那么可以把這個(gè)列再變成索引,如下:
#?把Unnamed:?0這一列,變成行索引
open.set_index(["Unnamed:?0"])
#?把索引名字變成index
open.index.name?=?"index"
5.2 HDF5
5.2.1 read_hdf與to_hdf
HDF5文件的讀取和存儲(chǔ)需要指定一個(gè)鍵,值為要存儲(chǔ)的DataFrame
(1)
pandas.read_hdf(path_or_buf,key =None,** kwargs)- path_or_buffer:文件路徑
- key:讀取的鍵
- return:Theselected object
(2)
DataFrame.to_hdf(path_or_buf, key, **kwargs)
5.2.2 案例
- 讀取文件
day_close?=?pd.read_hdf("./data/day_close.h5")
如果讀取的時(shí)候出現(xiàn)以下錯(cuò)誤
需要安裝安裝tables模塊避免不能讀取HDF5文件
pip?install?tables

- 存儲(chǔ)文件
day_close.to_hdf("./data/test.h5",?key="day_close")
再次讀取的時(shí)候, 需要指定鍵的名字
new_close?=?pd.read_hdf("./data/test.h5",?key="day_close")
注意:優(yōu)先選擇使用HDF5文件存儲(chǔ)
- HDF5在存儲(chǔ)的時(shí)候支持壓縮,使用的方式是blosc,這個(gè)是速度最快的也是pandas默認(rèn)支持的
- 使用壓縮可以提磁盤利用率,節(jié)省空間
- HDF5還是跨平臺(tái)的,可以輕松遷移到hadoop 上面
5.3 JSON
JSON是我們常用的一種數(shù)據(jù)交換格式,在前后端的交互經(jīng)常用到,也會(huì)在存儲(chǔ)的時(shí)候選擇這種格式。所以我們需要知道Pandas如何進(jìn)行讀取和存儲(chǔ)JSON格式。
5.3.1 read_json
pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)- 按照每行讀取json對(duì)象
- (1)‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}
- (2)‘records’ : list like [{column -> value}, … , {column -> value}]
- (3)‘index’ : dict like {index -> {column -> value}}
- (4)‘columns’ : dict like {column -> {index -> value}},默認(rèn)該格式
- (5)‘values’ : just the values array
- split 將索引總結(jié)到索引,列名到列名,數(shù)據(jù)到數(shù)據(jù)。將三部分都分開(kāi)了
- records 以columns:values的形式輸出
- index 以index:{columns:values}…的形式輸出
- colums 以columns:{index:values}的形式輸出
- values 直接輸出值
path_or_buf: 路徑orient: string,以什么樣的格式顯示.下面是5種格式:lines: boolean, default Falsetyp: default ‘frame’, 指定轉(zhuǎn)換成的對(duì)象類型series或者dataframe
案例:
- 數(shù)據(jù)介紹:
這里使用一個(gè)新聞標(biāo)題諷刺數(shù)據(jù)集,格式為json。is_sarcastic:1諷刺的,否則為0;headline:新聞報(bào)道的標(biāo)題;article_link:鏈接到原始新聞文章。存儲(chǔ)格式為:
{"article_link":?"https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5",?"headline":?"former?versace?store?clerk?sues?over?secret?'black?code'?for?minority?shoppers",?"is_sarcastic":?0}
{"article_link":?"https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365",?"headline":?"the?'roseanne'?revival?catches?up?to?our?thorny?political?mood,?for?better?and?worse",?"is_sarcastic":?0}
- 讀取
orient指定存儲(chǔ)的json格式,lines指定按照行去變成一個(gè)樣本:
json_read?=?pd.read_json("./data/Sarcasm_Headlines_Dataset.json",?orient="records",?lines=True)
結(jié)果為:
5.3.2 to_json
DataFrame.to_json(path_or_buf=None, orient=None, lines=False)- 將Pandas 對(duì)象存儲(chǔ)為json格式
- path_or_buf=None:文件地址
- orient:存儲(chǔ)的json形式,{‘split’,’records’,’index’,’columns’,’values’}
- lines:一個(gè)對(duì)象存儲(chǔ)為一行
案例:
- 存儲(chǔ)文件
#?不指定lines=Treu,則保存成一行
json_read.to_json("./data/test.json",?orient='records')
結(jié)果:
[{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former?versace?store?clerk?sues?over?secret?'black?code'?for?minority?shoppers","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the?'roseanne'?revival?catches?up?to?our?thorny?political?mood,?for?better?and?worse","is_sarcastic":0},{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom?starting?to?fear?son's?web?series?closest?thing?she?will?have?to?grandchild","is_sarcastic":1},{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner?just?wants?wife?to?listen,?not?come?up?with?alternative?debt-reduction?ideas","is_sarcastic":1},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k.?rowling?wishes?snape?happy?birthday?in?the?most?magical?way","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/advancing-the-worlds-women_b_6810038.html","headline":"advancing?the?world's?women","is_sarcastic":0},....]
- 修改
lines參數(shù)為True
#?指定lines=True,則多行存儲(chǔ)
json_read.to_json("./data/test.json",?orient='records',?lines=True)
結(jié)果:
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former?versace?store?clerk?sues?over?secret?'black?code'?for?minority?shoppers","is_sarcastic":0}
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the?'roseanne'?revival?catches?up?to?our?thorny?political?mood,?for?better?and?worse","is_sarcastic":0}
{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom?starting?to?fear?son's?web?series?closest?thing?she?will?have?to?grandchild","is_sarcastic":1}
{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner?just?wants?wife?to?listen,?not?come?up?with?alternative?debt-reduction?ideas","is_sarcastic":1}
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k.?rowling?wishes?snape?happy?birthday?in?the?most?magical?way","is_sarcastic":0}...
6、高級(jí)處理-缺失值處理在pandas中,缺失值使用NaN來(lái)標(biāo)記,如下圖所示:
6.1 如何處理nan
按如下步驟進(jìn)行:
(1)獲取缺失值的標(biāo)記方式(NaN或者其他標(biāo)記方式)
(2)如果缺失值的標(biāo)記方式是NaN
1、刪除存在缺失值的:
dropna(axis='rows')
注:不會(huì)修改原數(shù)據(jù),需要接受返回值2、替換缺失值:
fillna(value, inplace=True)- value:替換成的值
- inplace:True:會(huì)修改原數(shù)據(jù),F(xiàn)alse:不替換修改原數(shù)據(jù),生成新的對(duì)象
pd.isnull(df),pd.notnull(df)判斷數(shù)據(jù)中是否包含NaN:
存在缺失值nan:
(3)如果缺失值沒(méi)有使用NaN標(biāo)記,比如使用"?"
- 先替換‘?’為np.nan,然后繼續(xù)處理
步驟就是上面的這樣,下面通過(guò)例子來(lái)看看怎么使用pandas處理的:
6.2 電影數(shù)據(jù)的缺失值處理
- 電影數(shù)據(jù)文件獲取
#?讀取電影數(shù)據(jù)
movie?=?pd.read_csv("./data/IMDB-Movie-Data.csv")

6.2.1 判斷缺失值是否存在
(1)
pd.notnull()
#?判斷是否是缺失值,是則返回False
pd.notnull(movie)
#?結(jié)果:
Rank????Title????Genre????Description????Director????Actors????Year????Runtime?(Minutes)????Rating????Votes????Revenue?(Millions)????Metascore
0????True????True????True????True????True????True????True????True????True????True????True????True
1????True????True????True????True????True????True????True????True????True????True????True????True
2????True????True????True????True????True????True????True????True????True????True????True????True
3????True????True????True????True????True????True????True????True????True????True????True????True
4????True????True????True????True????True????True????True????True????True????True????True????True
5????True????True????True????True????True????True????True????True????True????True????True????True
6????True????True????True????True????True????True????True????True????True????True????True????True
7????True????True????True????True????True????True????True????True????True????True????False????True
但是上面這樣顯然不好觀察,我們可以借助np.all()來(lái)返回是否有缺失值。np.all()只要有一個(gè)就返回False,下面看例子:
np.all(pd.notnull(movie))
#?返回
False
(2)
pd.isnull()這個(gè)和上面的正好相反,判斷是否是缺失值,是則返回True。
#?判斷是否是缺失值,是則返回True
pd.isnull(movie).head()
#?結(jié)果:
?Rank?Title?Genre?Description?Director?Actors?Year?Runtime?(Minutes)?Rating?Votes?Revenue?(Millions)?Metascore
0?False?False?False?False?False?False?False?False?False?False?False?False
1?False?False?False?False?False?False?False?False?False?False?False?False
2?False?False?False?False?False?False?False?False?False?False?False?False
3?False?False?False?False?False?False?False?False?False?False?False?False
4?False?False?False?False?False?False?False?False?False?False?False?False
這個(gè)也不好觀察,我們利用np.any() 來(lái)判斷是否有缺失值,若有則返回True,下面看例子:
np.any(pd.isnull(movie))
#?返回
True
6.2.2 存在缺失值nan,并且是np.nan
- 1、刪除
pandas刪除缺失值,使用dropna的前提是,缺失值的類型必須是np.nan
#?不修改原數(shù)據(jù)
movie.dropna()
#?可以定義新的變量接受或者用原來(lái)的變量名
data?=?movie.dropna()
- 2、替換缺失值
#?替換存在缺失值的樣本的兩列
#?替換填充平均值,中位數(shù)
movie['Revenue?(Millions)'].fillna(movie['Revenue?(Millions)'].mean(),?inplace=True)
替換所有缺失值:
#?這個(gè)循環(huán),每次取出一列數(shù)據(jù),然后用均值來(lái)填充
for?i?in?movie.columns:
????if?np.all(pd.notnull(movie[i]))?==?False:
????????print(i)
????????movie[i].fillna(movie[i].mean(),?inplace=True)
6.2.3 不是缺失值nan,有默認(rèn)標(biāo)記的
直接看例子:
數(shù)據(jù)是這樣的:
#?讀入數(shù)據(jù)
wis?=?pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")
以上數(shù)據(jù)在讀取時(shí),可能會(huì)報(bào)如下錯(cuò)誤:
URLError:?<urlopen?error?[SSL:?CERTIFICATE_VERIFY_FAILED]?certificate?verify?failed?(_ssl.c:833)>
解決辦法:
#?全局取消證書驗(yàn)證
import?ssl
ssl._create_default_https_context?=?ssl._create_unverified_context
處理思路分析:
- 1、先替換‘?’為np.nan
- to_replace:替換前的值
- value:替換后的值
df.replace(to_replace=, value=)
#?把一些其它值標(biāo)記的缺失值,替換成np.nan
wis?=?wis.replace(to_replace='?',?value=np.nan)
- 2、再進(jìn)行缺失值的處理
#?刪除
wis?=?wis.dropna()
- 3、驗(yàn)證:
np.all(pd.notnull(wis))
#?返回True,說(shuō)明沒(méi)有了缺失值
#?或者
np.any(pd.isnull(wis))
#?返回False,說(shuō)明沒(méi)有了缺失值
7、高級(jí)處理-數(shù)據(jù)離散化7.1 為什么要離散化
連續(xù)屬性離散化的目的是為了簡(jiǎn)化數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)離散化技術(shù)可以用來(lái)減少給定連續(xù)屬性值的個(gè)數(shù)。離散化方法經(jīng)常作為數(shù)據(jù)挖掘的工具。
7.2 什么是數(shù)據(jù)的離散化
連續(xù)屬性的離散化就是在連續(xù)屬性的值域上,將值域劃分為若干個(gè)離散的區(qū)間,最后用不同的符號(hào)或整數(shù) 值代表落在每個(gè)子區(qū)間中的屬性值。
離散化有很多種方法,這里使用一種最簡(jiǎn)單的方式去操作:
- 原始人的身高數(shù)據(jù):165,174,160,180,159,163,192,184
- 假設(shè)按照身高分幾個(gè)區(qū)間段:150~165, 165~180,180~195
這樣我們將數(shù)據(jù)分到了三個(gè)區(qū)間段,對(duì)應(yīng)的標(biāo)記為矮、中、高三個(gè)類別,最終要處理成一個(gè)"啞變量"矩陣。
下面通過(guò)股票數(shù)據(jù)的例子來(lái)看看,具體是怎么操作的。
7.3 股票的漲跌幅離散化
我們對(duì)股票每日的"p_change"這一列進(jìn)行離散化,下圖便是離散化后的結(jié)果,當(dāng)前數(shù)據(jù)存在哪個(gè)區(qū)間,則這個(gè)區(qū)間標(biāo)記為1,否則為0。

那具體怎么做的呢?接著看:
7.3.1 讀取股票的數(shù)據(jù)
先讀取股票的數(shù)據(jù),篩選出p_change數(shù)據(jù)。
data?=?pd.read_csv("./data/stock_day.csv")
p_change=?data['p_change']
7.3.2 將股票漲跌幅數(shù)據(jù)進(jìn)行分組
下面是所在區(qū)間的個(gè)數(shù)。
使用的工具:
pd.qcut(data, q):- 對(duì)數(shù)據(jù)進(jìn)行分組,將數(shù)據(jù)分成q組,一般會(huì)與
value_counts搭配使用,統(tǒng)計(jì)每組的個(gè)數(shù)
- 對(duì)數(shù)據(jù)進(jìn)行分組,將數(shù)據(jù)分成q組,一般會(huì)與
series.value_counts():統(tǒng)計(jì)每個(gè)分組中有多少數(shù)據(jù)。
#?自行分組
qcut?=?pd.qcut(p_change,?10)
#?計(jì)算分到每個(gè)組數(shù)據(jù)個(gè)數(shù)
qcut.value_counts()
#?運(yùn)行結(jié)果:
(5.27,?10.03]????????????????????65
(0.26,?0.94]?????????????????????65
(-0.462,?0.26]???????????????????65
(-10.030999999999999,?-4.836]????65
(2.938,?5.27]????????????????????64
(1.738,?2.938]???????????????????64
(-1.352,?-0.462]?????????????????64
(-2.444,?-1.352]?????????????????64
(-4.836,?-2.444]?????????????????64
(0.94,?1.738]????????????????????63
Name:?p_change,?dtype:?int64
自定義區(qū)間分組:
pd.cut(data, bins)
#?自己指定分組區(qū)間
bins?=?[-100,?-7,?-5,?-3,?0,?3,?5,?7,?100]
p_counts?=?pd.cut(p_change,?bins)
p_counts.value_counts()
#?運(yùn)行結(jié)果:
(0,?3]????????215
(-3,?0]???????188
(3,?5]?????????57
(-5,?-3]???????51
(7,?100]???????35
(5,?7]?????????35
(-100,?-7]?????34
(-7,?-5]???????28
Name:?p_change,?dtype:?int64
7.3.3 股票漲跌幅分組數(shù)據(jù)變成one-hot編碼
- 什么是one-hot編碼
把每個(gè)類別生成一個(gè)布爾列,這些列中只有一列可以為這個(gè)樣本取值為1.其又被稱為熱編碼。
把下圖中左邊的表格轉(zhuǎn)化為使用右邊形式進(jìn)行表示:

下面看看pandas中是怎么實(shí)現(xiàn)的:
pandas.get_dummies(data, prefix=None)data:array-like, Series, or DataFrame
prefix:分組名字
下面是例子:
#?得出one-hot編碼矩陣
dummies?=?pd.get_dummies(p_counts,?prefix="rise")
運(yùn)行結(jié)果:
如果你的數(shù)據(jù)由多張表組成,那么有時(shí)候需要將不同的內(nèi)容合并在一起分析
8.1 pd.concat實(shí)現(xiàn)數(shù)據(jù)合并
pd.concat([data1, data2], axis=1)- 按照行或列進(jìn)行合并,axis=0為列索引,axis=1為行索引
比如我們將剛才處理好的one-hot編碼與原數(shù)據(jù)合并:
#?按照行索引進(jìn)行
pd.concat([data,?dummies],?axis=1)
結(jié)果:
8.2 pd.merge
pd.merge(left, right, how='inner', on=None)- 可以指定按照兩組數(shù)據(jù)的共同鍵值對(duì)合并或者左右各自
left: DataFrameright: 另一個(gè)DataFrameon: 指定的共同鍵how:按照什么方式連接,下面的表格是說(shuō)明

例子:
left?=?pd.DataFrame({'key1':?['K0',?'K0',?'K1',?'K2'],
????????????????????????'key2':?['K0',?'K1',?'K0',?'K1'],
????????????????????????'A':?['A0',?'A1',?'A2',?'A3'],
????????????????????????'B':?['B0',?'B1',?'B2',?'B3']})
right?=?pd.DataFrame({'key1':?['K0',?'K1',?'K1',?'K2'],
????????????????????????'key2':?['K0',?'K0',?'K0',?'K0'],
????????????????????????'C':?['C0',?'C1',?'C2',?'C3'],
????????????????????????'D':?['D0',?'D1',?'D2',?'D3']})
- 內(nèi)連接:健相同的取上,不同的刪掉
#?默認(rèn)內(nèi)連接
result?=?pd.merge(left,?right,?on=['key1',?'key2'])
結(jié)果:
- 左連接:按左邊的數(shù)據(jù)進(jìn)行合并
result?=?pd.merge(left,?right,?how='left',?on=['key1',?'key2'])
結(jié)果:
- 右連接:按右邊的數(shù)據(jù)進(jìn)行合并
result?=?pd.merge(left,?right,?how='right',?on=['key1',?'key2'])

- 外鏈接:無(wú)論健是否相同都取上,對(duì)應(yīng)不上的使用NaN填充。
result?=?pd.merge(left,?right,?how='outer',?on=['key1',?'key2'])
結(jié)果:
9.1 交叉表與透視表什么作用
探究股票的漲跌與星期幾有關(guān)?
以下圖當(dāng)中表示,week代表星期幾,1,0代表這一天股票的漲跌幅是好還是壞,里面的數(shù)據(jù)代表比例
可以理解為所有時(shí)間為星期一等等的數(shù)據(jù)當(dāng)中漲跌幅好壞的比例

- 交叉表:交叉表用于計(jì)算一列數(shù)據(jù)對(duì)于另外一列數(shù)據(jù)的分組個(gè)數(shù)(用于統(tǒng)計(jì)分組頻率的特殊透視表)
pd.crosstab(value1, value2)
- 透視表:透視表是將原有的DataFrame的列分別作為行索引和列索引,然后對(duì)指定的列應(yīng)用聚集函數(shù)
data.pivot_table()DataFrame.pivot_table([], index=[])
9.2 案例分析
9.2.1 數(shù)據(jù)準(zhǔn)備
- 準(zhǔn)備兩列數(shù)據(jù),星期數(shù)據(jù)以及漲跌幅是好是壞數(shù)據(jù)
- 進(jìn)行交叉表計(jì)算
#?尋找星期幾跟股票張得的關(guān)系
#?1、先把對(duì)應(yīng)的日期找到星期幾
date?=?pd.to_datetime(data.index).weekday
data['week']?=?date??#?增加一列
#?2、假如把p_change按照大小去分個(gè)類0為界限
data['posi_neg']?=?np.where(data['p_change']?>?0,?1,?0)
#?通過(guò)交叉表找尋兩列數(shù)據(jù)的關(guān)系
count?=?pd.crosstab(data['week'],?data['posi_neg'])
結(jié)果:

但是我們看到count只是每個(gè)星期日子的好壞天數(shù),并沒(méi)有得到比例,該怎么去做?
- 對(duì)于每個(gè)星期一等的總天數(shù)求和,運(yùn)用除法運(yùn)算求出比例
#?算數(shù)運(yùn)算,先求和
sum?=?count.sum(axis=1).astype(np.float32)
#?進(jìn)行相除操作,得出比例
pro?=?count.div(sum,?axis=0)
結(jié)果:
9.2.2 查看效果
使用plot畫出這個(gè)比例,使用stacked的柱狀圖
pro.plot(kind='bar',?stacked=True)
plt.show()

9.2.3 使用pivot_table(透視表)實(shí)現(xiàn)
使用透視表,剛才的過(guò)程更加簡(jiǎn)單
#?通過(guò)透視表,將整個(gè)過(guò)程變成更簡(jiǎn)單一些
data.pivot_table(['posi_neg'],?index='week')
結(jié)果:
分組與聚合通常是分析數(shù)據(jù)的一種方式,通常與一些統(tǒng)計(jì)函數(shù)一起使用,查看數(shù)據(jù)的分組情況
10.1 什么分組與聚合
下圖展示了分組與聚合的概念:
10.2 分組API
DataFrame.groupby(key, as_index=False)- key:分組的列數(shù)據(jù),可以多個(gè)
案例:不同顏色的不同筆的價(jià)格數(shù)據(jù)
col?=pd.DataFrame({'color':?['white','red','green','red','green'],?'object':?['pen','pencil','pencil','ashtray','pen'],'price1':[5.56,4.20,1.30,0.56,2.75],'price2':[4.75,4.12,1.60,0.75,3.15]})
#?結(jié)果:
color????object????price1????price2
0????white????pen????5.56????4.75
1????red????pencil????4.20????4.12
2????green????pencil????1.30????1.60
3????red????ashtray????0.56????0.75
4????green????pen????2.75????3.15
- 進(jìn)行分組,對(duì)顏色分組,price進(jìn)行聚合:
#?按color分組,再取出price1列求平均值
col.groupby(['color'])['price1'].mean()
#?和上述一個(gè)功能
col['price1'].groupby(col['color']).mean()
#?結(jié)果:
color
green????2.025
red??????2.380
white????5.560
Name:?price1,?dtype:?float64
#?分組,數(shù)據(jù)的結(jié)構(gòu)不變
col.groupby(['color'],?as_index=False)['price1'].mean()
#?結(jié)果:
color????price1
0????green????2.025
1????red????2.380
2????white????5.560
10.3 星巴克零售店鋪數(shù)據(jù)
現(xiàn)在我們有一組關(guān)于全球星巴克店鋪的統(tǒng)計(jì)數(shù)據(jù),如果我想知道美國(guó)的星巴克數(shù)量和中國(guó)的哪個(gè)多,或者我想知道中國(guó)每個(gè)省份星巴克的數(shù)量的情況,那么應(yīng)該怎么辦?
數(shù)據(jù)來(lái)源:https://www.kaggle.com/starbucks/store-locations/data

10.3.1 數(shù)據(jù)獲取
從文件中讀取星巴克店鋪數(shù)據(jù)
#?導(dǎo)入星巴克店的數(shù)據(jù)
starbucks?=?pd.read_csv("./data/starbucks/directory.csv")
10.3.2 進(jìn)行分組聚合
#?按照國(guó)家分組,求出每個(gè)國(guó)家的星巴克零售店數(shù)量
count?=?starbucks.groupby(['Country']).count()
畫圖顯示結(jié)果:
count['Brand'].plot(kind='bar',?figsize=(20,?8))
plt.show()

假設(shè)我們加入省市一起進(jìn)行分組:
#?設(shè)置多個(gè)索引,set_index()
starbucks.groupby(['Country',?'State/Province']).count()
結(jié)果:
11.1 需求
現(xiàn)在我們有一組從2006年到2016年1000部最流行的電影數(shù)據(jù)
數(shù)據(jù)來(lái)源:https://www.kaggle.com/damianpanek/sunday-eda/data
- 問(wèn)題1:我們想知道這些電影數(shù)據(jù)中評(píng)分的平均分,導(dǎo)演的人數(shù)等信息,我們應(yīng)該怎么獲取?
- 問(wèn)題2:對(duì)于這一組電影數(shù)據(jù),如果我們想rating,runtime的分布情況,應(yīng)該如何呈現(xiàn)數(shù)據(jù)?
- 問(wèn)題3:對(duì)于這一組電影數(shù)據(jù),如果我們希望統(tǒng)計(jì)電影分類(genre)的情況,應(yīng)該如何處理數(shù)據(jù)?
11.2 實(shí)現(xiàn)
首先獲取導(dǎo)入包,獲取數(shù)據(jù):
%matplotlib?inline
import?pandas??as?pd?
import?numpy?as?np
from?matplotlib?import?pyplot?as?plt
#文件的路徑
path?=?"./data/IMDB-Movie-Data.csv"
#讀取文件
df?=?pd.read_csv(path)
11.2.1 問(wèn)題一:
我們想知道這些電影數(shù)據(jù)中評(píng)分的平均分,導(dǎo)演的人數(shù)等信息,我們應(yīng)該怎么獲取?
- 得出評(píng)分的平均分
使用mean函數(shù)
df["Rating"].mean()
#?結(jié)果:
6.723200000000003
- 得出導(dǎo)演人數(shù)信息
求出唯一值,然后進(jìn)行形狀獲取
##?導(dǎo)演的人數(shù)
#?df["Director"].unique().shape[0]?#?方法一
np.unique(df["Director"]).shape[0]?#?方法二
644
11.2.2 問(wèn)題二:
對(duì)于這一組電影數(shù)據(jù),如果我們想Rating的分布情況,應(yīng)該如何呈現(xiàn)數(shù)據(jù)?
- 直接呈現(xiàn),以直方圖的形式
選擇分?jǐn)?shù)列數(shù)據(jù),進(jìn)行plot
df["Rating"].plot(kind='hist',figsize=(20,8))
plt.show()
效果:
發(fā)現(xiàn)直接通過(guò)pandas的plot畫圖,顯示的下標(biāo)不合適,這個(gè)時(shí)候我們需要借助matplotlib來(lái)改變。
- Rating進(jìn)行分布展示
進(jìn)行繪制直方圖
#?1.添加畫布
plt.figure(figsize=(20,8),dpi=100)
#?2.畫圖
plt.hist(df["Rating"].values,bins=20)
#?2.1?添加刻度線
max_?=?df["Rating"].max()
min_?=?df["Rating"].min()
x_ticks?=?np.linspace(min_,?max_,?num=21)
plt.xticks(x_ticks)
#?2.2添加網(wǎng)格線
plt.grid()
#?3.顯示
plt.show()

數(shù)據(jù)分析:從上圖中就可以發(fā)現(xiàn),評(píng)分主要分布在5~8分之間
11.2.3 問(wèn)題三:
對(duì)于這一組電影數(shù)據(jù),如果我們希望統(tǒng)計(jì)電影分類(genre)的情況,應(yīng)該如何處理數(shù)據(jù)?
- 思路分析
- 1、創(chuàng)建一個(gè)全為0的dataframe,列索引置為電影的分類,temp_df
- 2、遍歷每一部電影,temp_df中把分類出現(xiàn)的列的值置為1
- 3、求和
- 思路
下面接著看:
- 1、創(chuàng)建一個(gè)全為0的dataframe,列索引置為電影的分類,temp_df
#?進(jìn)行字符串分割
temp_list?=?[i.split(",")?for?i?in?df["Genre"]]
#?獲取電影的分類
genre_list?=?np.unique([i?for?j?in?temp_list?for?i?in?j])?
#?增加新的列,創(chuàng)建全為0的dataframe
temp_df?=?pd.DataFrame(np.zeros([df.shape[0],genre_list.shape[0]]),columns=genre_list)
- 2、遍歷每一部電影,temp_df中把分類出現(xiàn)的列的值置為1
for?i?in?range(1000):
????#temp_list[i]?就是['Action','Adventure','Animation']等
????temp_df.ix[i,temp_list[i]]=1
????
print(temp_df.sum().sort_values())?#?求合并排序,ascending=False為倒序
- 3、求和,繪圖
temp_df.sum().sort_values(ascending=False).plot(kind="bar",figsize=(20,8),fontsize=20,colormap="cool")
plt.show()
結(jié)果:
- EOF -
? 推薦閱讀:
點(diǎn)擊關(guān)注【python之禪】,提升Python技能??????
