Pandas 第一輪零基礎(chǔ)掃盲
為什么用 Pandas?
你好,我是悅創(chuàng)。
通過對 Numpy 的學(xué)習(xí),我們發(fā)現(xiàn) Numpy 的功能確實強大且易用。但是再強大的工具也有其局限性。
例如 Numpy 是基于數(shù)組的運算,但是在實際工作中,我們的數(shù)據(jù)元素會非常復(fù)雜,會同時包含文字格式、數(shù)字格式、時間格式等,顯然 Numpy就不適用了。
通常我們說 Numpy 是基于數(shù)組格式構(gòu)建的一個數(shù)組運算工具,而 Pandas 是基于 Numpy 構(gòu)建的結(jié)構(gòu)化數(shù)據(jù)處理工具。對 Pandas 來講,數(shù)據(jù)格式得到了擴(kuò)充,提供了時間序列能力,并且能夠同時容納多種數(shù)據(jù)格式,并且提供了靈活的缺失值處理工具,功能得到極大地拓展。
Pandas 常用的數(shù)據(jù)結(jié)構(gòu)有兩種:Series 和 DataFrame 。其中 Series ?是一個帶有名稱和索引的一維數(shù)組,而 DataFrame 則是用來表示多維的數(shù)組結(jié)構(gòu)。
總結(jié)如下:
快速高效的數(shù)據(jù)結(jié)構(gòu) 智能的數(shù)據(jù)處理能力 方便的文件存取功能 科研及商業(yè)應(yīng)用廣泛
對于 Pandas 有兩種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),基本上我們在使用的時候就是處理 Series 和 DataFrame。
Series:真正的數(shù)據(jù)是只有一列的,索引列我們是不算進(jìn)去的。
| 索引 | 數(shù)據(jù) |
|---|---|
| A | 10 |
| B | 30 |
| C | 20 |
| D | 40 |
DataFrame:好幾個 Series 結(jié)合起來,也就是有好幾列的數(shù)據(jù)結(jié)合起來。
| 電影 | 評分 | 評分人數(shù) | |
|---|---|---|---|
| 0 | 血觀音 | 7.9 | 38478 |
| 1 | 大佛普拉斯 | 8.6 | 58112 |
| 2 | 華盛頓郵報 | 8.2 | 30773 |
| 3 | 三塊廣告牌 | 8.7 | 250524 |
安裝 Pandas
Windows 系統(tǒng):
pip?install?pandas
Mac 系統(tǒng):
pip3?install?pandas
新建一個 Python 文件
導(dǎo)入模塊
In?[1]:?import?pandas?as?pd
Pandas 的基礎(chǔ)類型1——Series
創(chuàng)建一個 Series 類型的數(shù)據(jù)
In?[2]:?data?=?pd.Series([1,?3,?5,?7])
Series() 里直接填一個由數(shù)字組成的列表
In?[3]:?list_data?=?[1,?3,?5,?7]
In?[4]:?data?=?pd.Series(list_data)
??
In?[5]:?data
Out[5]:
0????1
1????3
2????5
3????7
dtype:?int64
由結(jié)果我們可知,左邊把我們的索引也列出來了,右邊對應(yīng)的數(shù)值也列出來了。底部告訴你這個 Series 的數(shù)據(jù)類型 int64。「如果里面最低的數(shù)據(jù)類型是 ?float 那結(jié)果也會變成浮點數(shù)?!?/p>
獲取 Series 數(shù)據(jù)的值
In?[6]:?data.values
Out[6]:?array([1,?3,?5,?7])
獲取 Series 數(shù)據(jù)的索引
In?[7]:?data.index
Out[7]:?RangeIndex(start=0,?stop=4,?step=1)
創(chuàng)建特殊的索引值 有時候,我們索引的名稱比較特殊不是我們原本簡單的數(shù)字了,有可能是 a、b、c、d 之類的。這個時候就我們該如何指定索引值呢?直接在 Series 創(chuàng)建的時候指定一下就 ok 了。
In?[7]:?data?=?pd.Series(list_data,?index=['a',?'b',?'c',?'d'])
In?[8]:?data
Out[8]:
a????1
b????3
c????5
d????7
dtype:?int64
這里我們就在創(chuàng)建的時候進(jìn)行的索引值的指定,那我們?nèi)绻趧?chuàng)建之后修改索引呢?
修改索引值名稱
In?[9]:?data.index?=?['j',?'k',?'x',?'f']?#?長度需要和數(shù)組的長度一樣
In?[10]:?data
Out[10]:
j????1
k????3
x????5
f????7
dtype:?int64
獲取 Series 數(shù)據(jù)長度
In?[11]:?len(data)
Out[11]:?4
獲取數(shù)組中的某個數(shù)據(jù)
In?[12]:?data['k']?#?data[1]
Out[12]:?3
獲取數(shù)組中多個數(shù)據(jù)「不連續(xù)」「第一個中括號:告訴程序說,我要索引一下;第二個中括號:用來獲取多個數(shù)據(jù),一個數(shù)據(jù)則不用」
In?[13]:?data[['k',?'f']]
Out[13]:
k????3
f????7
dtype:?int64
獲取數(shù)組中多個數(shù)據(jù)「連續(xù)的」
In?[14]:?data[1:3]?#?也可以有步長
Out[14]:
k????3
x????5
dtype:?int64
計算重復(fù)元素出現(xiàn)的次數(shù)
In?[17]:?list_data1?=?[1,?1,?1,?3,?5,?5,?7,?7,?9]
In?[18]:?data1?=?pd.Series(list_data1)
In?[19]:?data1.value_counts()
Out[19]:
1????3
7????2
5????2
9????1
3????1
dtype:?int64
判斷某個索引值是否存在
In?[21]:?list_data2?=?[1,?3,?5,?7]
In?[22]:?data3?=?pd.Series(list_data2,?index=['a',?'j',?'b',?'f'])
In?[23]:?'a'?in?data3
Out[23]:?True
In?[24]:?'z'?in?data3
Out[24]:?False
檢查值是否包含在系列
In?[4]:?s?=?pd.Series(['lama',?'cow',?'lama',?'beetle',?'lama',?'hippo'],?name='animal')
In?[5]:?s.isin(['cow',?'lama'])
Out[5]:
0?????True
1?????True
2?????True
3????False
4?????True
5????False
Name:?animal,?dtype:?bool
In?[6]:?s.isin(['lama'])
Out[6]:
0?????True
1????False
2?????True
3????False
4?????True
5????False
Name:?animal,?dtype:?bool
從字典創(chuàng)建一個 Series 類型的數(shù)據(jù)
In?[26]:?dict_data?=?{"BeiJing":?1000,?"Shanghai":?800,?"Shenzhen":?500}
In?[27]:?data4?=?pd.Series(dict_data)
In?[28]:?data4
Out[28]:
BeiJing?????1000
Shanghai?????800
Shenzhen?????500
dtype:?int64
給數(shù)據(jù)傳入索引值「由字典創(chuàng)建的數(shù)組,當(dāng)我們指定的索引超出時,會自動 nan 填充」
In?[33]:?dict_data?=?{"BeiJing":?1000,?"Shanghai":?800,?"Shenzhen":?500}
In?[34]:?index_list?=?["Guangzhou",?"BeiJing",?"Shanghai",?"Shenzhen"]
In?[35]:?data5?=?pd.Series(dict_data,?index=index_list)
In?[36]:?data5
Out[36]:
Guangzhou???????NaN
BeiJing??????1000.0
Shanghai??????800.0
Shenzhen??????500.0
dtype:?float64
檢測哪些數(shù)據(jù)是缺失的(空的)「檢測非空用 notnull() 」
In?[37]:?data5.isnull()
Out[37]:
Guangzhou?????True
BeiJing??????False
Shanghai?????False
Shenzhen?????False
dtype:?bool
數(shù)組運算
In?[10]:?data5?*?5
Out[10]:
Guangzhou???????NaN
BeiJing??????5000.0
Shanghai?????4000.0
Shenzhen?????2500.0
dtype:?float64
數(shù)組運算支持 numpy 數(shù)組運算
In?[12]:?import?numpy?as?np
In?[13]:?np.square(data5)?#?求平方
Out[13]:
Guangzhou??????????NaN
BeiJing??????1000000.0
Shanghai??????640000.0
Shenzhen??????250000.0
dtype:?float64
兩個數(shù)組相加「兩個的數(shù)組的長度可以不一樣,順序也可以不一樣」
In?[14]:?dict_data1?=?{"BeiJing":?1000,?"Shanghai":?800,?"Shenzhen":?500}
????...:?dict_data2?=?{"BeiJing":?1000,?"Shanghai":?800,?"Shenzhen":?500}
????...:
????...:?index_list?=?["Guangzhou",?"BeiJing",?"Shanghai",?"Shenzhen"]
????...:?data1?=?pd.Series(dict_data1,?index=index_list)
????...:?data2?=?pd.Series(dict_data2)
In?[15]:?data1?+?data2
Out[15]:
BeiJing??????2000.0
Guangzhou???????NaN
Shanghai?????1600.0
Shenzhen?????1000.0
dtype:?float64
In?[16]:?data1?=?pd.Series(dict_data1,?index=index_list)
????...:?data2?=?pd.Series(dict_data2,?index=index_list)
In?[17]:?data1?+?data2
Out[17]:
Guangzhou???????NaN
BeiJing??????2000.0
Shanghai?????1600.0
Shenzhen?????1000.0
dtype:?float64
In?[21]:?data1?=?pd.Series([1,?3,?5,?6,?7,?8])
In?[22]:?data2?=?pd.Series([2,?4,?6,?8,?9])
In?[23]:?data1?+?data2
Out[23]:
0?????3.0
1?????7.0
2????11.0
3????14.0
4????16.0
5?????NaN
dtype:?float64
設(shè)定 Series 對象的 name 和索引名稱「類似于給一個表格取個名稱,給索引值取個名稱」
In?[25]:?dict_data?=?{"BeiJing":?1000,?"Shanghai":?800,?"Shenzhen":?500}
In?[26]:?data?=?pd.Series(dict_data)
In?[27]:?data.name?=?'City?Data'
In?[28]:?data.index.name?=?'City'
In?[29]:?data
Out[29]:
City
BeiJing?????1000
Shanghai?????800
Shenzhen?????500
Name:?City?Data,?dtype:?int64
當(dāng)然我們還可以在創(chuàng)建為數(shù)組取名字
In?[30]:?dict_data?=?{"BeiJing":?1000,?"Shanghai":?800,?"Shenzhen":?500}
In?[31]:?data?=?pd.Series(dict_data,?name='City?Data')
In?[32]:?data
Out[32]:
BeiJing?????1000
Shanghai?????800
Shenzhen?????500
Name:?City?Data,?dtype:?int64
Pandas 的基礎(chǔ)類型2——DataFrame
創(chuàng)建一個 DataFrame 類型的數(shù)據(jù)
In?[39]:?dict_data?=?{
????...:?'Student':?['lilei',?'hanmeimei',?'aiyuechuang'],
????...:?'Score':?[99,?100,?135],
????...:?'Gender':?['M',?'F',?'M']
????...:?}
In?[40]:?data?=?pd.DataFrame(dict_data)
In?[41]:?data
Out[41]:
???????Student??Score?Gender
0????????lilei?????99??????M
1????hanmeimei????100??????F
2??aiyuechuang????135??????M
指定 DataFrame 數(shù)據(jù)的列順序「如果出現(xiàn)結(jié)果順序不一樣,這個是正?,F(xiàn)象」
In?[42]:?data?=?pd.DataFrame(dict_data,?columns=['Gender',?'Score',?'Student'])??#?指定列的順序
In?[43]:?data
Out[43]:
??Gender??Score??????Student
0??????M?????99????????lilei
1??????F????100????hanmeimei
2??????M????135??aiyuechuang
獲取 DataFrame 數(shù)據(jù)的列名稱
In?[45]:?data.columns
Out[45]:?Index(['Gender',?'Score',?'Student'],?dtype='object')
指定 DataFrame 數(shù)據(jù)的索引值
In?[46]:?data?=?pd.DataFrame(dict_data,
????...:?????????????????????columns=['Gender',?'Score',?'Student'],
????...:?????????????????????index=['a',?'b',?'c'])
In?[47]:?data
Out[47]:
??Gender??Score??????Student
a??????M?????99????????lilei
b??????F????100????hanmeimei
c??????M????135??aiyuechuang
獲取 DataFrame 數(shù)據(jù)中的某一列數(shù)據(jù)
In?[48]:?data['Student']?#??方法一
Out[48]:
a??????????lilei
b??????hanmeimei
c????aiyuechuang
Name:?Student,?dtype:?object
In?[49]:?data.Student??#??方法二
Out[49]:
a??????????lilei
b??????hanmeimei
c????aiyuechuang
Name:?Student,?dtype:?object
獲取 DataFrame 數(shù)據(jù)中的某一行數(shù)據(jù)
根據(jù)行編號
In?[51]:?data.iloc[0]
Out[51]:
Gender?????????M
Score?????????99
Student????lilei
Name:?a,?dtype:?object
In?[59]:?data.loc[['a',?'c']]?#?指定多行數(shù)據(jù)
Out[59]:
??Gender??Score??????Student
a??????M?????99????????lilei
c??????M????135??aiyuechuang
In?[60]:?data[0:2]
Out[60]:
??Gender??Score????Student
a??????M?????99??????lilei
b??????F????100??hanmeimei

根據(jù)行索引
In?[52]:?data.loc['a']
Out[52]:
Gender?????????M
Score?????????99
Student????lilei
Name:?a,?dtype:?object
切片「單列數(shù)據(jù)」
In?[53]:?slice_data?=?data['Student']
In?[54]:?slice_data
Out[54]:
a??????????lilei
b??????hanmeimei
c????aiyuechuang
Name:?Student,?dtype:?object
切片「獲取多列數(shù)據(jù)」
In?[56]:?slice_data?=?data[['Student',?'Gender']]
In?[57]:?slice_data
Out[57]:
???????Student?Gender
a????????lilei??????M
b????hanmeimei??????F
c??aiyuechuang??????M
注意!切片得到的數(shù)據(jù)對應(yīng)的還是原始數(shù)據(jù),任何修改都會反映到原始數(shù)據(jù)上
In?[62]:?dict_data?=?{
????...:?????'Student':?['lilei',?'hanmeimei',?'aiyuechuang'],
????...:?????'Score':?[99,?100,?135],
????...:?????'Gender':?['M',?'F',?'M']
????...:?????}
????...:
????...:?data?=?pd.DataFrame(dict_data,
????...:?????????????????????columns=['Gender',?'Score',?'Student'],
????...:?????????????????????index=['a',?'b',?'c'])
????...:?slice_data?=?data['Score']??#?data[['Score']]
????...:?"""
????...:?第一種?['Score']?在確定只提取一個的話使用這種方法;
????...:?第二種?[['Score']]?在不確定或者確定會有提取多個的話,推薦使用這個方法。
????...:?"""
????...:?slice_data[0]?=?999??#?當(dāng)我們在切片的時候,如果只是單純的切片「不帶?copy」沒有操作不會出
????...:?現(xiàn)"警告"?如果進(jìn)行的賦值或者修改,則會出現(xiàn)警告?!杆闶翘崾景?,也是比較智能的一個點」
/usr/local/bin/ipython:15:?SettingWithCopyWarning:
A?value?is?trying?to?be?set?on?a?copy?of?a?slice?from?a?DataFrame
See?the?caveats?in?the?documentation:?https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
In?[63]:?data
Out[63]:
??Gender??Score??????Student
a??????M????999????????lilei
b??????F????100????hanmeimei
c??????M????135??aiyuechuang
想要一份副本不影響原始數(shù)據(jù)?
請用 data['score'].copy()
In?[64]:?slice_data?=?data['Score'].copy()
????...:?slice_data[0]?=?999
In?[65]:?data
Out[65]:
??Gender??Score??????Student
a??????M?????99????????lilei
b??????F????100????hanmeimei
c??????M????135??aiyuechuang
如果如果同時切片數(shù)據(jù)不止一個,那修改之后的數(shù)據(jù)變成這樣:
In?[75]:?slice_data?=?data[['Score',?'Student']].copy()
????...:?slice_data.iloc[0]?=?999
In?[76]:?slice_data
Out[76]:
???Score??????Student
a????999??????????999
b????100????hanmeimei
c????135??aiyuechuang
注意:如果你是如此操作提取數(shù)據(jù)的話—— data[['Score']] ,在下一步中修改數(shù)據(jù)中如果是這樣操作的話:slice_data[0] = 999 得到的結(jié)果是 添加新的列。所以,就需要使用 iloc 或 loc 來指定了。
In?[73]:?slice_data?=?data[['Score',?'Student']].copy()
????...:?slice_data[0]?=?999?#??slice_data[列名]?=?列值
????...:?slice_data
Out[73]:
???Score??????Student????0
a?????99????????lilei??999
b????100????hanmeimei??999
c????135??aiyuechuang??999
修改 DataFrame 數(shù)據(jù)中的某一列數(shù)據(jù)
In?[77]:?data
Out[77]:
??Gender??Score??????Student
a??????M?????99????????lilei
b??????F????100????hanmeimei
c??????M????135??aiyuechuang
In?[78]:?data['Score']?=?120
In?[79]:?data
Out[79]:
??Gender??Score??????Student
a??????M????120????????lilei
b??????F????120????hanmeimei
c??????M????120??aiyuechuang
In?[80]:?data['Score']?=?10,?20,?30?#??[10,?20,?30]、(10,?20,?30)
In?[81]:?data
Out[81]:
??Gender??Score??????Student
a??????M?????10????????lilei
b??????F?????20????hanmeimei
c??????M?????30??aiyuechuang
In?[88]:?data['Score']?=?range(95,?98)
In?[89]:?data
Out[89]:
??Gender??Score??????Student
a??????M?????95????????lilei
b??????F?????96????hanmeimei
c??????M?????97??aiyuechuang
傳入 Series 類型修改 DataFrame 數(shù)據(jù)中的某一列數(shù)據(jù)
In?[90]:?series_data?=?pd.Series([1,?3,?5])
In?[91]:?data['Score']?=?series_data
In?[92]:?data
Out[92]:
??Gender??Score??????Student
a??????M????NaN????????lilei
b??????F????NaN????hanmeimei
c??????M????NaN??aiyuechuang
In?[94]:?series_data?=?pd.Series([1,?3,?5],?index=['a',?'b',?'c'])
In?[95]:?data['Score']?=?series_data
In?[96]:?data
Out[96]:
??Gender??Score??????Student
a??????M??????1????????lilei
b??????F??????3????hanmeimei
c??????M??????5??aiyuechuang
如果 Series 的數(shù)據(jù)過長,則自動忽略:
In?[97]:?series_data?=?pd.Series([1,?3,?5,?7],?index=['a',?'b',?'c',?'d'])
In?[98]:?data['Score']?=?series_data
In?[99]:?data
Out[99]:
??Gender??Score??????Student
a??????M??????1????????lilei
b??????F??????3????hanmeimei
c??????M??????5??aiyuechuang
刪除 DataFrame 數(shù)據(jù)中的某一列數(shù)據(jù)
In?[102]:?del?data['Score']
In?[103]:?data
Out[103]:
??Gender??????Student
a??????M????????lilei
b??????F????hanmeimei
c??????M??aiyuechuang
刪除一行或一列:drop 函數(shù)
DataFrame.drop(labels=None,?axis=0,?index=None,?columns=None,?inplace=False)
#?labels?就是要刪除的行列的名字,用列表給定
#?axis?默認(rèn)為0,指刪除行,因此刪除?columns?時要指定?axis=1;
#?index?直接指定要刪除的行
#?columns?直接指定要刪除的列
#?inplace=False,默認(rèn)該刪除操作不改變原數(shù)據(jù),而是返回一個執(zhí)行刪除操作后的新?dataframe;
#?inplace=True,則會直接在原數(shù)據(jù)上進(jìn)行刪除操作,刪除后無法返回。
因此,刪除行列有兩種方式:
labels=None,axis=0 的組合 index 或 columns 直接指定要刪除的行或列
In?[111]:?df?=?pd.DataFrame(np.arange(12).reshape(3,4),?columns=['A',?'B',?'C',?'D'])
In?[112]:?df
Out[112]:
???A??B???C???D
0??0??1???2???3
1??4??5???6???7
2??8??9??10??11
#Drop?columns,兩種方法等價
In?[113]:?df.drop(['B',?'C'],?axis=1)
Out[113]:
???A???D
0??0???3
1??4???7
2??8??11
In?[114]:?df.drop(columns=['B',?'C'])
Out[114]:
???A???D
0??0???3
1??4???7
2??8??11
#?第一種方法下刪除?column?一定要指定?axis=1,否則會報錯
In?[115]:?df.drop(['B',?'C'])
---------------------------------------------------------------------------
KeyError??????????????????????????????????Traceback?(most?recent?call?last)
KeyError:?"['B'?'C']?not?found?in?axis"
#Drop?rows
In?[116]:?df.drop([0,?1])
Out[116]:
???A??B???C???D
2??8??9??10??11
In?[117]:?df.drop(index=[0,?1])
Out[117]:
???A??B???C???D
2??8??9??10??11
根據(jù)新的索引重新排列數(shù)據(jù)
In?[120]:?dict_data?=?{
?????...:?????'Student':?['lilei',?'hanmeimei',?'aiyuechuang'],
?????...:?????'Score':?[99,?100,?135],
?????...:?????'Gender':?['M',?'F',?'M']
?????...:?}
In?[121]:?data?=?pd.DataFrame(dict_data,
?????...:?????columns=['Gender',?'Score',?'Student'],
?????...:?????index=['a',?'b',?'c'])
In?[122]:?data.reindex(['b',?'a',?'c'])
Out[122]:
??Gender??Score??????Student
b??????F????100????hanmeimei
a??????M?????99????????lilei
c??????M????135??aiyuechuang
如果,我們在重新排序的時候,多填了一個 d 那相對應(yīng) d 的幾個位置的數(shù)據(jù) pandas 會自動幫你填上 NaN。
In?[123]:?data.reindex(['b',?'a',?'c',?'d'])
Out[123]:
??Gender??Score??????Student
b??????F??100.0????hanmeimei
a??????M???99.0????????lilei
c??????M??135.0??aiyuechuang
d????NaN????NaN??????????NaN
如果,我們想在多填了之后指定數(shù)據(jù)呢?
將缺失位置填0
In?[124]:?data.reindex(['b',?'a',?'c',?'d'],?fill_value=0)
Out[124]:
??Gender??Score??????Student
b??????F????100????hanmeimei
a??????M?????99????????lilei
c??????M????135??aiyuechuang
d??????0??????0????????????0
將缺失位置通過插值法計算并補上內(nèi)容
In?[125]:?data.reindex(['b',?'a',?'c',?'d'],?method='ffill')
Out[125]:
??Gender??Score??????Student
b??????F????100????hanmeimei
a??????M?????99????????lilei
c??????M????135??aiyuechuang
d??????M????135??aiyuechuang
In?[126]:?data.reindex(['b',?'a',?'c',?'d'],?method='bfill')
Out[126]:
??Gender??Score??????Student
b??????F??100.0????hanmeimei
a??????M???99.0????????lilei
c??????M??135.0??aiyuechuang
d????NaN????NaN??????????NaN
扔掉包含缺失的數(shù)據(jù)(NaN)的行「例如:我們數(shù)據(jù)量很大的時候,有可能想把空值去掉,使用 dropna 來去掉,只要這一行有一個空數(shù)據(jù),就會去掉?!惯@里代碼為了方便演示,就先不使用 IPython。
import?numpy?as?np
import?pandas?as?pd
dict_data?=?{
?'Student':?['lilei',?'hanmeimei',?'aiyuechuang'],
?'Score':?[99,?100,?135],
?'Gender':?['M',?'F',?'M']
}
data?=?pd.DataFrame(dict_data,
?columns=['Gender',?'Score',?'Student',?'Age'],
?index=['a',?'b',?'c'])
new_data?=?data.reindex(['a',?'b',?'c',?'d'])?
print(new_data)
print(new_data.dropna())
扔掉全部都是缺失的數(shù)據(jù)(NaN)的行
print(new_data.dropna(how='all'))
填充所有缺失數(shù)據(jù)為一個值
print(new_data.fillna(0))
按列填充缺失數(shù)據(jù)為不同值「fillna:按列填寫缺失值,如果存在著不填?!?/section>
dict_data?=?{
?'Student':?['lilei',?'hanmeimei',?'aiyuechuang'],
?'Score':?[99,?100,?135],
?'Gender':?['M',?'F',?'M']
}
data?=?pd.DataFrame(dict_data,
?columns=['Gender',?'Score',?'Student',?'Age'],
?index=['a',?'b',?'c'])
new_data?=?data.reindex(['a',?'b',?'c',?'d'])
key_value?=?{'Gender':?'F',?'Score':?145,?'Student':?'Alex',?'Age':?21}
print(new_data.fillna(key_value))
#??輸出
??Gender??Score??????Student??Age
a??????M???99.0????????lilei???21
b??????F??100.0????hanmeimei???21
c??????M??135.0??aiyuechuang???21
d??????F??145.0?????????Alex???21
篩選數(shù)據(jù)
dict_data?=?{
?'Student':?['lilei',?'hanmeimei',?'aiyuechuang'],
?'Score':?[80,?100,?135],
?'Gender':?['M',?'F',?'M']
}
data?=?pd.DataFrame(dict_data,
?columns=['Gender',?'Score',?'Student',?'Age'],
?index=['a',?'b',?'c'])
print(data[data['Score']?>=?90])
#?輸出
??Gender??Score??????Student??Age
b??????F????100????hanmeimei??NaN
c??????M????135??aiyuechuang??NaN
從列表中篩選數(shù)據(jù)
dict_data?=?{
?'Student':?['lilei',?'hanmeimei',?'aiyuechuang',?'Alex',?'Cleland',?'AI悅創(chuàng)'],
?'Score':?[80,?100,?135,?90,?85,?95],
?'Gender':?['M',?'F',?'M',?'M',?'F',?'M']
}
data?=?pd.DataFrame(dict_data)
select_list?=?[95,?100,?135]
#?print(data)
print(data[data['Score'].isin(select_list)])
GroupBy
import?pandas?as?pd
ipl_data?=?{'Team':?['Riders',?'Riders',?'Devils',?'Devils',?'Kings',
?????????'kings',?'Kings',?'Kings',?'Riders',?'Royals',?'Royals',?'Riders'],
?????????'Rank':?[1,?2,?2,?3,?3,4?,1?,1,2?,?4,1,2],
?????????'Year':?[2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
?????????'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df?=?pd.DataFrame(ipl_data)
print?(df)
#?執(zhí)行上面示例代碼,得到以下結(jié)果?-
????Points??Rank????Team??Year
0??????876?????1??Riders??2014
1??????789?????2??Riders??2015
2??????863?????2??Devils??2014
3??????673?????3??Devils??2015
4??????741?????3???Kings??2014
5??????812?????4???kings??2015
6??????756?????1???Kings??2016
7??????788?????1???Kings??2017
8??????694?????2??Riders??2016
9??????701?????4??Royals??2014
10?????804?????1??Royals??2015
11?????690?????2??Riders??2017
"""
將數(shù)據(jù)拆分成組
Pandas對象可以分成任何對象。有多種方式來拆分對象,如?-
-?obj.groupby(‘key’)
-?obj.groupby([‘key1’,’key2’])
-?obj.groupby(key,axis=1)
現(xiàn)在來看看如何將分組對象應(yīng)用于?DataFrame?對象
示例
"""
import?pandas?as?pd
ipl_data?=?{'Team':?['Riders',?'Riders',?'Devils',?'Devils',?'Kings',
?????????'kings',?'Kings',?'Kings',?'Riders',?'Royals',?'Royals',?'Riders'],
?????????'Rank':?[1,?2,?2,?3,?3,4?,1?,1,2?,?4,1,2],
?????????'Year':?[2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
?????????'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df?=?pd.DataFrame(ipl_data)
print?(df.groupby('Team'))
#?執(zhí)行上面示例代碼,得到以下結(jié)果?-
0x00000245D60AD518>
#?查看分組
import?pandas?as?pd
ipl_data?=?{'Team':?['Riders',?'Riders',?'Devils',?'Devils',?'Kings',
?????????'kings',?'Kings',?'Kings',?'Riders',?'Royals',?'Royals',?'Riders'],
?????????'Rank':?[1,?2,?2,?3,?3,4?,1?,1,2?,?4,1,2],
?????????'Year':?[2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],???????????'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df?=?pd.DataFrame(ipl_data)
print?(df.groupby('Team').groups)
#?執(zhí)行上面示例代碼,得到以下結(jié)果?-
{
'Devils':?Int64Index([2,?3],?dtype='int64'),?
'Kings':?Int64Index([4,?6,?7],?dtype='int64'),?
'Riders':?Int64Index([0,?1,?8,?11],?dtype='int64'),?
'Royals':?Int64Index([9,?10],?dtype='int64'),?
'kings':?Int64Index([5],?dtype='int64')
}
#?得到的結(jié)果類似字典的結(jié)構(gòu),提取字典的值之后,可以直接用整數(shù)索引或者使用?.values?可以提取出分組之后的值「數(shù)組」
利用 groupby 對數(shù)據(jù)進(jìn)行分組并計算 sum, mean 等
import?pandas?as?pd
data?=?pd.DataFrame({
?"tag_id":?['a',?'b',?'c',?'a',?'a',?'c',?'c'],
?'count':?[10,?30,?20,?10,?15,?22,?22]
?})
grouped_data?=?data.groupby('tag_id')
print(grouped_data.sum())
#?輸出
????????count
tag_id???????
a??????????35
b??????????30
c??????????64
data?=?pd.DataFrame({
?"tag_id":?['a',?'b',?'c',?'a',?'a',?'c',?'c'],
?'count':?[10,?30,?20,?10,?15,?22,?'22']
?})
grouped_data?=?data.groupby('tag_id')
print(grouped_data.sum())
#?輸出
????????count
tag_id???????
a????????35.0
b????????30.0
c?????????NaN
data?=?pd.DataFrame({
?"tag_id":?['a',?'b',?'c',?'a',?'a',?'c',?'c'],
?'count':?[10,?30,?20,?10,?15,?22,?22]
?})
grouped_data?=?data.groupby('count')
print(grouped_data.sum())
#?輸出
??????tag_id
count???????
10????????aa
15?????????a
20?????????c
22????????cc
30?????????b
數(shù)據(jù)排序——按索引名稱升序排列
import?pandas?as?pd
data?=?pd.DataFrame({
?"tag_id":?['0802',?'0823',?'0832',?'0731'],
?'count':?[10,?30,?20,?10]
?},
?index=['b',?'c',?'a',?'d'])
print(data)
print(data.sort_index())
數(shù)據(jù)排序——按索引名稱降序排列
print(data.sort_index(ascending=False))?#?ascending?上升
數(shù)據(jù)排序——按某一列的數(shù)據(jù)進(jìn)行排序
print(data.sort_values(by='tag_id'))
數(shù)據(jù)匯總「對 DataFrame 的數(shù)據(jù)全部進(jìn)行求和」
data?=?pd.DataFrame({
?"tag_id":?['AI',?'YC',?'FP',?'MK'],
?'count':?[10,?30,?20,?10]
?})
#?print(data)
print(data.sum())
一些常用的方法 | 函數(shù) | 說明 | | --- | --- | | count | 計算非 NaN 數(shù)據(jù)的數(shù)量 | | min、max | 計算最小、最大值 | | argmin、argmax | 計算最小、最大值位置 | | sum | 計算數(shù)值的和 | | mean | 計算平均數(shù) | | median | 計算中位數(shù) | | var | 計算方差 | | std | 計算標(biāo)準(zhǔn)差 |
同一個軸可以用多種方式來索引
import?numpy?as?np
import?pandas?as?pd
np_data?=?np.random.randint(1,?5,?size=7)
book_ratings?=?pd.Series(
?np_data,?
?index=[
?['b1',?'b1',?'b2',?'b2',?'b3',?'b4',?'b4'],
?[1,?2,?1,?2,?1,?2,?3]
?])
print(book_ratings)
print(book_ratings.loc['b1'])
#?輸出
b1??1????4
????2????3
b2??1????4
????2????1
b3??1????2
b4??2????1
????3????3
dtype:?int64
1????4
2????3
dtype:?int64
兩個 DataFrame 進(jìn)行合并
import?pandas?as?pd
book_name?=?pd.DataFrame({
?'book_name':?['a',?'b',?'c',?'d',?'e',?'f'],
?'book_id':?[11,?22,?33,?44,?55,?66]
?})
id_rating?=?pd.DataFrame({
?'book_id':?[11,?22,?22,?44,?55,?66,?33,?11,?55],
?'rating':?[1,?3,?5,?2,?4,?3,?2,?4,?5]
?})
print(pd.merge(book_name,?id_rating))


兩個 DataFrame 進(jìn)行合并,不指定連接方式「默認(rèn)是把他們都有的」
data1?=?pd.DataFrame({
?'key':?['a',?'b',?'a',?'c',?'b',?'d'],
?'data1':?[1,?2,?3,?4,?5,?6]
?})
data2?=?pd.DataFrame({
?'key':?['a',?'b',?'c'],
?'data2':?[8,?9,?7]
?})
print(pd.merge(data1,?data2))


默認(rèn)把兩個數(shù)據(jù)框都有的數(shù)據(jù)進(jìn)行合并。
兩個 DataFrame 進(jìn)行合并,指定連接方式「現(xiàn)在我們希望,你不要把雙方都有的留下來,我要把只有一方有的也留下來」
print(pd.merge(data1,?data2,?how='outer'))
#?輸出
??key??data1??data2
0???a??????1????8.0
1???a??????3????8.0
2???b??????2????9.0
3???b??????5????9.0
4???c??????4????7.0
5???d??????6????NaN
還可以使用 left、right 「類似交集并集、交集之類的」
兩個 DataFrame 進(jìn)行合并,指定連接的列名稱「兩個數(shù)據(jù)框都有的一個列,來合并」
data1?=?pd.DataFrame({
?'key':?['a',?'b',?'a',?'c',?'b',?'b'],
?'data1':?[1,?2,?3,?4,?5,?6]
?})
data2?=?pd.DataFrame({
?'key':?['a',?'b',?'c'],
?'data2':?[8,?9,?7]
?})
print(pd.merge(data1,?data2,?on='key'))
兩個 DataFrame 進(jìn)行合并,分別指定連接的列名稱「兩個數(shù)據(jù)沒有重合的名稱,我們分別指定列來合并」
print(pd.merge(data1,?data2,
?left_on='lkey',?
?right_on='rkey'))
Pandas 文件存取——讀取 CSV 文件「默認(rèn)會把文件的第一行,變成標(biāo)題」https://aiyc.lanzoux.com/iSU8ufj79af
data?=?pd.read_csv('rating.csv')
讀取 CSV 文件,不要標(biāo)題行「取消第一行為標(biāo)題」
data?=?pd.read_csv('rating.csv',?header=None)
讀取 CSV 文件,自定義標(biāo)題行
data?=?pd.read_csv('rating.csv',?names=['user_id',?'book_id',?'rating'])
讀取 CSV 文件,指定索引列「有可能我都某一列是我們的索引列,所以這個時候需要指定索引列」
data?=?pd.read_csv('rating.csv',
??????????????????names=['user_id',?'book_id',?'rating'],
??????????????????index_col='user_id')
讀取 CSV 文件,指定分隔符
data?=?pd.read_csv('rating.csv',
??????????????????names=['user_id',?'book_id',?'rating'],
??????????????????sep=',')
讀取 CSV 文件,自動處理缺失的數(shù)據(jù)「pandas 比較智能地方就是會把空的地方補上 Nan」
新建 data.csv 文件,里面存儲如下數(shù)據(jù)
1,2,3,4,5
6,7,8,,10
11,,13,14,15
代碼如下:
data?=?pd.read_csv('data.csv',?header=None)
儲存數(shù)據(jù)為 CSV 文件
import?pandas?as?pd
data?=?pd.DataFrame({
?'student':?['lilei',?'hanmeimei',?'madongmei'],
?'gender':?['M',?'F',?'F'],
?'score':?[90,?80,?100]
?})
data.to_csv('student.csv')
,student,gender,score
0,lilei,M,90
1,hanmeimei,F,80
2,madongmei,F,100在軟件中打開:

讀取 Excel 文件,首先安裝 xlrd 模塊
Windows 系統(tǒng):
pip install xlrdMac 系統(tǒng):
pip3 install xlrd新建一個 Excel 文件,保存文件名稱為:student.xlsx

讀取 Excel 文件

import?pandas?as?pd
file?=?pd.ExcelFile('student.xlsx')
data?=?file.parse('Sheet1')?#?Excel?表格名稱
print(data)
#?輸出
???Unnamed:?0????student?gender??score
0???????????0??????lilei??????M?????90
1???????????1??hanmeimei??????F?????80
2???????????2??madongmei??????F????100
Pandas VS. Numpy 讀取文件速度比較
import?numpy?as?np
import?pandas?as?pd
import?time
start_time?=?time.time()
data?=?np.genfromtxt('./rating.txt',?delimiter=',')
end_reading_time?=?time.time()
print('Numpy?reading?time:?{}ms'.format(round((end_reading_time?-?start_time)?*?1000,?2)))
start_time?=?time.time()
data?=?pd.read_table('./rating.csv',?
?names=['user_id',?'book_id',?'rating'],
?sep=',')
end_reading_time?=?time.time()
print('Pandas?reading?time:?{}ms'.format(round((end_reading_time?-?start_time)?*?1000,?2)))
#?輸出
Numpy?reading?time:?27029.64ms
Pandas?reading?time:?1003.31ms
Pandas 讀取速度很快,處理起來比 Numpy 慢一些。Numpy 是最底層的,Pandas 會智能的時候給你做一些數(shù)據(jù)處理,所以很多時候我們使用 Pandas 。
分析熱門標(biāo)簽
數(shù)據(jù)集:https://aiyc.lanzoux.com/iqgPTfxyrxc
任務(wù)1:找出最多人想讀的 50本書的名稱 任務(wù)2:找出這 50本書對應(yīng)最熱門的10個標(biāo)簽
文件1:to_read.csv
每行兩個數(shù)據(jù),用戶 id 和該用戶想讀的書籍 id
文件2:books.csv
書籍的各類 id,名稱,作者等信息
文件3:tags.csv
每行兩個數(shù)據(jù),標(biāo)簽 id 和標(biāo)簽名稱
文件4:book_tags.csv
每行三個數(shù)據(jù), _goodreads_book_id_(和to_read中的書籍 id 的對應(yīng)關(guān)系可以在books.csv里找到),標(biāo)簽 id,標(biāo)記次數(shù)
解答
Python 原生的處理方式,代碼如下「簡版代碼」:
import?pandas?as?pd
import?numpy?as?np
data?=?pd.read_csv('../to_read.csv')
#?print(data)
new_data?=?data['book_id']
#?array_lengt?=?len(set(data['book_id']))
#?print(array_lengt)
#?book_count_array?=?np.zeros(array_lengt)
#?print(set(new_data))
book_id_values?=?{}
result?=?list(new_data)
for?data?in?set(new_data):
?book_id_values[data]?=?result.count(data)
#?print(book_id_values)
d_sorted_by_value?=?sorted(book_id_values.items(),?key=lambda?x:?x[1])?#?根據(jù)字典值的升序排序
a?=?d_sorted_by_value[::-1][:50]
print(a)
print(len(a))
[(47,?2772),?(143,?1967),?(113,?1840),?(13,?1812),?(11,?1767),?(45,?1717),?(139,?1650),?(39,?1619),?(65,?1608),?(35,?1576),?(342,?1521),?(185,?1502),?(119,?1499),?(8,?1498),?(6,?1484),?(4,?1478),?(94,?1460),?(89,?1458),?(55,?1441),?(61,?1435),?(109,?1432),?(16,?1425),?(31,?1417),?(67,?1352),?(146,?1342),?(54,?1339),?(46,?1325),?(121,?1313),?(5,?1293),?(173,?1292),?(115,?1285),?(68,?1257),?(36,?1211),?(95,?1208),?(167,?1188),?(129,?1181),?(265,?1180),?(137,?1172),?(277,?1160),?(66,?1158),?(267,?1154),?(268,?1149),?(28,?1148),?(38,?1130),?(60,?1129),?(14,?1127),?(225,?1111),?(10,?1110),?(233,?1106),?(252,?1105)]
50
[Finished?in?147.9s]
Pandas 代碼:
第一步,找到最熱的50本書
import?pandas?as?pd
import?numpy?as?np
to_read?=?pd.read_csv('../to_read.csv')
to_read_counts?=?to_read['book_id'].value_counts().sort_values(ascending=False)
hottest_50_books_id?=?to_read_counts[:50].index
hottest_50_books_counts?=?to_read_counts[:50].values
hottest_50_books?=?pd.DataFrame({
?'book_id':?hottest_50_books_id,
?'to_read_counts':?hottest_50_books_counts
?})
"""
涉及到的知識點
1.?value_counts():??計算重復(fù)元素出現(xiàn)的次數(shù)「顯示形式為:值為索引,次數(shù)為值」
2.?sort_values():??按某一列的數(shù)據(jù)進(jìn)行排序,使用?by=列名,來指定。?
?????默認(rèn)是升序排序,可以使用?ascending=False?來反轉(zhuǎn)
"""
print(hottest_50_books)
????book_id??to_read_counts
0????????47????????????2772
1???????143????????????1967
2???????113????????????1840
3????????13????????????1812
4????????11????????????1767
5????????45????????????1717
6???????139????????????1650
7????????39????????????1619
8????????65????????????1608
9????????35????????????1576
10??????342????????????1521
11??????185????????????1502
12??????119????????????1499
13????????8????????????1498
14????????6????????????1484
15????????4????????????1478
16???????94????????????1460
17???????89????????????1458
18???????55????????????1441
19???????61????????????1435
20??????109????????????1432
21???????16????????????1425
22???????31????????????1417
23???????67????????????1352
24??????146????????????1342
25???????54????????????1339
26???????46????????????1325
27??????121????????????1313
28????????5????????????1293
29??????173????????????1292
30??????115????????????1285
31???????68????????????1257
32???????36????????????1211
33???????95????????????1208
34??????167????????????1188
35??????129????????????1181
36??????265????????????1180
37??????137????????????1172
38??????277????????????1160
39???????66????????????1158
40??????267????????????1154
41??????268????????????1149
42???????28????????????1148
43???????38????????????1130
44???????60????????????1129
45???????14????????????1127
46??????225????????????1111
47???????10????????????1110
48??????233????????????1106
49??????252????????????1105
[Finished?in?0.6s]
第二步,找到書籍的名稱
books?=?pd.read_csv('../books.csv')
book_id_and_title?=?books[['book_id',?'goodreads_book_id',?'title']]
hottest_50_books_with_title?=?pd.merge(
?hottest_50_books,?
?book_id_and_title,?
?how='left')
print(hottest_50_books_with_title)
hottest_50_books_with_title.to_csv('hottest_50_books_with_title.csv')
第三步,找到這50本書對應(yīng)最熱的10個標(biāo)簽
book_tags?=?pd.read_csv('../book_tags.csv')
book_tags?=?book_tags[book_tags['_goodreads_book_id_'].isin(hottest_50_books_with_title['goodreads_book_id'])]
del?book_tags['_goodreads_book_id_']
hottest_10_tags?=?book_tags.groupby('tag_id').sum()
hottest_10_tags?=?hottest_10_tags.sort_values(by='count',?ascending=False)[:10]
hottest_10_tags?=?pd.DataFrame({
?'tag_id':?hottest_10_tags.index,
?'count':?hottest_10_tags['count']
?})
print(hottest_10_tags['tag_id'])
第四步,找到這10個標(biāo)簽的名稱
tags?=?pd.read_csv('../tags.csv')
hottest_10_tags_with_tag_name?=?pd.merge(
?hottest_10_tags,
?tags,
?on='tag_id',
?how='left')
print(hottest_10_tags_with_tag_name)
hottest_10_tags_with_tag_name.to_csv('hottest_10_tags_with_tag_name.csv')“AI悅創(chuàng)·推出輔導(dǎo)班啦,包括「Python 語言輔導(dǎo)班、C++輔導(dǎo)班、算法/數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)班、少兒編程、pygame 游戲開發(fā)」,全部都是一對一教學(xué):一對一輔導(dǎo) + 一對一答疑 + 布置作業(yè) + 項目實踐等。QQ、微信在線,隨時響應(yīng)!V:Jiabcdefh
”
黃家寶丨AI悅創(chuàng)
隱形字
攝影公眾號「悅創(chuàng)攝影研習(xí)社」
在這里分享自己的一些經(jīng)驗、想法和見解。
長按識別二維碼關(guān)注


