查詢和替換是日常工作中很常見的資料預處理操作,下面就來講解如何使用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
要進行多條件篩選,並且這些條件之間是“邏輯或”的關係,可以用“|”符號連線多個篩選條件,每個條件也要分別用括號括起來。