10張思維導(dǎo)圖,全面講解 Pandas
哈嘍,大家好。今天 Python 中非常重要的一個庫——Pandas。
Pandas 是一個基于 Numpy 的強(qiáng)大工具集,用于數(shù)據(jù)處理、分析、挖掘和可視化。
我整理一張 Pandas 知識結(jié)構(gòu)的思維導(dǎo)圖,本文完整代碼可以關(guān)注我的另一個公眾號【簡說編程】,回復(fù):代碼?獲取。(注意??,看清獲取方式哈)。

下面我們用 10 個小節(jié)來學(xué)習(xí) Pandas,過程簡潔,思路清楚。
1. 數(shù)據(jù)結(jié)構(gòu)
Pandas中有兩種數(shù)據(jù)結(jié)構(gòu)Series和DataFrame。
Series用一維數(shù)組,可以存儲不同類型的數(shù)據(jù)。
>>>?import?pandas?as?pd
>>>?import?numpy?as?np
>>>?pd.Series(np.random.randn(5),?index=['a',?'b',?'c',?'d',?'e'])
a????0.881931
b???-0.112222
c????0.470156
d????0.394478
e????0.704801
dtype:?float64
pd.Series()函數(shù)用來創(chuàng)建Series對象。
第一個參數(shù)是存儲的數(shù)據(jù),這里是 Numpy 隨機(jī)生成的一維數(shù)組。
第二個參數(shù)index是數(shù)據(jù)對應(yīng)的索引。在 Python list或 Numpy 中數(shù)組的索引都是數(shù)字,也稱為下標(biāo),但在 Pandas 中索引可以是任意類型。
DataFrame是二維結(jié)構(gòu),類似 Excel 或數(shù)據(jù)庫中的表。
>>>?d?=?{'one':?pd.Series([1.,?2.,?3.],?index=['a',?'b',?'c']),'two':?pd.Series([1.,?2.,?3.,?4.],?index=['a',?'b',?'c',?'d'])}
>>>?df?=?pd.DataFrame(d)
>>>?df
???one??two
a??1.0??1.0
b??2.0??2.0
c??3.0??3.0
d??NaN??4.0
pd.DataFrame()函數(shù)用來創(chuàng)建DataFrame對象。
這里用字典d創(chuàng)建DataFrame對象,d中的兩個鍵值對作為DataFrame兩列。鍵作為列名,值是Series對象作為列值。
創(chuàng)建Series和DataFrame對象的方式還有很多

在 Pandas 中用DataFrame的頻率更高,下面的介紹以DataFrame為主。
2. 查看數(shù)據(jù)
上面創(chuàng)建的DataFrame只有幾條數(shù)據(jù),一眼就看完了。如果數(shù)據(jù)量比較大,就需要借助一些函數(shù)來查看。
通過屬性查看DataFrame基本情況,如:index、columns和shape
>>>?df.index
Index(['a',?'b',?'c',?'d'],?dtype='object')
通過head()和tail()函數(shù)查看DataFrame明細(xì)數(shù)據(jù)
>>>?df.head(2)
???one??two
a??1.0??1.0
b??2.0??2.0
通過describe()查看DataFrame每列統(tǒng)計(jì)摘要
>>>?df.describe()
???????one???????two
count??3.0??4.000000
mean???2.0??2.500000
std????1.0??1.290994
min????1.0??1.000000
25%????1.5??1.750000
50%????2.0??2.500000
75%????2.5??3.250000
max????3.0??4.000000

3. 索引
索引在 Pandas 中非常重要,通過索引我們可以獲取 Series 或 DataFrame中的任意數(shù)據(jù)。
Pandas的既有行索引,也有列索引。
3.1 索引的創(chuàng)建與轉(zhuǎn)化
索引除了創(chuàng)建Series 或 DataFrame時(shí)指定,也可以單獨(dú)創(chuàng)建。
>>>?index?=?pd.Index(['e',?'d',?'a',?'b'])
>>>?columns?=?pd.Index(['A',?'B',?'C'],?name='cols')
>>>?df?=?pd.DataFrame(np.random.randn(4,?3),?index=index,?columns=columns)
>>>?df
cols?????????A?????????B?????????C
e????-0.037910?-1.032842?-1.658740
d????-0.784543??0.649506??0.928499
a?????0.901721??0.022041?-0.515617
b????-0.443420?-0.246031?-0.803685
通過pd.Index分別創(chuàng)建行列索引index和columns,并用于創(chuàng)建 DateFrame。

3.2 索引排序
用sort_index函數(shù)對上面的df行索引排序
>>>?df.sort_index(axis=0)
cols?????????A?????????B?????????C
a?????2.180095?-1.820624??0.046273
b????-0.607010?-0.123721??1.375773
d????-0.057358?-1.403620??0.462811
e????-1.672218??1.299837??0.055571
Pandas 函數(shù)里經(jīng)常會見到 axis 參數(shù),用來指定行索引或列索引
axis=0 等價(jià)于 axis='index' axis=1 等價(jià)于 axis='columns'
axis=0 表示行索引或者行索引對應(yīng)的列值,因此,axis=0表示處理每列數(shù)據(jù)。同樣地,axis=1表示處理每行數(shù)據(jù)。
3.3 用索引訪問數(shù)據(jù)
通過[]形式直接獲取某列或某行
>>>?#?訪問A列,等價(jià)于?df.A
>>>?df['A']?
e???-1.672218
d???-0.057358
a????2.180095
b???-0.607010
>>>?df[:1]?#?切片訪問第一行
cols?????????A?????????B?????????C
e????-1.672218??1.299837??0.055571
通過標(biāo)簽選擇器.loc和.at,可按照索引名訪問數(shù)據(jù)。iloc獲取切片,.at獲取標(biāo)量。
>>>?df
cols?????????A?????????B?????????C
e????-1.672218??1.299837??0.055571
d????-0.057358?-1.403620??0.462811
a?????2.180095?-1.820624??0.046273
b????-0.607010?-0.123721??1.375773
>>>?#獲取a?b兩行,?A?B兩列數(shù)據(jù)
>>>?df.loc[['a',?'b'],?['A',?'B']]
cols?????????A?????????B
a?????2.180095?-1.820624
b????-0.607010?-0.123721
>>>?#獲取a行,?A列元素
>>>?df.at['a',?'A']
2.180094959110999
通過位置選擇器.iloc和.iat,可按照索引位置訪問數(shù)據(jù)。
之前 Pandas 還可以通過ix和reindex函數(shù)訪問數(shù)據(jù),現(xiàn)在都不推薦使用了。
還可以通過布爾索引篩選滿足條件的數(shù)據(jù)
>>>?#獲取A列大于0的行
>>>?df[df.A?>?0]
cols?????????A?????????B?????????C
a?????2.180095?-1.820624??0.046273
初次學(xué)習(xí)布爾索引可能會覺得難以理解,這里來拆解一下,幫助大家理解。
第一步,看df.A > 0的返回值
mask?=?df.A?>?0
mask
>>>?mask
e????False
d????False
a?????True
b????False
Name:?A,?dtype:?bool
df.A > 0返回的是Series一維數(shù)組,索引跟df一樣,取值bool類型。
第二步,將mask應(yīng)用在df上
>>>?df[mask]
cols?????????A?????????B?????????C
a?????2.180095?-1.820624??0.046273
因?yàn)?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">mask是bool類型,True表示保留該行索引,False表示丟棄該行索引。這里只有索引e取值為True,所以只保留e行。
布爾索引中通過|、&、~連接不同的判斷條件,分別代表與、或、非。

3.4 其他函數(shù)
Pandas 中還定義了很多有用的函數(shù),可以靈活地訪問、獲取數(shù)據(jù)。如:isin()、where()、query()。

3.5 多級索引
之前我們接觸的DataFrame行列索引只有一層,Pandas 還支持多級(多層)索引。
多層索引并不難理解,將單層索引的某個值替換成元組,就是多層索引,用法上二者有相似之處。
3.5.1 索引創(chuàng)建與獲取
一般我們可以通過pd.MultiIndex創(chuàng)建多級索引
>>>?#?通過元組列表創(chuàng)建2級行索引
>>>?index?=?pd.MultiIndex.from_tuples([('bar',?'one'),('bar',?'two'),('baz',?'one'),('baz',?'two')],?names=['first',?'second'])
>>>?df?=?pd.DataFrame(np.random.randn(4,?2),?index=index)
>>>?df
?????????????????????0?????????1
first?second????????????????????
bar???one?????0.813204??0.817983
??????two????-0.304902??0.396040
baz???one????-0.634707??0.665182
??????two?????0.246232?-0.609914

3.5.2 多級索引訪問
同樣可以通過[]、.loc等方式訪問多級索引。
>>>?df
?????????????????????0?????????1
first?second????????????????????
bar???one?????0.813204??0.817983
??????two????-0.304902??0.396040
baz???one????-0.634707??0.665182
??????two?????0.246232?-0.609914
>>>?#?獲取從('bar',?'one')到('bar',?'two')的行,0列
>>>?df.loc[('bar','one'):('bar',?'two'),?0]
first??second
bar????one???????0.813204
???????two??????-0.304902
Name:?0,?dtype:?float64
>>>?#?獲取第0層行索引,bar到baz之間所有行
>>>?df.loc[(slice('bar',?'baz'),?slice(None)),?:]
?????????????????????0?????????1
first?second????????????????????
bar???one?????0.813204??0.817983
??????two????-0.304902??0.396040
baz???one????-0.634707??0.665182
??????two?????0.246232?-0.609914

3.5.3 其他函數(shù)

4 遍歷
除了上面的訪問方式,Pandas 還支持遍歷的方式訪問 Series 或 DataFrame中的數(shù)據(jù)。
4.1 循環(huán)方式
可以使用for循環(huán)遍歷DataFrame每行、每列。
df.iterrows()函數(shù)可遍歷行,df.items()函數(shù)可遍歷列
>>>?df[:2]
?????????????????????0?????????1
first?second????????????????????
bar???one?????0.813204??0.817983
??????two????-0.304902??0.396040
>>>?for?index,?row?in?df[:2].iterrows():
...???print(index)
...???print(row)
...?
('bar',?'one')
0????0.813204
1????0.817983
Name:?(bar,?one),?dtype:?float64
('bar',?'two')
0???-0.304902
1????0.396040
Name:?(bar,?two),?dtype:?float64
4.2 函數(shù)方式
df.apply()函數(shù)遍歷行或列,并接收函數(shù)作為參數(shù),用來對行、列處理。
df.applymap() 函數(shù)遍歷所有元素,接收函數(shù)作為參數(shù),用來處理處理。

5 運(yùn)算
只能獲取數(shù)據(jù)還不夠,我們還需能對數(shù)據(jù)做計(jì)算。
5.1 二元運(yùn)算
可以用運(yùn)算法,也可以用函數(shù)對DataFrame做四則運(yùn)算。
以加法為例
>>>?df
???a??b
0??1??3
1??2??4
>>>?df2
???a??b
0??5??7
1??6??8
>>>?#?df?+?1,等價(jià)于?df.add(1)
>>>?df?+?1
???a??b
0??2??4
1??3??5
>>>?#?df?+?df2,等價(jià)于?df.add(df2)
>>>?df+df2
???a???b
0??6??10
1??8??12
這里的運(yùn)算返回新的DataFrame,而不會改變df中的值。
另外,Pandas 還支持反向運(yùn)算法。如:df.rdiv(df2) 等價(jià)于 df2 / df。

5.2 計(jì)算工具
Pandas 還提供了很多好用的計(jì)算工具,幫助我們快速完成計(jì)算。
以df.cov()函數(shù)為例,調(diào)用該函數(shù),可以返回列與列之間的協(xié)方差。
>>>?df.cov()
?????a????b
a??0.5??0.5
b??0.5??0.5

6 分組統(tǒng)計(jì)
分組統(tǒng)計(jì)是 Pandas 數(shù)據(jù)分析最常用的功能。
6.1 分組統(tǒng)計(jì)
Pandas 可以對 DataFrame按照行、按列、行+列的方式分組。
>>>?df
????a??b
0??a1??1
1??a2??2
2??a1??3
>>>?#?按a列分組
>>>?df.groupby('a')
0x7fafbe6f4a30>
>>>?#?按第0層行索引分組
>>>?df.groupby(level=0)
0x7fafbe6f49a0>
>>>?#?按第0層行索引和a列,分組計(jì)數(shù)
0x7fafbe70bac0>

6.2 分組遍歷
分完組后,我們可以獲取單個分組結(jié)果,或者遍歷所有分組。
>>>?for?name,?group?in?df.groupby('a'):
...?????print(group)
...?????print(name)
...?
????a??b
0??a1??1
2??a1??3
a1
????a??b
1??a2??2
a2
name是a列取值,group是每個分組DataFrame。

6.3 分組聚合
分組的最終目的就是為了對每個分組的數(shù)據(jù)做聚合統(tǒng)計(jì)。
Pandas 提供了一些內(nèi)置的聚合函數(shù),下面列舉一些常見的

同時(shí),也支持 Numpy 的聚合函數(shù)和自定義聚合函數(shù)。
可以指定1個聚合函數(shù),也可以指定多個聚合函數(shù),甚至還可以對不同列指定不同的聚合函數(shù)。
>>>?df
????a??b??c
0??a1??1??4
1??a2??2??5
2??a1??3??6
>>>?#?對a列分組求和
>>>?df.groupby("a").sum()
????b???c
a????????
a1??4??10
a2??2???5
>>>?#?對a列分組,對b?c列求和、求均值
>>>?df.groupby("a").agg([np.sum,?np.mean])
?????b????????c?????
???sum?mean?sum?mean
a???????????????????
a1???4??2.0??10??5.0
a2???2??2.0???5??5.0
>>>?#?對a列分組,b列求和,c列用自定函數(shù)求方差
>>>?df.groupby("a").agg({"b":?np.sum,?"c":?lambda?x:?np.std(x,?ddof=1)})
????b?????????c
a??????????????
a1??4??1.414214
a2??2???????NaN

7. 重塑和透視
之前無論對DataFrame做什么操作,都不會改變它的結(jié)構(gòu)。這部分我們會改變DataFrame的形狀,即:改變現(xiàn)有的行列結(jié)構(gòu)。
pd.stack()將列索引變成行索引。

pd.unstack()是pd.stack()的反向操作

pd.melt(),保留某幾列,將剩下的列“融化”掉,生成兩個新列,一個存放被“融化”的列名,另一個存放被“融化”的列值。

pd.pivot()類似 Excel 中的透視表,任意指定新的行列值。

pd.pivot_table()提供了透視表的聚合功能。

8. 合并
Pandas 提供了一些函數(shù),可以將多個DataFrame合并,既可以按行和并也可以按列合并。
這些函數(shù)的功能類似 SQL 中的union和join。
以pd.concat()為例,按列合并
pd.concat([df1,?df2,?df3])

按行和并
pd.concat([df1,?df4],?axis=1)


9. 可視化
Pandas 集成了 Matplotlib ,可以幫助我們快速作圖。
ts?=?pd.Series(np.random.randn(1000),?index=pd.date_range("1/1/2000",?periods=1000))
df?=?pd.DataFrame(np.random.randn(1000,?4),?index=ts.index,?columns=list("ABCD"))
df?=?df.cumsum()
plt.figure()
df.plot()


10. 特殊數(shù)據(jù)類型
Padans 對某些特殊數(shù)據(jù)類型提供一些函數(shù),方便數(shù)據(jù)處理。
對字符串類型的數(shù)據(jù),提供字符串分割、拼接、提取等函數(shù)。
對缺失值,提供填充、插值和刪除等函數(shù)
對日期類型,提供日期加減、日期間隔等函數(shù)。

至此,我們通過 10 個小節(jié)把 Pandas 常用的功能講完了。
本文完整代碼可以關(guān)注我的另一個公眾號【簡說編程】,回復(fù):代碼?獲取。(注意??,看清獲取方式哈)。
點(diǎn)贊、在看、轉(zhuǎn)發(fā),感謝支持,我們下期見~
近期文章:
【干貨】視頻教學(xué)|搞定Python編程學(xué)習(xí)環(huán)境+工具
【干貨+贈書】手寫一個 Python "病毒"
如何找到我:
