pandas
Pandas是線上服務(wù)類(lèi)型铆帽,數(shù)據(jù)分析和數(shù)據(jù)處理(在機(jī)器學(xué)習(xí)中數(shù)據(jù)處理)
數(shù)據(jù)分析三劍客:
numpy數(shù)值計(jì)算
pandas數(shù)據(jù)分析
matplotlib+seaborn數(shù)據(jù)可視化
pandas中有兩組數(shù)據(jù)類(lèi)型州藕,一個(gè)是Series,另一個(gè)是DataFrame送丰。
importpandasaspd
1、 Series
Series是一種類(lèi)似與一維數(shù)組的對(duì)象毫捣,由下面兩個(gè)部分組成:
values:一組數(shù)據(jù)(ndarray類(lèi)型)
key:相關(guān)的數(shù)據(jù)索引標(biāo)簽
可理解為帶索引的一維數(shù)組坪哄。
1.1 Series屬性
index—— 索引項(xiàng)
values——索引值,numpy.ndarray類(lèi)型
1.2 創(chuàng)建Series
1.2.1 通過(guò)已有數(shù)據(jù)創(chuàng)建
指定內(nèi)容挠轴,默認(rèn)索引
pd.Series(np.arange(5))
#輸出
00
11
22
33
44
指定索引:通過(guò)設(shè)置index參數(shù)指定索引
pd.Series([10,12,23,45,23],index=['a','b','c','d','e'])
#輸出
a10
b12
c23
d45
e23
dtype:?int64
1.2.2 通過(guò)字典創(chuàng)建
pd.Series({'a':3,'b':4,'c':5})
#輸出
a3
b4
c5
dtype:?int64
name參數(shù)
pd.Series(data=[1,2,3,4],index=list('abcd'),name='demo')
#輸出
a1
b2
c3
d4
Name:?demo,?dtype:?int64
copy屬性:類(lèi)似于Python中的deepcopy
arr=?np.array([1,2,3,4,5])
ser=?pd.Series(data=arr)
##這樣當(dāng)我們修改arr中數(shù)據(jù)時(shí)传睹,ser中的數(shù)據(jù)也會(huì)跟著改變
ser=?pd.Series(data=arr,copy=True)
##此時(shí)再修改arr中的數(shù)據(jù)時(shí)岸晦,ser中的數(shù)據(jù)不會(huì)再改變欧啤。
1.3 Series的索引和切片
可以使用中括號(hào)取單個(gè)索引(此時(shí)返回的是元素類(lèi)型),
或者中括號(hào)里一個(gè)列表取多個(gè)索引(此時(shí)返回的仍然是一個(gè)Series類(lèi)型)启上。
分為顯示索引和隱式索引:
1.3.1 常規(guī)索引的方式
s=?pd.Series({'a':3,'b':4,'c':5})
s['a':'b'],s[:1],s.c
#輸出
a3
b4
dtype:?int64
###############
a3
dtype:?int64
###############
5
P纤怼!冈在!注意5够邸!纫谅!利用自定義的index和自帶索引切片時(shí)的范圍閉合問(wèn)題哦!
這里先介紹:
索引的類(lèi)型有兩種:
枚舉型索引:特征索引是連續(xù)數(shù)值
關(guān)聯(lián)型索引:特征索引都是離散字符類(lèi)型
1.3.2 顯式索引
使用index中的關(guān)聯(lián)類(lèi)型作為索引值
使用.loc[](推薦)
可以理解為pandas是ndarray的升級(jí)版,但是Series也可是dict的升級(jí)版
注意溅固,此時(shí)是閉區(qū)間
s.loc['a':'c'],s['a':'c']
#輸出
b4
c5
dtype:?int64,?
a3
b4
c5
dtype:?int64
?
1.3.3 隱式索引
使用整數(shù)作為索引值
使用.iloc[](推薦)
注意付秕,此時(shí)是半閉區(qū)間
s.iloc[:1]
#輸出
a3
dtype:?int64
自然而然切片也有常規(guī)切片、顯式切片和隱式切片
#常規(guī)
s[1:-1]
s['a':'d']
#顯式
s.loc['a':'c']
#隱式
s.iloc[0:-1]
1.4 Series的基本概念
可以把Series看成一個(gè)定長(zhǎng)的有序字典
可以通過(guò)ndim,shape侍郭,size询吴,index,values等得到series的屬性
ser.index獲得索引
ser.values獲得值
ser.keys()?獲得索引
可以通過(guò)head(),tail()快速查看Series對(duì)象的樣式
共同都有一個(gè)參數(shù)n,默認(rèn)值為5
S=?pd.Series(data=np.random.randint(0,10,10000))
#Linux 當(dāng)中 head -n xxx.txt 讀取前幾行
S.head(n=3)
#輸出
04
19
28
dtype:?int32
當(dāng)索引沒(méi)有對(duì)應(yīng)的值時(shí)亮元,可能出現(xiàn)缺失數(shù)據(jù)顯示NaN的情況汰寓。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ||
可以使用pd.isnull(),pd.notnull()苹粟,或自帶isnull(),notnull()函數(shù)檢測(cè)缺失數(shù)據(jù)。
S=pd.Series([None,1,2,3])
#mysql where demo is not null
index=?S.notnull()
index
#輸出
0False
1?True
2?True
3?True
dtype:?bool
2跃闹、DataFrame
DataFrame是一個(gè)【表格型】的數(shù)據(jù)結(jié)構(gòu)嵌削,可以看做是【由Series組成的字典】(共用同一個(gè)索引)毛好。DataFrame由按一定順序排列的多列數(shù)據(jù)組成。設(shè)計(jì)初衷是將Series的使用場(chǎng)景從一維拓展到多維苛秕。DataFrame既有行索引肌访,也有列索引。
行索引:index
列索引:columns
值:values(numpy的二維數(shù)組)
我們的 訓(xùn)練集(一些二維的數(shù)據(jù))都是二維的艇劫,那么Series滿足不了這個(gè)條件,xy軸吼驶,軸上的一點(diǎn)(0,0)店煞。
2.1 DataFrame的創(chuàng)建
2.2 DataFrame的屬性和方法
pd.DataFrame(array, index,columns)
因?yàn)閜andas是集成了numpy的蟹演,屬性方面用法和功能都類(lèi)似
屬性:
shape(形狀)
values(除去行列索引后的值)
T(行列轉(zhuǎn)置)
index(行索引)
columns(列索引)
方法:
head(size)——顯示前size行數(shù)據(jù),默認(rèn)前五行
tail(size)——顯示后size行數(shù)據(jù)顷蟀,默認(rèn)后五行
2.3 設(shè)置索引
修改行列索引值?
只能整體修改酒请,不能修改單獨(dú)某一項(xiàng)
重設(shè)索引
reset_index(drop=False)
#重置索引值,默認(rèn)drop為False鸣个,不刪除原索引羞反,將其單獨(dú)立為一列,在此基礎(chǔ)上將索引重置
設(shè)置新的索引 `set_index(keys, drop=True)`
keys:列索引名稱(chēng)或者列索引名稱(chēng)的列表;
drop: boolean囤萤,默認(rèn)為T(mén)rue昼窗,當(dāng)做新的索引,刪除原來(lái)的列
#設(shè)置多個(gè)索引
df=?pd.DataFrame({'month':[1,4,7,10],'year':[2012,2014,2013,2016],'sale':[55,40,84,31]})
?
df.set_index(['month'])
df.set_index(['year','month'])?#此設(shè)置可以同時(shí)設(shè)置多層次索引如['year','month'],設(shè)置之后此時(shí)返回的index是MultiIndex類(lèi)型
2.4 MultiIndex
多級(jí)或分層索引對(duì)象,可用于存放三維數(shù)據(jù)
index屬性
names:levels的名稱(chēng)
levels:每個(gè)level的元組值
new_df = df.set_index(['year', 'month'])
new_df.index.names
##輸出
FrozenList(['year', 'month'])
new_df.index.levels
#輸出
FrozenList([[2012, 2013, 2014, 2016], [1, 4, 7, 10]])
索引的堆(stack)
stack() 把列索引轉(zhuǎn)變?yōu)樾兴饕?/p>
unstack() 把行索引轉(zhuǎn)變?yōu)榱兴饕?/p>
2.5 DataFrame的索引
2.5.1 對(duì)列進(jìn)行索引
通過(guò)類(lèi)似字典的方式
通過(guò)屬性的方式
可以將DataFrame的列獲取為一個(gè)Series涛舍。返回的Series擁有原DataFrame相同的索引澄惊,且name屬性也已經(jīng)設(shè)置好了,就是相應(yīng)的列名做盅。
DataFrame的中括號(hào)缤削,只能獲取列索引。
2.5.2 對(duì)行進(jìn)行索引
使用.loc[]加index來(lái)進(jìn)行行索引
使用.iloc[]加整數(shù)來(lái)進(jìn)行行索引
data = pd.DataFrame({'A':[12,23,67,89],'B':[67,76,45,89],'c':[90,89,45,78]},index=['語(yǔ)文','數(shù)學(xué)','英語(yǔ)','自然'])
data
#輸出
? ? ? A ? B ? c
語(yǔ)文 12 67 90
數(shù)學(xué) 23 76 89
英語(yǔ) 67 45 45
自然 89 89 78
data.loc['語(yǔ)文']
#輸出
A? ? 12
B? ? 67
c? ? 90
Name: 語(yǔ)文, dtype: int64
data.iloc[0]
#輸出
A? ? 12
B? ? 67
c? ? 90
Name: 語(yǔ)文, dtype: int64
2.5.3 對(duì)元素索引的方法
使用列索引
使用行索引(iloc[3,1]相當(dāng)于兩個(gè)參數(shù);iloc[[3,3]] 里面的[3,3]看做一個(gè)參數(shù))
使用values屬性(二維numpy數(shù)組)
data.iloc[0,1]? #相當(dāng)于第0行的第二個(gè)元素
data.iloc[[0,0]]? #可以同時(shí)選取多行數(shù)據(jù)吹榴,這里就是選取兩次第0行的數(shù)據(jù)
#輸出
? ? ? A ? B c
語(yǔ)文 12 67 90
語(yǔ)文 12 67 90
使用行索引loc切片和使用隱式iloc思維方式和二維array一致亭敢,故意不寫(xiě)清楚,如果已經(jīng)忘記图筹,正好一起把二維array切片回顧一下吧帅刀!
2.6 數(shù)據(jù)的增刪改查CURD操作
2.6.1 插入
2.6.1 .1 增加一行
data.loc['政治']=[67,38,95]
#
? ? A ? B ? c
語(yǔ)文 12 67 90
數(shù)學(xué) 23 76 89
英語(yǔ) 67 45 45
自然 89 89 78
政治 67 38 95
2.6.1.2 增加一列
在增加時(shí),增加一列? 一列中有多少個(gè)元素是不知道的
data.loc[:,'D']=np.nan
data
#輸出
? ? A ? B ? c ? D
語(yǔ)文 12 67 90 NaN
數(shù)學(xué) 23 76 89 NaN
英語(yǔ) 67 45 45 NaN
自然 89 89 78 NaN
政治 67 38 95 NaN
2.6.2 修改
欲修改先查詢
col_index = data.A == 67
col_index
#輸出匹配結(jié)果是布爾值類(lèi)型
語(yǔ)文? ? False
數(shù)學(xué)? ? False
英語(yǔ)? ? True
自然? ? False
政治? ? True
Name: A, dtype: bool
根據(jù)查詢到的index結(jié)果再去修改
#因?yàn)槠ヅ浣Y(jié)果有兩個(gè)远剩,而只想修改第二個(gè)
res = data[col_index].iloc[1]
res.D = 90
#被拷貝的新數(shù)據(jù)扣溺,在單獨(dú)的內(nèi)存空間中,把修改好的數(shù)據(jù)覆蓋
data.loc[col_index].iloc[1]=res
另外一種方法,常用點(diǎn):
new_data = user.query("username=='李晶'")
new_data.age = 50
user.loc[new_data.index] = new_data
user
#輸出
username sex addr seet age
東 70 77 81 40 NaN
南 89 5 8 32 NaN
西 60 37 72 18 NaN
北 78 17 54 44 NaN
中 8 62 84 55 NaN
東邪 李晶 ? 紅浪漫 1123 50.0
2.6.3 查
見(jiàn)上
2.6.4 刪除
labels參數(shù)代表要被刪除的索引名稱(chēng)
axis=0參數(shù)代表是刪除行還是列
inplace 發(fā)生變化的數(shù)據(jù)把原數(shù)據(jù)替換
#刪除列
user.drop(labels='age',axis=1,inplace=True)
#刪除行
user.drop(labels='東邪',axis=0,inplace=True)
2.7 丟失數(shù)據(jù)的處理
在python中有兩種
np.nan
None
pandas 中對(duì)于空的操作
isnull():#把每一列中True和False求和以便統(tǒng)計(jì)缺失數(shù)據(jù)數(shù)目
notnull()
dropna() #過(guò)濾空值 :
刪除行還是列:
在數(shù)據(jù)分析中我們刪除行
在探索性數(shù)據(jù)分析中瓜晤,如果行缺失的比較多那就刪除行锥余,如果列缺失的比較多那就刪除列
fillna()? 不好玩,代碼想寫(xiě)自己聯(lián)系吧
填充空值
1.指定填充
2.前后填充,不能使用value=None
2.8 聚合操作
【注意】
需要指定axis
【小技巧】和unstack()相反痢掠,聚合的時(shí)候驱犹,axis等于哪一個(gè)嘲恍,哪一個(gè)就保留。
所謂的聚合操作:平均數(shù)雄驹,標(biāo)準(zhǔn)方差佃牛,最大值,最小值……
首先你要理解各個(gè)函數(shù)的數(shù)學(xué)和統(tǒng)計(jì)學(xué)意義哦医舆!就很容易了!
3 俘侠、pandas的拼接操作
pandas主要作用就是對(duì)數(shù)據(jù)進(jìn)行一個(gè)統(tǒng)計(jì) pandas 也有類(lèi)似于 left join 的操作 、select union select(聯(lián)合查詢)蔬将。
相當(dāng)于Mysql中的聯(lián)表查詢爷速,聯(lián)合查詢 的操作:pd.concat(), pd.append() pd.merge()
3.1 使用Pandas連接MySQL獲取數(shù)據(jù)
importpymysql
fromsqlalchemyimportcreate_engine
conn=?create_engine("mysql+pymysql://root:Chenjiajian1225@wst.life:3306/py1907?charset=utf8")
sql1=?"select * from usr_info;"
demo=?pd.read_sql(sql1,conn)
demo.head()
#輸出
idnamegenderpassword
01tommale123456
12bobmale123456
23lucyfemale123456
34lilyfemale123456
45alexmale123456
uid=?demo.query("gender == 'female'").id
uid=?uid.tolist()
uid=?tuple(uid)
sql2=?f"select * from usr_info where id in {uid};"
female_info=?pd.read_sql(sql2,conn)
female_info
#輸出
?
idnamegenderpassword
03lucyfemale123456
14lilyfemale123456
29evafemale123456
310ellafemale123456
?
# 數(shù)據(jù)的操作就是DataFrame數(shù)據(jù)類(lèi)型的操作
3.2? 使用pd.concat()級(jí)聯(lián)
pandas使用pd.concat函數(shù),與np.concatenate函數(shù)類(lèi)似娃胆,只是多了一些參數(shù):
pd.concat(objs,?axis=0,?join='outer',?join_axes=None,?ignore_index=False,keys=None,?levels=None,?names=None,?verify_integrity=False,copy=True)
3.2.1 簡(jiǎn)單級(jí)聯(lián)
和np.concatenate一樣遍希,優(yōu)先增加行數(shù)(默認(rèn)axis=0)
pd.concat([demo,female_info],join='outer')
#輸出
idnamegenderpassword
01tommale123456
12bobmale123456
23lucyfemale123456
34lilyfemale123456
45alexmale123456
56johnmale123456
67jackmale123456
78tomasmale123456
89evafemale123456
910ellafemale123456
1011nickmale123456
03lucyfemale123456
14lilyfemale123456
29evafemale123456
310ellafemale123456
####看到?jīng)],index可以重復(fù)里烦。
pd.concat((demo,female_info),axis=1,join='outer')
#輸出
idnamegenderpasswordidnamegenderpassword
01tommale1234563.0lucyfemale123456
12bobmale1234564.0lilyfemale123456
23lucyfemale1234569.0evafemale123456
34lilyfemale12345610.0ellafemale123456
45alexmale123456NaNNaNNaNNaN
56johnmale123456NaNNaNNaNNaN
67jackmale123456NaNNaNNaNNaN
78tomasmale123456NaNNaNNaNNaN
89evafemale123456NaNNaNNaNNaN
910ellafemale123456NaNNaNNaNNaN
1011nickmale123456NaNNaNNaNNaN
可以通過(guò)設(shè)置axis來(lái)改變級(jí)聯(lián)方向
注意index在級(jí)聯(lián)時(shí)可以重復(fù)
也可以選擇忽略ignore_index凿蒜,重新索引
或者使用多層索引 keys
3.2.2 不匹配級(jí)聯(lián)
不匹配指的是級(jí)聯(lián)的維度的索引不一致。例如縱向級(jí)聯(lián)時(shí)列索引不一致胁黑,橫向級(jí)聯(lián)時(shí)行索引不一致
有2種連接方式:
外連接:補(bǔ)NaN(默認(rèn)模式)outer
內(nèi)連接:只連接匹配的項(xiàng)? ? ? ? inner
使用concat()模擬聯(lián)合查詢
(select*?fromuser_info?limit10)?union(selectuserid,orderid,paidtime?fromorder_info?limit10) ;
要求聯(lián)合查詢的字段數(shù)量要相同
數(shù)據(jù)類(lèi)型可以不相同
兩邊的字段名稱(chēng)可以不相同
字段名稱(chēng)顯示問(wèn)題以左邊的表為基準(zhǔn)
那在pandas中废封,是不是得先讓用于union的數(shù)據(jù)符合條件,即抽提出要用于聯(lián)合查詢的數(shù)據(jù)列丧蘸,把列名稱(chēng)修改成一致的漂洋,之后聯(lián)合在一起。
3.2.3 使用append()函數(shù)添加
由于在后面級(jí)聯(lián)的使用非常普遍力喷,因此有一個(gè)函數(shù)append專(zhuān)門(mén)用于在后面添加刽漂,append 和 concat 相似,默認(rèn)也是上下拼接弟孟。
user_info.append(union_right,ignore_index=True)
3.3 使用pd.merge()合并
pd.merge(left,?right,?how='inner',?on=None,?left_on=None,?right_on=None,?left_index=False,?right_index=False,?sort=False,?suffixes=('_x',?'_y'),?copy=True,?indicator=False,?validate=None)
on : label or list.Column or index level names to join on. These must be found in both DataFrames.
merge與concat的區(qū)別在于:
merge需要依據(jù)某一共同的行或列來(lái)進(jìn)行合并
使用pd.merge()合并時(shí)贝咙,會(huì)自動(dòng)根據(jù)兩者相同column名稱(chēng)的那一列,作為key來(lái)進(jìn)行合并拂募。
默認(rèn)也是內(nèi)連接:how : {'left', 'right', 'outer', 'inner'}, default 'inner'庭猩。
inner 內(nèi)連接,兩邊的關(guān)聯(lián)字段對(duì)等則返回陈症,否則過(guò)濾
left 左外連接蔼水,以左表中的關(guān)聯(lián)字段為主,如果右邊中的字段不匹配录肯,則填補(bǔ)Null
right 右外連接趴腋,以右表中的關(guān)聯(lián)字段為主,如果左邊中的字段不匹配,則填補(bǔ)Null
outer 全外連接,如果兩邊的數(shù)據(jù)不對(duì)等优炬,則兩邊全部填補(bǔ)Null
注意每一列元素的順序不要求一致
將id設(shè)置為行號(hào)
set_index()
data.set_index(keys='userid',inplace=True)
重新設(shè)置行索引
data.reset_index(inplace=True)
指定關(guān)聯(lián)列
left_on=None
right_on=None
使用left_on和right_on指定左右兩邊的列作為key疏叨,當(dāng)左右兩邊的key都不相同時(shí)使用
關(guān)聯(lián)列是行索引
user_info.set_index('uid',inplace=True)
order_info.set_index('userid',inplace=True)
pd.merge(user_info,order_info,left_index=True,right_index=True,how='outer')
內(nèi)合并與外合并
內(nèi)合并:只保留兩者都有的key(默認(rèn)模式)
外合并 how='outer':補(bǔ)NaN
左合并、右合并:how='left'穿剖,how='right',
列沖突的解決
當(dāng)列沖突時(shí)卦溢,即有多個(gè)列名稱(chēng)相同時(shí)糊余,需要使用on=來(lái)指定哪一個(gè)列作為key,配合suffixes指定沖突列名
可以使用suffixes=自己指定后綴
出現(xiàn)這種狀況的場(chǎng)景:兩張表的字段有大部分是相同的单寂,那你讓merge怎么辦贬芥,它咋知道用哪一列的數(shù)據(jù)進(jìn)行連接呢?
使用suffixes=自己指定后綴宣决,就像是給同名的倆人起別稱(chēng)進(jìn)行標(biāo)識(shí)一樣的蘸劈。
pd.merge(user_info,union_right,left_on='uid',right_on='uid',suffixes=('_user',?'_union'),how='outer')
4、數(shù)據(jù)合并的案例
4.1 為什么取得的數(shù)據(jù)不能直接用尊沸,為什么要進(jìn)行數(shù)據(jù)預(yù)處理呢威沫?
那你做菜可不得洗菜、切菜哦洼专,準(zhǔn)備蔥姜蒜等配料呢棒掠。同樣我們?cè)谀玫綌?shù)據(jù)時(shí),是不能直接用的屁商,要‘因材處理’烟很!
掌握數(shù)據(jù)組成和結(jié)構(gòu):表與表之間的關(guān)系,表頭字段的合法性蜡镶。雾袱。。官还。
根據(jù)表之間的關(guān)系合并數(shù)據(jù):注意保證數(shù)據(jù)完整性用外連接芹橡,當(dāng)然,要根據(jù)實(shí)際要求靈活處理妻枕。
合并數(shù)據(jù)后缺失值的查找僻族、處理。
以上處理完也要記得最后檢查下是否還存在影響數(shù)據(jù)完整性的缺失值的檢查屡谐。
4.2 操作實(shí)例
第一步:
abb=?pd.read_csv('../Lesson_3/state-abbrevs.csv')
abb.head()
pop=?pd.read_csv('../Lesson_3/state-population.csv')
pop.head()
area=?pd.read_csv('../Lesson_3/state-areas.csv')
area.head()
cols=?pop.columns.tolist()
cols[0] =?'state_region'
pop.columns=?cols
pop.head()
第二步:
##兩表合并
abb_pop=pd.merge(abb,pop,left_on='abbreviation',right_on='state_region',how='outer')
##檢查缺失值
abb_pop.isnull().sum()
##刪除冗余數(shù)據(jù)列
abb_pop.drop(labels='abbreviation',axis=1,inplace=True)
abb_pop.isnull().sum()
第三步:
#缺失值的填補(bǔ)
indexs=abb_pop.state.isnull()
filter_data=abb_pop.loc[indexs]
filter_data.state_region.unique()
pr_inds=?abb_pop.query("state_region=='PR'").index
reple=?abb_pop.loc[pr_inds]
reple['state'] =?'Puerto Rico'
abb_pop.loc[pr_inds]=reple
abb_pop.isnull().sum()
usa_inds=?abb_pop.query("state_region=='USA'").index
reple_usa=?abb_pop.loc[usa_inds]
reple_usa['state'] =?'USA'
abb_pop.loc[usa_inds] =?reple_usa
abb_pop.isnull().sum()
第四步:
#合并第三張表
cols=?area.columns.tolist()
cols[1] =?'area'
area.columns=?cols
abb_pop_area=?pd.merge(abb_pop,area,how='outer')
abb_pop_area.head()
abb_pop_area.isnull().sum()
第五步:
#缺失值檢查填補(bǔ)
ins=abb_pop_area.area.isnull()
area_fill=?abb_pop_area.loc[ins]
state_name= [xforxinabb_pop_area.state.unique()?ifx!='USA']
total_area=?0
forxinstate_name:
total_area=?total_area+abb_pop_area.query(f"state=='{x}'").iloc[0].area
area_fill=?abb_pop_area.loc[ins]
area_fill.area=?total_area
abb_pop_area.loc[ins] =area_fill
abb_pop_area.loc[ins]?
abb_pop_area.isnull().sum()
至此述么,數(shù)據(jù)預(yù)處理完成。
數(shù)據(jù)簡(jiǎn)單分析
---分析某一州各個(gè)年份成年與未成年分的比例
Alabama = abb_pop_area.query("state=='Alabama'")
u_pop=Alabama.query("ages =='under18'").population
t_pop = Alabama.query("ages =='total'").population
year = Alabama.year.unique()
a_pop = np.array(t_pop) - np.array(u_pop)
u_rate =np.divide(np.array(u_pop),np.array(t_pop))
a_rate = np.divide(a_pop,np.array(t_pop))
result = pd.DataFrame(np.c_[u_rate,a_rate],columns=['u_rate','a_rate'],index=year)
from matplotlib import pyplot as plt
#堆疊圖()
result.plot(kind='barh',stacked=True,figsize=(10,10))
pandas數(shù)據(jù)處理
1愕掏、刪除重復(fù)數(shù)據(jù)
使用duplicated()函數(shù)檢測(cè)重復(fù)的行度秘,返回元素為布爾類(lèi)型的Series對(duì)象,每個(gè)元素對(duì)應(yīng)一行,如果該行不是第一次出現(xiàn)剑梳,則元素為T(mén)rue唆貌。
使用drop_duplicates()函數(shù)刪除重復(fù)的行。
data.drop_duplicates(inplace=True)
2垢乙、映射
映射的含義:創(chuàng)建一個(gè)映射關(guān)系列表锨咙,把values元素和一個(gè)特定的標(biāo)簽或者字符串 綁定。
需要使用字典:
map = {
? ? 'label1':'value1',
? ? 'label2':'value2',
? ? ...
? ? }
包含三種操作:
replace()函數(shù):替換元素
最重要:map()函數(shù):新建一列追逮,修改一列
rename()函數(shù):替換行索引
``.loc[]``?isprimarilylabelbased,?butmayalsobeusedwithabooleanarray.
2.1 使用replace()函數(shù)酪刀,對(duì)values進(jìn)行替換操作
還經(jīng)常用來(lái)替換NaN元素,當(dāng)然替換是雙向的钮孵,也可以把值替換成控制骂倘,
如果想修改原來(lái)的數(shù)組,記得加上inplace=True
p1= {'math':[90,89,78,90,89],'chinese':[90,89,67,89,80],'english':[90,89,90,90,90]}
p=?pd.DataFrame(data=p1)
p.loc[2:4,'english'] =?np.nan
p.english.iloc[-1]='?'
#輸出
mathchineseenglish
090?9090.0
189?8989.0
278?67NaN
390?89NaN
489?80?
?
填補(bǔ)空值可以用fillna()函數(shù)但是它的功能比較單一
p.fillna(value=0)
#輸出
mathchinese
090?9090
189?8989
278?670
390?890
489?80?
#你看‘巴席?’可沒(méi)辦法被填補(bǔ)历涝,這個(gè)時(shí)候replace()就有用啦!
p.replace('?','不可知',inplace=True),
mathchineseenglish
0909090
1898989
27867NaN
39089NaN
48980不可知
p.replace(to_replace=None,?value=None,?inplace=False,?limit=None,?regex=False,?method='pad')
Docstring:
Replacevaluesgivenin`to_replace`?with`value`.
to_replace:?str,?regex,?list,?dict,?Series,?int,?float,?orNone
Howtofindthevaluesthatwillbereplaced.
#1漾唉、直接寫(xiě)由啥替換成啥
s=?pd.Series([0,?1,?2,?3,?4])
s.replace(0,?5)#將0替換成5
05
11
22
33
44
========================================
df=?pd.DataFrame({'A': [0,?1,?2,?3,?4],
...'B': [5,?6,?7,?8,?9],
...'C': ['a',?'b',?'c',?'d',?'e']})
df.replace(0,?5)
?ABC
055a
116b
227c
338d
449e
?
#2荧库、將好多元素同時(shí)替換
df.replace([0,?1,?2,?3],?4)
?ABC
045a
146b
247c
348d
449e
?
df.replace([0,?1,?2,?3], [4,?3,?2,?1])
?ABC
045a
136b
227c
318d
449e
s.replace([1,?2],?method='bfill')
00
13
23
33
44
#3、字典形式的多個(gè)元素替換
df.replace({0:?10,?1:?100})
?ABC
0?105a
11006b
227c
338d
449e
指定位置的替換
df.replace({'A':?0,?'B':?5},?100)
?ABC
0100100a
116b
227c
338d
449e
df.replace({'A': {0:?100,?4:?400}})
?ABC
01005a
116b
227c
338d
44009e
當(dāng)然也支持正則匹配替換毡证,但是好麻煩电爹,估計(jì)不會(huì)用哦。
2.2 rename()函數(shù):替換索引
p.index=['a','b','c','d','e']
p.rename({'a':'A'})
#輸出
mathchineseenglish
A909090
b898989
c7867NaN
d9089NaN
e8980不可知
函數(shù)參數(shù)詳解:就看看好了料睛,不是很好玩丐箩,掌握一種替換方式就行了。
df=?pd.DataFrame({"A": [1,?2,?3],?"B": [4,?5,?6]})
>>>df.rename(index=str,?columns={"A":?"a",?"B":?"c"})
?ac
014
125
236
?
>>>df.rename(index=str,?columns={"A":?"a",?"C":?"c"})
?aB
014
125
236
?
Usingaxis-styleparameters
?
>>>df.rename(str.lower,?axis='columns')
?ab
014
125
236
?
>>>df.rename({1:?2,?2:?4},?axis='index')
?AB
014
225
436
reindex()
pandas中的reindex方法可以為series和dataframe添加或者刪除索引恤煞。方法:serise.reindex()屎勘、dataframe.reindex()如果新添加的索引沒(méi)有對(duì)應(yīng)的值,則默認(rèn)為nan居扒。如果減少索引概漱,就相當(dāng)于一個(gè)切片操作。
# series reindex
s1=?Series([1,?2,?3,?4],?index=['A',?'B',?'C',?'D'])
print(s1)
'''
A ? 1
B ? 2
C ? 3
D ? 4
dtype: int64
'''
?
?
# 重新指定 index喜喂, 多出來(lái)的index瓤摧,可以使用fill_value 填充
print(s1.reindex(index=['A',?'B',?'C',?'D',?'E'],?fill_value=?10))
'''
A ? ? 1
B ? ? 2
C ? ? 3
D ? ? 4
E ? 10
dtype: int64
'''
s2=?Series(['A',?'B',?'C'],?index= [1,?5,?10])
print(s2)
'''
1 ? ? A
5 ? ? B
10 ? C
dtype: object
'''
?
# 修改索引,
# 將s2的索引增加到15個(gè)
# 如果新增加的索引值不存在玉吁,默認(rèn)為 Nan
print(s2.reindex(index=range(15)))
'''
0 ? ? NaN
1 ? ? ? A
2 ? ? NaN
3 ? ? NaN
4 ? ? NaN
5 ? ? ? B
6 ? ? NaN
7 ? ? NaN
8 ? ? NaN
9 ? ? NaN
10 ? ? C
11 ? NaN
12 ? NaN
13 ? NaN
14 ? NaN
dtype: object
'''
?
# ffill : foreaward fill 向前填充照弥,
# 如果新增加索引的值不存在,那么按照前一個(gè)非nan的值填充進(jìn)去
print(s2.reindex(index=range(15),?method='ffill'))
'''
0 ? ? NaN
1 ? ? ? A
2 ? ? ? A
3 ? ? ? A
4 ? ? ? A
5 ? ? ? B
6 ? ? ? B
7 ? ? ? B
8 ? ? ? B
9 ? ? ? B
10 ? ? C
11 ? ? C
12 ? ? C
13 ? ? C
14 ? ? C
dtype: object
'''
# reindex dataframe
df1=?DataFrame(np.random.rand(25).reshape([5,?5]),?index=['A',?'B',?'D',?'E',?'F'],?columns=['c1',?'c2',?'c3',?'c4',?'c5'])
print(df1)
'''
? ? ? ? c1 ? ? ? c2 ? ? ? c3 ? ? ? c4 ? ? ? c5
A 0.700437 0.844187 0.676514 0.727858 0.951458
B 0.012703 0.413588 0.048813 0.099929 0.508066
D 0.200248 0.744154 0.192892 0.700845 0.293228
E 0.774479 0.005109 0.112858 0.110954 0.247668
F 0.023236 0.727321 0.340035 0.197503 0.909180
'''
?
# 為 dataframe 添加一個(gè)新的索引
# 可以看到 自動(dòng) 擴(kuò)充為 nan
print(df1.reindex(index=['A',?'B',?'C',?'D',?'E',?'F']))
''' 自動(dòng)填充為 nan
? ? ? ? c1 ? ? ? c2 ? ? ? c3 ? ? ? c4 ? ? ? c5
A 0.700437 0.844187 0.676514 0.727858 0.951458
B 0.012703 0.413588 0.048813 0.099929 0.508066
C ? ? ? NaN ? ? ? NaN ? ? ? NaN ? ? ? NaN ? ? ? NaN
D 0.200248 0.744154 0.192892 0.700845 0.293228
E 0.774479 0.005109 0.112858 0.110954 0.247668
F 0.023236 0.727321 0.340035 0.197503 0.909180
'''
?
# 擴(kuò)充列进副, 也是一樣的
print(df1.reindex(columns=['c1',?'c2',?'c3',?'c4',?'c5',?'c6']))
'''
? ? ? ? c1 ? ? ? c2 ? ? ? c3 ? ? ? c4 ? ? ? c5 c6
A 0.700437 0.844187 0.676514 0.727858 0.951458 NaN
B 0.012703 0.413588 0.048813 0.099929 0.508066 NaN
D 0.200248 0.744154 0.192892 0.700845 0.293228 NaN
E 0.774479 0.005109 0.112858 0.110954 0.247668 NaN
F 0.023236 0.727321 0.340035 0.197503 0.909180 NaN
'''
?
# 減小 index
print(s1.reindex(['A',?'B']))
''' 相當(dāng)于一個(gè)切割效果
A ? 1
B ? 2
dtype: int64
'''
?
print(df1.reindex(index=['A',?'B']))
''' 同樣是一個(gè)切片的效果
? ? ? ? c1 ? ? ? c2 ? ? ? c3 ? ? ? c4 ? ? ? c5
A 0.601977 0.619927 0.251234 0.305101 0.491200
B 0.244261 0.734863 0.569936 0.889996 0.017936
'''
?
# 對(duì)于一個(gè) serie 來(lái)說(shuō)这揣,可以使用 drop,來(lái)丟掉某些 index
print(s1.drop('A'))
''' 就只剩下 三個(gè)了
B ? 2
C ? 3
D ? 4
dtype: int64
'''
?
# dataframe drop(A) 直接去掉一行
print(df1.drop('A',?axis=0))
''' axis 默認(rèn) 是 行
? ? ? ? c1 ? ? ? c2 ? ? ? c3 ? ? ? c4 ? ? ? c5
B 0.571883 0.254364 0.530883 0.295224 0.352663
D 0.858452 0.379495 0.593284 0.786078 0.949718
E 0.556276 0.643187 0.808664 0.289422 0.501041
F 0.737993 0.286072 0.332714 0.873371 0.421615
'''
?
print(df1.drop('c1',?axis=1))
''' 將 c1 的列 去掉
? ? ? ? c2 ? ? ? c3 ? ? ? c4 ? ? ? c5
A 0.326681 0.247832 0.601982 0.145905
B 0.373961 0.393819 0.439284 0.926706
D 0.558490 0.617851 0.461280 0.373102
E 0.030434 0.566498 0.383103 0.739243
F 0.982220 0.989826 0.957863 0.411514
'''
2.3? map()函數(shù):新建一列
使用map()函數(shù),由已有的列生成一個(gè)新列
適合處理某一單獨(dú)的列,支持Series類(lèi)型
注意:map函數(shù)的參數(shù)支持function和dict
function在定義的時(shí)候给赞,必須要寫(xiě)一個(gè)形參,形參會(huì)代表一列中每一個(gè)元素(map函數(shù)會(huì)自動(dòng)遍歷)机打。
#映射修改
data=?pd.read_excel('銷(xiāo)售記錄.xlsx')
demo=?data.copy()
#把下單的日期只提取月份
defget_m(item):
returnstr(item).split()[0].split('-')[1]
#demo是一個(gè)dataframe
demo.loc[:,'下單日期'] =?demo.loc[:,'下單日期'].map(get_m)
#映射類(lèi)型替換
#昨天繪制散布圖出現(xiàn)了一個(gè)問(wèn)題,鳶尾花數(shù)據(jù)的類(lèi)別值是str類(lèi)型片迅,散布圖不支持
#.astype('category').cat.codes
importseabornassns
iris=?sns.load_dataset('iris')
#['setosa', 'versicolor', 'virginica'] => [0,1,2]
iris.species.unique()
#1.字典替換方式 {'setosa':0, 'versicolor':1, 'virginica':2} 比較固定
#加入類(lèi)別的數(shù)量是動(dòng)態(tài)的
#2.使用函數(shù)自動(dòng)識(shí)別
#設(shè)置全局變量,獲取當(dāng)前的類(lèi)別數(shù)量
cls=?iris.species.unique()
?
defstr2num(item):
foriinnp.arange(cls.shape[0]):
ifitem==?cls[i]:
returni
iris['lables']=iris.species.map(str2num)
iris
sepal_lengthsepal_widthpetal_lengthpetal_widthspecieslables
05.13.51.40.2setosa0
14.93.01.40.2setosa0
24.73.21.30.2setosa0
34.63.11.50.2setosa0
45.03.61.40.2setosa0
55.43.91.70.4setosa0
64.63.41.40.3setosa0
2.4 transform()残邀、apply()、agg()
map()類(lèi)似值只能是一個(gè)function
3柑蛇、異常值檢測(cè)
使用describe()函數(shù)查看每一列的描述性統(tǒng)計(jì)量
iris.iloc[:,:-1].describe()
#輸出各列數(shù)據(jù)的基本狀況
sepal_lengthsepal_widthpetal_lengthpetal_width
count150.000000150.000000150.000000150.000000
mean5.8433333.0573333.7580001.199333
std0.8280660.4358661.7652980.762238
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
?
pandas中.isnull().any()含義
python pandas判斷缺失值一般采用 isnull()罐旗,然而生成的卻是所有數(shù)據(jù)的true/false矩陣,對(duì)于龐大的數(shù)據(jù)dataframe唯蝶,很難一眼看出來(lái)哪個(gè)數(shù)據(jù)缺失,一共有多少個(gè)缺失數(shù)據(jù)遗嗽,缺失數(shù)據(jù)的位置粘我。
importpandasaspd
importnumpyasnp
df=?pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] =?np.nan
df.iloc[5,3] =?np.nan
df.iloc[7:9,5] =?np.nan
##輸出
0?1?2?3?4?5
00.5201130.8840001.260966-0.2365970.312972-0.196281
1-0.837552?NaN0.1430170.8623550.3465500.842952
2-0.452595?NaN-0.4207900.4562151.2034590.527425
30.317503-0.9170421.780938-1.5841020.4327450.389797
4-0.7228521.704820-0.113821-1.4664580.0830020.011722
5-0.622851-0.251935-1.498837?NaN1.0983230.273814
60.3295850.075312-0.690209-3.8079240.489317-0.841368
7-1.123433-1.1874961.868894-2.046456-0.949718?NaN
81.133880-0.1104470.050385-1.1583870.188222?NaN
9-0.5137411.1962590.7045370.982395-0.585040-1.693810
df.isnull()會(huì)產(chǎn)生如下結(jié)果:
?012345
0FalseFalseFalseFalseFalseFalse
1False?TrueFalseFalseFalseFalse
2False?TrueFalseFalseFalseFalse
3FalseFalseFalseFalseFalseFalse
4FalseFalseFalseFalseFalseFalse
5FalseFalseFalse?TrueFalseFalse
6FalseFalseFalseFalseFalseFalse
7FalseFalseFalseFalseFalse?True
8FalseFalseFalseFalseFalse?True
9FalseFalseFalseFalseFalseFalse
df.isnull().any()則會(huì)判斷哪些”列”存在缺失值
0False
1?True
2False
3?True
4False
5?True
dtype:?bool
對(duì)于該問(wèn)題,可以采用如下方式解決:
df[df.isnull().values==True]?當(dāng)然也可像老師做痹换,得到所有的index是否含有空值的結(jié)果再提取征字。
0?1?2?3?4?5
11.090872?NaN-0.287612-0.239234-0.5898971.849413
2-1.384721?NaN-0.1582930.011798-0.564906-0.607121
5-0.477590-2.6962390.312837?NaN0.404196-0.797050
70.369665-0.268898-0.344523-0.0944360.214753?NaN
8-0.114483-0.8423220.164269-0.812866-0.601757?NaN
####可以只顯示存在缺失值的行列,清楚的確定缺失值的位置娇豫。
4匙姜、排序
sort_values() sort_index()
#根據(jù)行索引排序
data.sort_index(ascending=False)?#ascending:升序
#order by 列
data.sort_values(by=['銷(xiāo)售代表ID','數(shù)量']).iloc[:10]
5、數(shù)據(jù)聚合【重點(diǎn)】
5.1
數(shù)據(jù)聚合是數(shù)據(jù)處理的最后一步冯痢,通常是要使每一個(gè)數(shù)組生成一個(gè)單一的數(shù)值氮昧。
數(shù)據(jù)分類(lèi)處理:
分組:先把數(shù)據(jù)分為幾組
用函數(shù)處理:為不同組的數(shù)據(jù)應(yīng)用不同的函數(shù)以轉(zhuǎn)換數(shù)據(jù)
合并:把不同組得到的結(jié)果合并起來(lái)
數(shù)據(jù)分類(lèi)處理的核心: groupby()函數(shù)
groupby()在pandas中也擔(dān)任分組的重?fù)?dān)
如果想使用color列索引,計(jì)算price1的均值浦楣,可以先獲取到price1列袖肥,然后再調(diào)用groupby函數(shù),用參數(shù)指定color這一列
使用.groups屬性查看各行的分組情況:
pd.DataFrame(data.groupby(by='客戶省份').金額.sum())
# select avg(age) from table_name where group by age,sex;
#分組的意義在與更好的統(tǒng)計(jì)
foriindata.iloc[:100].groupby(by='客戶省份'):
display(i[1])
data.groupby(by='客戶省份').__dict__
add_prefix()添加前綴
pd.DataFrame(data.groupby(by='客戶省份').金額.sum()).add_prefix('總')
可以使用pd.merge()函數(shù)將聚合操作的計(jì)算結(jié)果添加到df的每一行使用groupby分組后調(diào)用加和等函數(shù)進(jìn)行運(yùn)算振劳,讓后最后可以調(diào)用add_prefix()椎组,來(lái)修改列名。
可以使用transform和apply實(shí)現(xiàn)相同功能
在transform或者apply中傳入函數(shù)即可
data.groupby(by=['客戶省份']).金額.agg(sum).sort_values()
5.2 離散化和分箱
字符型和范圍型
方便觀察和統(tǒng)計(jì)
pd.cut(),映射成一個(gè)范圍類(lèi)型
投票選舉的例子就自己練習(xí)哦
5.3 一些概念
時(shí)間序列
時(shí)間類(lèi)型是連續(xù)型
時(shí)間可以當(dāng)作行索引
把字符串的時(shí)間轉(zhuǎn)變?yōu)闀r(shí)間類(lèi)型: pd.to_datetime()
s = pd.Series(['3/11/2000', '3/12/2000', '3/13/2000']*1000)
0? ? ? 3/11/2000
1? ? ? 3/12/2000
2? ? ? 3/13/2000
3? ? ? 3/11/2000
4? ? ? 3/12/2000
5? ? ? 3/13/2000
6? ? ? 3/11/2000
....
pd.to_datatime(s)
0? ? ? 2000-03-11
1? ? ? 2000-03-12
2? ? ? 2000-03-13
3? ? ? 2000-03-11
4? ? ? 2000-03-12
5? ? ? 2000-03-13
6? ? ? 2000-03-11
重采樣
降采樣 : 把高頻的數(shù)據(jù)轉(zhuǎn)換為低頻的數(shù)據(jù)
數(shù)據(jù)量大历恐,計(jì)算效率下降
數(shù)據(jù)不容易觀察
要求行索引必須是時(shí)間序列
.resample()
Pandas中的resample寸癌,重新采樣蒸苇,是對(duì)原樣本重新處理的一個(gè)方法莺葫,是一個(gè)對(duì)常規(guī)時(shí)間序列數(shù)據(jù)重新采樣和頻率轉(zhuǎn)換的便捷的方法堡纬。
DataFrame.resample(rule, how``=``None``, axis``=``0``, fill_method``=``None``, closed``=``None``, label``=``None``, convention``=``'start'``,kind``=``None``, loffset``=``None``, limit``=``None``, base``=``0``)
6炮叶、大數(shù)據(jù)的讀取
假如你待處理的數(shù)據(jù)比你的內(nèi)存大怎么辦?
#分片讀取? skip()? limit()
#skiprows=None (跳過(guò)多少行), nrows=None (獲取多少行)
#查找最大值僚纷,每次讀取100行
#把其它的最大金額給存儲(chǔ)起來(lái)
max_data = []
#代表循環(huán)的次數(shù)
n = 0
while True:
? ? if n == 0:
? ? ? ? df = pd.read_excel('銷(xiāo)售記錄.xlsx',skiprows=n,nrows=100,header=None).iloc[1:]
? ? ? ? max_data.append(df.iloc[:,-1].max())
? ? else:
? ? ? ? df = pd.read_excel('銷(xiāo)售記錄.xlsx',skiprows=n*100,nrows=100,header=None)
? ? ? ? #dataframe中獲取的數(shù)據(jù)大于1行
? ? ? ? if df.shape[0] > 0:
? ? ? ? ? ? max_data.append(df.iloc[:,-1].max())
? ? ? ? else:
? ? ? ? ? ? break
? ? n += 1?
np.max(max_data)