查找和替換是日常工作中很常見的數據預處理操作,下面就來講解如何使用pandas模塊中的函數對DataFrame中的數據進行查找和替換。
1. 數據文件
2. 讀數據
import pandas as pd
data = pd.read_csv('D:\git\python\code\第5章\產品統計表.csv')
print(data)
輸出
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16 65 60 960 3900 2940
1 a002 錢包 90 187 50 4500 9350 4850
2 a003 背包 16 65 23 368 1495 1127
3 a004 手提包 36 147 26 936 3822 2886
4 a005 錢包 90 187 78 7020 14586 7566
5 a006 單肩包 58 124 63 3654 7812 4158
6 a007 單肩包 58 124 58 3364 7192 3828
3. 查找數據
>>> data.isin(['錢包','005'])
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 False False False False False False False False
1 False True False False False False False False
2 False False False False False False False False
3 False False False False False False False False
4 False True False False False False False False
5 False False False False False False False False
6 False False False False False False False False
>>> data['產品'].isin(['手提包'])
0 False
1 False
2 False
3 True
4 False
5 False
6 False
Name: 產品, dtype: bool
說明:
- 在整個數據表中查找是否有值“a005”和“錢包”,將等於“a005”或“錢包”的地方標記為True,將不等於“a005”或“錢包”的地方標記為False。需要注意的是,要查找的值必須以列表的形式給出。
- 判斷數據表的某一列中是否有某個值。在“產品”列中查找值“手提包”,將等於“手提包”的地方標記為True,將不等於“手提包”的地方標記為False。
4. 替換數據
4.1 一對一替換
將數據表中的值“背包”全部替換為“挎包”。replace()函數括號中逗號前面的參數是需要替換的值,逗號后面的參數是替換后的值。
參數inplace默認是不對原表替換,設置為True則原表上替換。
>>> data.replace('背包','挎包', inplace=True)
>>> print(data)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 挎包 16 65 60 960 3900 2940
1 a002 錢包 90 187 50 4500 9350 4850
2 a003 挎包 16 65 23 368 1495 1127
3 a004 手提包 36 147 26 936 3822 2886
4 a005 錢包 90 187 78 7020 14586 7566
5 a006 單肩包 58 124 63 3654 7812 4158
6 a007 單肩包 58 124 58 3364 7192 3828
4.2 多對一替換
>>> data.replace(['背包','手提包'], '挎包')
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 挎包 16 65 60 960 3900 2940
1 a002 錢包 90 187 50 4500 9350 4850
2 a003 挎包 16 65 23 368 1495 1127
3 a004 挎包 36 147 26 936 3822 2886
4 a005 錢包 90 187 78 7020 14586 7566
5 a006 單肩包 58 124 63 3654 7812 4158
6 a007 單肩包 58 124 58 3364 7192 3828
4.3 多對多替換
多對多替換可以看成是多個一對一替換。
>>> data.replace({'背包':'挎包', 16:39, 65:68}, inplace=True)
>>> print(data)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 挎包 39 68 60 960 3900 2940
1 a002 錢包 90 187 50 4500 9350 4850
2 a003 挎包 39 68 23 368 1495 1127
3 a004 手提包 36 147 26 936 3822 2886
4 a005 錢包 90 187 78 7020 14586 7566
5 a006 單肩包 58 124 63 3654 7812 4158
6 a007 單肩包 58 124 58 3364 7192 3828
5. 插入數據
pandas模塊沒有專門提供插入行的方法,因此,插入數據主要是指插入一列新的數據。常用的方法有兩種:
- 第一種是以賦值的方式在數據表的最右側插入列數據;
- 第二種是用insert()函數在數據表的指定位置插入列數據。
>>> data = pd.read_csv('D:\git\python\code\第5章\產品統計表.csv')
>>> data['品牌'] = ['AM','DE','SR','AM','TY','DE','UD']
>>> print(data)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元) 品牌
0 a001 背包 16 65 60 960 3900 2940 AM
1 a002 錢包 90 187 50 4500 9350 4850 DE
2 a003 背包 16 65 23 368 1495 1127 SR
3 a004 手提包 36 147 26 936 3822 2886 AM
4 a005 錢包 90 187 78 7020 14586 7566 TY
5 a006 單肩包 58 124 63 3654 7812 4158 DE
6 a007 單肩包 58 124 58 3364 7192 3828 UD
>>> data.insert(2, '產地', ['北京','深圳','成都','杭州','上海','重慶','武漢'])
>>> print(data)
編號 產品 產地 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元) 品牌
0 a001 背包 北京 16 65 60 960 3900 2940 AM
1 a002 錢包 深圳 90 187 50 4500 9350 4850 DE
2 a003 背包 成都 16 65 23 368 1495 1127 SR
3 a004 手提包 杭州 36 147 26 936 3822 2886 AM
4 a005 錢包 上海 90 187 78 7020 14586 7566 TY
5 a006 單肩包 重慶 58 124 63 3654 7812 4158 DE
6 a007 單肩包 武漢 58 124 58 3364 7192 3828 UD
6. 刪除數據
使用pandas模塊中的drop()函數。該函數既可以刪除指定的列,也可以刪除指定的行。
6.1 刪除列
在drop()函數中直接給出要刪除的列的列標簽就可以刪除列。
>>> data.drop(['成本價(元/個)', '成本(元)'], axis=1)
編號 產品 產地 銷售價(元/個) 數量(個) 收入(元) 利潤(元) 品牌
0 a001 背包 北京 65 60 3900 2940 AM
1 a002 錢包 深圳 187 50 9350 4850 DE
2 a003 背包 成都 65 23 1495 1127 SR
3 a004 手提包 杭州 147 26 3822 2886 AM
4 a005 錢包 上海 187 78 14586 7566 TY
5 a006 單肩包 重慶 124 63 7812 4158 DE
6 a007 單肩包 武漢 124 58 7192 3828 UD
drop()函數設置了兩個參數:
- 第1個參數以列表的形式給出要刪除的行或列的標簽;
- 第2個參數axis用於設置按行刪除還是按列刪除;
- 設置為0表示按行刪除(即第1個參數中給出的標簽是行標簽);
- 設置為1表示按列刪除(即第1個參數中給出的標簽是列標簽)。
- 還可以通過列序號來獲取列標簽,然后作為drop()函數的第1個參數使用。
# 這3個效果一樣
data.drop(data.columns[[3,6]], axis=1)
data.drop(['成本價(元/個)', '成本(元)'], axis=1)
data.drop(columns=['成本價(元/個)', '成本(元)'], axis=1)
6.2 刪除行
刪除行的方法和刪除列的方法類似,都要用到drop()函數,只不過需要將參數axis設置為0,其缺省值是0,可以不設。
>>> data = pd.read_csv('D:\git\python\code\第5章\產品統計表.csv', index_col=0)
>>> data.drop(['a001','a003'], axis=0)
產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
編號
a002 錢包 90 187 50 4500 9350 4850
a004 手提包 36 147 26 936 3822 2886
a005 錢包 90 187 78 7020 14586 7566
a006 單肩包 58 124 63 3654 7812 4158
a007 單肩包 58 124 58 3364 7192 3828
和刪除列類似.
# 這3個效果一樣,只不過在使用第2種時,讀文件時,可以不用index-col參數
data.drop(['a001','a003'], axis=0)
data.drop(data.index[[0,2]])
data.drop(index=['a001','a003'])
7. 處理缺失值
7.1 數據准備
7.2 查看缺失值
在Python中,缺失值一般用NaN表示。從運行結果可以看出,數據表的第3行和第7行含有缺失值。
>>> data = pd.read_csv('D:\git\python\code\第5章\產品統計表1.csv')
>>> print(data)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65 60 960.0 3900 2940
1 a002 錢包 90.0 187 50 4500.0 9350 4850
2 a003 背包 NaN 65 23 368.0 1495 1127
3 a004 手提包 36.0 147 26 936.0 3822 2886
4 a005 錢包 90.0 187 78 7020.0 14586 7566
5 a006 單肩包 58.0 124 63 3654.0 7812 4158
6 a007 單肩包 58.0 124 58 NaN 7192 3828
如果要查看每一列的缺失值情況,可以使用pandas模塊中的info()函數。
>>> print(data.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 8 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 編號 7 non-null object
1 產品 7 non-null object
2 成本價(元/個) 6 non-null float64
3 銷售價(元/個) 7 non-null int64
4 數量(個) 7 non-null int64
5 成本(元) 6 non-null float64
6 收入(元) 7 non-null int64
7 利潤(元) 7 non-null int64
dtypes: float64(2), int64(4), object(2)
memory usage: 576.0+ bytes
None
從運行結果可以看出,“成本價(元/個)”列和“成本(元)”列都是“6 non-null”,表示這兩列都有6個非空值,而其他列都有7個非空值,說明這兩列各有1個空值(即缺失值)。
使用isnull()函數判斷數據表中的哪個值是缺失值,並將缺失值標記為True,非缺失值標記為False。
>>> a = data.isnull()
>>> print(a)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 False False False False False False False False
1 False False False False False False False False
2 False False True False False False False False
3 False False False False False False False False
4 False False False False False False False False
5 False False False False False False False False
6 False False False False False True False False
7.3 刪除缺失值
使用dropna()函數可以刪除數據表中含有缺失值的行。默認情況下,只要某一行中有缺失值,該函數就會把這一行刪除。
>>> b = data.dropna()
>>> print(b)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65 60 960.0 3900 2940
1 a002 錢包 90.0 187 50 4500.0 9350 4850
3 a004 手提包 36.0 147 26 936.0 3822 2886
4 a005 錢包 90.0 187 78 7020.0 14586 7566
5 a006 單肩包 58.0 124 63 3654.0 7812 4158
如果只想刪除整行都為缺失值的行,則需要為dropna()函數設置參數how的值為'all'。
c = data.dropna(how='all')
print(c)
7.4 缺失值的填充
使用fillna()函數可以將數據表中的所有缺失值填充為指定的值。
>>> d = data.fillna(0)
>>> print(d)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65 60 960.0 3900 2940
1 a002 錢包 90.0 187 50 4500.0 9350 4850
2 a003 背包 0.0 65 23 368.0 1495 1127
3 a004 手提包 36.0 147 26 936.0 3822 2886
4 a005 錢包 90.0 187 78 7020.0 14586 7566
5 a006 單肩包 58.0 124 63 3654.0 7812 4158
6 a007 單肩包 58.0 124 58 0.0 7192 3828
可以通過為fillna()函數傳入一個字典,為不同列中的缺失值設置不同的填充值。
>>> e = data.fillna({'成本價(元/個)': 16, '成本(元)': 3364})
>>> print(e)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65 60 960.0 3900 2940
1 a002 錢包 90.0 187 50 4500.0 9350 4850
2 a003 背包 16.0 65 23 368.0 1495 1127
3 a004 手提包 36.0 147 26 936.0 3822 2886
4 a005 錢包 90.0 187 78 7020.0 14586 7566
5 a006 單肩包 58.0 124 63 3654.0 7812 4158
6 a007 單肩包 58.0 124 58 3364.0 7192 3828
8. 處理重復值
重復值的常用處理操作包括刪除重復值和提取唯一值,前者可以使用drop_duplicates()函數來完成,后者可以使用unique()函數來完成。
數據文件:產品統計表2.7z
8.1 刪除重復行
>>> data = pd.read_excel('D:\git\python\code\第5章\產品統計表2.xlsx')
>>> data = data.dropna(how='all')
>>> print(data)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65.0 60.0 960.0 3900.0 2940.0
1 a002 錢包 90.0 187.0 50.0 4500.0 9350.0 4850.0
2 a003 背包 16.0 65.0 23.0 368.0 1495.0 1127.0
3 a004 手提包 36.0 147.0 26.0 936.0 3822.0 2886.0
4 a004 手提包 36.0 147.0 26.0 936.0 3822.0 2886.0
5 a005 錢包 90.0 187.0 78.0 7020.0 14586.0 7566.0
6 a006 單肩包 58.0 124.0 63.0 3654.0 7812.0 4158.0
上述數據表的第4行和第5行中每列數據都完全相同,這樣的行稱為重復行。如果要只保留第4行,刪除與第4行重復的行,可直接使用drop_duplicates()函數,無須設置任何參數。
>>> a = data.drop_duplicates()
>>> print(a)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65.0 60.0 960.0 3900.0 2940.0
1 a002 錢包 90.0 187.0 50.0 4500.0 9350.0 4850.0
2 a003 背包 16.0 65.0 23.0 368.0 1495.0 1127.0
3 a004 手提包 36.0 147.0 26.0 936.0 3822.0 2886.0
5 a005 錢包 90.0 187.0 78.0 7020.0 14586.0 7566.0
6 a006 單肩包 58.0 124.0 63.0 3654.0 7812.0 4158.0
8.2 刪除某一列中的重復值
>>> b = data.drop_duplicates(subset='產品')
>>> print(b)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
0 a001 背包 16.0 65.0 60.0 960.0 3900.0 2940.0
1 a002 錢包 90.0 187.0 50.0 4500.0 9350.0 4850.0
3 a004 手提包 36.0 147.0 26.0 936.0 3822.0 2886.0
6 a006 單肩包 58.0 124.0 63.0 3654.0 7812.0 4158.0
默認保留第一個重復值所在的行,刪除其他重復值所在的行。
可以利用drop_duplicates()函數的參數keep來自定義刪除重復值時保留哪個重復值所在的行。
例如:
- 將參數keep設置為'first',表示保留第一個重復值所在的行。
- 如果要保留最后一個重復值所在的行,則將參數keep設置為'last'。
- 還可以將參數keep設置為False,表示把重復值一個不留地全部刪除。
8.3 獲取唯一值
使用pandas模塊中的unique()函數可以獲取某一列數據的唯一值。
>>> f = data['產品'].unique()
>>> print(f)
['背包' '錢包' '手提包' '單肩包']
說明:獲取的唯一值是按照其在數據表中出現的順序排列的。
9 排序數據
排序數據主要會用到sort_values()函數和rank()函數。
- sort_values()函數的功能是將數據按照大小進行升序排序或降序排序;
- rank()函數的功能則是獲取數據的排名。
9.1 用sort_values()函數排序數據
sort_values()函數的常用參數有兩個:
- 一個是by,用於指定要排序的列;
- 另一個是ascending,用於指定排序方式是升序還是降序。
>>> a = data.sort_values(by='數量(個)', ascending=True)
>>> print(a)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
2 a003 背包 16.0 65.0 23.0 368.0 1495.0 1127.0
3 a004 手提包 36.0 147.0 26.0 936.0 3822.0 2886.0
4 a004 手提包 36.0 147.0 26.0 936.0 3822.0 2886.0
1 a002 錢包 90.0 187.0 50.0 4500.0 9350.0 4850.0
0 a001 背包 16.0 65.0 60.0 960.0 3900.0 2940.0
6 a006 單肩包 58.0 124.0 63.0 3654.0 7812.0 4158.0
5 a005 錢包 90.0 187.0 78.0 7020.0 14586.0 7566.0
9.2 用rank()函數獲取數據的排名
rank()函數的常用參數有兩個:
- 一個是method,用於指定數據有重復值時的處理方式;
- 另一個是ascending,用於指定排序方式是升序還是降序。
rank初次接觸不好理解,第10小節專門解釋一下。
>>> b = data['利潤(元)'].rank(method='average', ascending=False)
>>> print(b)
0 4.0
1 2.0
2 7.0
3 5.5
4 5.5
5 1.0
6 3.0
10 rank()函數
rank是通過“為各組分配一個平均排名”的方式破壞平級關系的。pandas排名會增加一個排名值(從1開始,一直到數組中有效數據的數量)。
函數原型:
rank(axis=0, method: str = 'average', numeric_only: Union[bool, NoneType] = None, na_option: str = 'keep', ascending: bool = True, pct: bool = False)
官方文檔:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rank.html
假設創建了一個Series對象obj = Series([7, -5, 7, 4, 2, 0, 4]),就是上圖中”索引“和”值“這兩列,我們人為的按照值的大小進行了一個排名,並且產生了一個序列(”人為的排名“)這一列,關於有兩個索引(0和2)的值都是7的這種情況的排名的規則是,首先出現的值排名靠前。
下面就來說一下method參數的作用。
- 若為”average“,不相同的值,排名就取”人為的排名“的排名值,相同值的,排名需要求平均值,例如:索引0和2的值都為7,則平均值為(7+6)/2=6.5;
- 若為”min“,不相同的值,排名就取”人為的排名“的排名值,相同值的,排名取最小值,例如:索引0和2的值都為7,則排名都取6;
- 若為”max“,不相同的值,排名就取”人為的排名“的排名值,相同值的,排名取最大值,例如:索引0和2的值都為7,則排名都取7;
- 若為”first“,則就取”人為的排名“這列的值。
11. 篩選數據
>>> data = pd.read_csv('D:\git\python\code\第5章\產品統計表.csv')
>>> a = data[data['產品'] == '單肩包']
>>> print(a)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
5 a006 單肩包 58 124 63 3654 7812 4158
6 a007 單肩包 58 124 58 3364 7192 3828
用比較運算符“>”篩選出“數量(個)”列的值大於60的數據
>>> b = data[data['數量(個)'] > 60]
>>> print(b)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
4 a005 錢包 90 187 78 7020 14586 7566
5 a006 單肩包 58 124 63 3654 7812 4158
如果要進行多條件篩選,並且這些條件之間是“邏輯與”的關系,可以用“&”符號連接多個篩選條件。
需要注意的是,每個條件要分別用括號括起來。
>>> c = data[(data['產品'] == '單肩包') & (data['數量(個)'] > 60)]
>>> print(c)
編號 產品 成本價(元/個) 銷售價(元/個) 數量(個) 成本(元) 收入(元) 利潤(元)
5 a006 單肩包 58 124 63 3654 7812 4158
要進行多條件篩選,並且這些條件之間是“邏輯或”的關系,可以用“|”符號連接多個篩選條件,每個條件也要分別用括號括起來。