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算法在构件库中的应用
作文语句实录