[Python] Pandas 對資料進行查詢、替換、篩選、排序、重複值和缺失值處理

哆啦夢樂園發表於2021-02-11


查詢和替換是日常工作中很常見的資料預處理操作,下面就來講解如何使用pandas模組中的函式對DataFrame中的資料進行查詢和替換。

1. 資料檔案

產品統計表.7z

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

說明:

  1. 在整個資料表中查詢是否有值“a005”和“錢包”,將等於“a005”或“錢包”的地方標記為True,將不等於“a005”或“錢包”的地方標記為False。需要注意的是,要查詢的值必須以列表的形式給出。
  2. 判斷資料表的某一列中是否有某個值。在“產品”列中查詢值“手提包”,將等於“手提包”的地方標記為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 資料準備

產品統計表1.7z

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

要進行多條件篩選,並且這些條件之間是“邏輯或”的關係,可以用“|”符號連線多個篩選條件,每個條件也要分別用括號括起來。

相關文章