?

Python語言處理各類空值的方法研究

2024-01-24 08:52蔡黎亞李淑萍
電腦知識與技術 2023年34期
關鍵詞:庫中語句運算

蔡黎亞 李淑萍

摘要:在各類編程語言中的空值表述都有所不同。對于數據分析而言,篩選出當前表內的空值并對其進行有效填充或進行其他操作,是數據清洗過程中的重要一環。該文對各類編程語言中可能出現的空值表述方法進行了梳理匯總,然后通過Python中的pandas擴展庫相關函數操作闡述了Python語言處理這些不同語境中空值的常用方法。

關鍵詞:數據處理;Python;Pandas;空值;None;NaN;NaT;Null;NA

中圖分類號:TP311? ? ? ? 文獻標識碼:A

文章編號:1009-3044(2023)34-0038-03

開放科學(資源服務)標識碼(OSID)

0 引言

在數據處理過程中會遇到形態各異的空值運算,比如Java中的Null,NumPy擴展庫中的NaN或者pandas擴展庫中的NA或者Python原生語言中的None類型等,都是各類編程語言對空值的描述。它們無論在表述方式和運算方法上都有所不同。要在數據清洗處理階段準確找出不同來源表格中的空值項,就需要掌握這些語言對空值項的表述方法。Python作為數據分析領域的重要開發語言,在數據處理擴展庫Pandas中有很多便捷的函數方法來處理各類的空值運算。

1 各類編程語言中的空值表述

在Python語言中的空值(也稱之為缺失值)是用None表示,其數據類型就是NoneType。None不支持任何運算——和其他數據類型的運算只返回False,但可以把None賦值給任何變量以表示為空[1],而兩個None進行比較時是相等關系。

在Python的NumPy擴展庫中,空值是用NaN(也可以寫作nan) 表示,它的數據類型是浮點型float。nan在NumPy庫中的含義是not a number[2]。任何與nan的運算結果都是nan,無窮大減無窮大會產生nan,而無窮大乘以零或無窮小除以無窮大等運算都會導致產生nan。兩個nan比較并不相等,這些nan的運算特點與Python中的None是有所不同的。

而Pandas的運算是基于NumPy庫構建的,因此通過NumPy庫運算的數值類空值往往用NaN表示(數值類型的空值)[3],也可能存在None(如表示字符串類型的空值)或者NaT(表示時間類型的空值)等。當None被運算時可能會觸發NumPy的運算機制而轉換為NaN。

另外,在其他類編程語言中,如Java、PHP、C++等語言的空值往往是用Null表示。Null在Python語言中是一個普通的字符串,但Python中存在一個與Null相關的比較函數isnull()可判斷各類其他語言運算后所存在的空值Null。

而如果存在類似a=’ ’這樣的賦值方式,則并不會被系統認定為空,而會被認為是非空的字符串。這些不同語言及擴展庫對空值的不同描述會在用戶進行數據清洗或整理時,帶來不小的困擾[4]。

在Python的Pandas擴展庫中推出了一個頂層的缺失值容器pd.NA來承載和處理Pandas庫內出現的各類空值,它嘗試把諸多類型的空值統一在pd.NA這個頂層的容器內,并為此創建了一個數據類型NAType[5]。因此,很多教程中也會把NA作為Pandas庫對空值類型的一種專屬描述。

Pandas庫中具有后綴名為na的各種函數,如df.fillna(), df.dropna(),df.isna()等,它們都可直接操作和處理不同類型的空值。

隨著Pandas庫的版本更新,相關na函數的功能也越來越完善,但依然與np.NaN等處理方法還存在一些差異。比如pd.NA是整數,np.NaN是浮點數。而pd.NA常用于整數、布爾型或字符串類型。在與1和0比較時,pd.NA的輸出是NA類型,而np.nan與1和0比較的結果是False。這些處理上的細微差異稍不留意就可能影響最終數據分析的準確性。

2 過濾空值

分析數據時會遇到許多數據不完整的情況,為了讓分析結果更接近真實,往往需要在空值處填充既定數據(如均值、中位數等),或者干脆丟棄這些少量而不完整數據。這時Pandas庫中的dropna()或者fillna()就可以方便地完成既定的任務。

通過函數dropna()可刪除數組對象DataFrame中存在的一個或多個空值列或行數據,因此常用于數據清洗中的過濾缺失值任務。

使用df.dropna()方法可以通過軸axis來指明刪除的是行還是列,其主要語法格式如下所示:

df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False) [3]

ü axis:可選參數,是指刪除空值所在的行或列,默認為0(行)。

ü how:可選參數,是指刪除的條件,默認為any(含有空值的任意行或列),還可選擇all (全是空值的行或列)。

ü thresh:可選參數,是指刪除空值后保留的行或列數,默認為空(全部都保留)。

ü subset:可選參數,是指定義在哪些列集合中查找空值,默認為空(全部列都檢索)。

ü inplace:可選參數,是指是否就地修改原數據對象,默認為False。

在該語法中,不存在必選參數,單獨使用df.dropna()即可刪除所有存在空值的行數據。下例所示為通過df.dropna()刪除數據對象中各類空值的程序實例。

在下例中,使用四個Series創建了一個數據對象df。其中salary列由NaN、None、<NA>這三種空值類型組成,而other列則是由pd.Series([''])所創建。它有一個看上去并不存在任何值卻并非空值的一個空字符串作為列首的數據。

import pandas as pd

import numpy as np

d1 = pd.Series([101, 102, 103, 104])

d2 = pd.Series(['Alex', 'Peter', 'Lisa'])

d3 = pd.Series([np.NaN, None, pd.NA, None])

d4 = pd.Series([''])

df = pd.DataFrame({'id': d1, 'name': d2, 'salary': d3, 'other': d4})

print('原數組->\n', df)

原數組->

id? ? name salary other

0? 101? ? Alex? ? NaN

1? 102? Peter? ? None? ? NaN

2? 103? ? Lisa? ? <NA>? ? NaN

3? 104? ? NaN? ? None? ? NaN

使用df.dropna()) 語句即可刪除所有存在空值的行數據,但介于df的每行都有空值,因此返回為空對象。

print('dropna()->\n', df.dropna())

dropna()->

Empty DataFrame

Columns: [id, name, salary, other]

Index: []

在df.dropna(subset=['name', 'other'])) 語句中使用了參數subset來指定需檢索的列名稱name與other。檢索的結果是除了第一行外,在這兩列內的其他行數據都存在空值(被刪除)。這里需要注意的是,pd.Series([''])所創建的空字符串并不被認為是空值。

print('dropna(subset=[])->\n', df.dropna(subset=['name', 'other']))

dropna(subset=[])->

id? name salary other

0? 101? Alex? ? NaN

在df.dropna(axis=1)) 語句中使用了軸參數axis=1指明刪除所有存在空值的列,因此只輸出了id列內容。

print('dropna(axis=1)->\n', df.dropna(axis=1))

dropna(axis=1)->

id

0? 101

1? 102

2? 103

3? 104

在df.dropna(axis=1, how='all') 語句中,除了通過軸參數axis=1來確定刪除軸的方向為縱向之外,還使用了參數how=all來指明刪除全部是空值的列。由于只有salary列數據全部都是空值,因此輸出的結果為不包含salary列的其他列內容。

print("drop.na(axis=1,how='all')->\n", df.dropna(axis=1, how='all'))

drop.na(axis=1,how='all')->

id? ? name other

0? 101? ? Alex

1? 102? Peter? ? NaN

2? 103? ? Lisa? ? NaN

3? 104? ? NaN? ? NaN

3 填充空值

外部獲取到的數據經常會存在數據缺失的情況,如何填充缺失值,填充哪些類的缺失值是數據清洗過程中常見的而又重要的一類操作[6]。Pandas庫中的fillna()就可以完成此類任務。

填充操作的函數使用方法會比刪除操作復雜一些,它擁有更多的參數。

df.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None) [3]

ü value:可選參數,是指填充值,可以是標量、字典、Series或DataFrame。默認為空。

ü method:可選參數,是指填充方法,可以是向后(backfill、bfill) 或向前填充(ffill、pad) ,默認為空(不指定)。

ü axis:可選參數,是指行方向還是列方向填充,默認為空。

ü inplace:可選參數,是指是否就地修改原數據對象。

ü limit:可選參數,是指填充的數量限制,默認為空(不限定填充數量,全部填充)。

ü downcast:可選參數,是指填充方向是向下廣播,默認為空(不指定填充方向)。

參數說明:

這些參數雖然全是可選參數,但至少需要在參數value與method中選擇一個參數使用。

在下例中依然創建了一個含有各類空值的待填充對象df。

import pandas as pd

import numpy as np

d1 = pd.Series([101, 102, 103, 104])

d2 = pd.Series(['Alex', 'Peter', 'Lisa'])

d3 = pd.Series([np.NaN, 6000, pd.NA, None])

d4 = pd.Series([None, 5, None, 9])

df = pd.DataFrame({'id': d1, 'name': d2, 'salary': d3, 'other': d4})

print('原數據對象->\n', df)

原數據對象->

id? ? name salary other

0? 101? ? Alex? ? NaN? ? NaN

1? 102? Peter? ? 6000? ? 5.0

2? 103? ? Lisa? ? <NA>? ? NaN

3? 104? ? NaN? ? None? ? 9.0

數據對象df中存在有缺失值的現象,使用df.fillna('missing')語句可以對所有的缺失值使用字符串missing填充。

print('標量填充->\n', df.fillna('missing'))

標量填充->

id name salary other

0 101 Alex missing missing

1 102 Peter 6000 5.0

2 103 Lisa missing missing

3 104 missing missing 9.0

在下面語句中使用df.fillna(df.mean())方法,可利用計算后的均值來填充。

print('均值填充->\n', df.fillna(df.mean()))

均值填充->

id name salary other

0 101 Alex 6000.0 7.0

1 102 Peter 6000.0 5.0

2 103 Lisa 6000.0 7.0

3 104 NaN 6000.0 9.0

在下面語句中使用了參數method='ffill'和limit=1,它們是指根據df.ffill()方法向后填充且限定一次。

print('向后填充限一次->\n', df.fillna(method='ffill', limit=1))

向后填充限一次->

id name salary other

0 101 Alex NaN NaN

1 102 Peter 6000.0 5.0

2 103 Lisa 6000.0 5.0

3 104 Lisa NaN 9.0

在下面語句中,使用了df.bfill()方法利用后值向前進行填充。bfill、ffill這些不僅可以作為method參數的關鍵字使用,也是一種可直接使用的填充方法。

print('向前(后值)填充->\n', df.fillna(method='bfill'))

向前(后值)填充->

id name salary other

0 101 Alex 6000.0 5.0

1 102 Peter 6000.0 5.0

2 103 Lisa NaN 9.0

3 104 NaN NaN 9.0

使用下面語句可以在指定列“salary”中使用該列的均值來填充空值。

df['salary'] = df.salary.fillna(df.salary.mean())

print('指定salary列填充均值->\n', df)

指定salary列填充均值->

id name salary other

0 101 Alex 6000.0 NaN

1 102 Peter 6000.0 5.0

2 103 Lisa 6000.0 NaN

3 104 NaN 6000.0 9.0

下面語句中使用了df.ffill()函數在df['salary']列內利用前值向后進行填充。 (下轉第58頁)

(上接第40頁)

df['salary'] = df['salary'].ffill()? # 使用ffill()填充,類似method指定

print('指定salary列向后填充->\n', df)

指定salary列向后填充->

id name salary other

0 101 Alex NaN NaN

1 102 Peter 6000.0 5.0

2 103 Lisa 6000.0 NaN

3 104 NaN 6000.0 9.0

參數method是指填充的方法,關鍵字backfill、bfill是指向后填充,ffill、pad是指向前填充。這些關鍵字也可以作為df的函數使用[7],如df.bfill()就是對既定的數據對象進行向后填充。

4 結束語

Pandas庫主要用于對二維表格式的數據清洗與整理過程。在Python進行數據處理過程中,首先可通過判斷函數篩選出數據中的空值項,以此確定空值項所在的位置和表述形態。再依據任務需求對空值項進行填充或刪除過濾,有時可能還需要去除重復的數據項等。Python的pandas擴展庫中包含了諸多的空值處理方法,主要應用于對二維表格式數據的清洗與整理過程。但在數據清洗過程中需要注意的是,經過不同操作處理或轉換后的空值可能形態各異。而在進行邏輯運算時,其比較的結果也會因該空值類型的運算特性而有所不同。

參考文獻:

[1] 蔡黎亞,劉正,唐志峰.零基礎學Python:基于PyCharm IDE[M].北京:清華大學出版社,2021.

[2] NumPy Developers. NumPy英文官網[EB/OL].[2022-10-20].https://numpy.org/doc/stable/user/index.html.

[3] Zhi Bing. pandas中文網[EB/OL].[2022-10-20].https://www.pypandas.cn/.

[4] 蔡黎亞,李淑萍,田英杰.基于大數據平臺的農業智能信息處理系統設計[J].農機化研究,2023,45(2):207-210.

[5] Python Software Foundation. Python 官網文檔 [EB/OL]. https://docs.python.org, 2023-02

[6] CAI L Y,YAO S C.Application of big data technology in blockchain computing[C]//ICAIIS 2021:2021 2nd International Conference on Artificial Intelligence and Information Systems.ACM,2021:1-3.

[7] 李慶輝.深入淺出Pandas:利用Python進行數據處理與分析[M].北京:機械工業出版社,2021.

【通聯編輯:代影】

猜你喜歡
庫中語句運算
動物城堡
動物城堡
重視運算與推理,解決數列求和題
重點:語句銜接
有趣的運算
智能盤庫在自動化立體庫中的探索和應用
如何搞定語句銜接題
ID3算法在構件庫中的應用
作文語句實錄
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合