Python
解密 Pandas 的 NaN: 初学者指南

解密 Pandas 的 NaN: 初学者指南

MoeNagy Dev

了解 pandas.isnull() 和 pandas.isna() 的基础知识

探索 pandas is nan 概念

什么是 pandas.isnull() 和 pandas.isna()?

pandas.isnull()pandas.isna() 函数用于识别 pandas DataFrame 或 Series 中的缺失值。这些函数返回一个与输入数据形状相同的布尔掩码,其中 True 表示缺失值,False 表示非缺失值。

下面是一个示例:

import pandas as pd
 
# 创建一个示例 DataFrame
df = pd.DataFrame({'A': [1, 2, None, 4], 'B': [5, None, 7, 8]})
 
# 检查缺失值
print(df.isnull())
#       A     B
# 0  False False
# 1  False  True
# 2   True False
# 3  False False

在上述示例中,df.isnull() 方法返回一个布尔 DataFrame,指示每个单元格中是否存在缺失值。

理解 pandas.isnull() 和 pandas.isna() 的区别

pandas.isnull()pandas.isna() 函数基本上是相同的,可以互换使用。两个函数都用于识别 DataFrame 或 Series 中的缺失值。

主要区别在于 pandas.isna() 是一种更现代和推荐的检查缺失值的方式,因为它提供了更好的支持,可以处理不同的数据类型,包括 NumPy 的 NaN 值、Python 的 None 以及 Pandas 自己的缺失值指示符。

在大多数情况下,您可以使用 pandas.isna() 代替 pandas.isnull() 而不会出现任何问题。但是,如果您需要与较旧版本的 Pandas 保持兼容性,则可能需要使用 pandas.isnull()

使用 pandas is nan 处理缺失数据

一旦您已经识别出. 使用 pandas.isnull()pandas.isna() 检测缺失值,您可以使用各种方法来处理它们。一些常见的技术包括:

  1. 替换缺失值:您可以用特定值或根据数据计算的值来替换缺失值。
df['A'] = df['A'].fillna(0)  # 将列 'A' 中的缺失值替换为 0
  1. 删除包含缺失值的行或列:
df = df.dropna(subset=['A', 'B'])  # 删除 'A' 或 'B' 列中存在缺失值的行
  1. 填充缺失值:您可以使用平均值、中位数或众数等各种填充技术来填充缺失值。
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean')
df[['A', 'B']] = imputer.fit_transform(df[['A', 'B']])
  1. 插值缺失值:对于时间序列数据,您可以使用插值来根据周围的数据点估计缺失值。
df = df.interpolate()  # 在 DataFrame 中插值缺失值

在数据操作中使用 pandas.isnull() 和 pandas.isna()

识别 DataFrame 中的缺失值

您可以使用 pandas.isnull()pandas.isna() 函数来识别 DataFrame 中的缺失值:

import pandas as pd
 
# 创建一个示例 DataFrame
df = pd.DataFrame({'A': [1, 2, None, 4], 'B': [5, None, 7, 8]})
 
# 检查缺失值
print(df.isnull())
#       A     B
# 0  False False
# 1  False  True
# 2   True False
# 3  False False

返回的布尔型 DataFrame 指示每个单元格是否存在缺失值。

使用 pandas.isnull() 和 pandas.isna() 处理缺失值

您可以使用 pandas.isnull()pandas.isna() 返回的布尔掩码来对 DataFrame 执行各种操作,例如:

  1. 替换缺失值:
df['A'] = df['A'].fillna(0)
df['B'] = df['B'].fillna(df['B'].mean())
  1. 删除包含缺失值的行或列:
```python
df = df.dropna(subset=['A', 'B'])  # 删除 'A' 或 'B' 列中有任何缺失值的行
df = df.dropna(how='all')  # 删除所有值都缺失的行
df = df.dropna(axis=1)  # 删除有任何缺失值的列
  1. 填充缺失值:
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean')
df[['A', 'B']] = imputer.fit_transform(df[['A', 'B']])

用特定值替换缺失值

您可以使用 fillna() 方法用特定值替换缺失值:

# 将 'A' 列的缺失值替换为 0
df['A'] = df['A'].fillna(0)
 
# 将 'B' 列的缺失值替换为该列的平均值
df['B'] = df['B'].fillna(df['B'].mean())

删除包含缺失值的行或列

您可以使用 dropna() 方法删除包含缺失值的行或列:

# 删除 'A' 或 'B' 列中有任何缺失值的行
df = df.dropna(subset=['A', 'B'])
 
# 删除所有值都缺失的行
df = df.dropna(how='all')
 
# 删除有任何缺失值的列
df = df.dropna(axis=1)

使用 pandas.isnull() 的高级技术

将 pandas.isnull() 和 pandas.isna() 与其他 DataFrame 方法结合使用

您可以将 pandas.isnull()pandas.isna() 函数与其他 DataFrame 方法结合使用,执行更复杂的操作。例如,您可以在条件过滤、数据转换等中使用它们。

# 过滤 'A' 列中有缺失值的行
filtered_df = df[df['A'].isnull()]
 
# 用 'B' 列非缺失值的中位数填充缺失值
df['B'] = df['B'].fillna(df['B'].median())
 
# 创建一个新列,指示 'A' 列是否有缺失值
df['has_missing_A'] = df['A'].isnull()

基于缺失值的条件过滤

您可以使用 pandas.isnull()pandas.isna() 返回的布尔掩码进行条件过滤:

# 过滤.

过滤掉 'A' 列中有缺失值的行

filtered_df = df[df['A'].isnull()]

过滤掉 'B' 列中没有缺失值的行

non_missing_df = df[~df['B'].isnull()]

使用各种技术填补缺失值

除了简单的值替换外,您还可以使用更高级的技术来填补缺失值,例如:

  1. 均值/中位数/众数填补:
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean')
df[['A', 'B']] = imputer.fit_transform(df[['A', 'B']])
  1. KNN 填补:
from fancyimpute import KNNImputer
imputer = KNNImputer(n_neighbors=5)
df[['A', 'B']] = imputer.fit_transform(df[['A', 'B']])
  1. 迭代填补:
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
imputer = IterativeImputer()
df[['A', 'B']] = imputer.fit_transform(df[['A', 'B']])

这些高级填补技术在处理更复杂的缺失数据模式或相互依赖的特征时特别有用。

探索 pandas.isna() 的具体使用案例

使用 pandas.isna() 清洗和预处理数据

pandas.isnull()pandas.isna() 的主要使用案例之一是在数据分析或机器学习管道的数据清洗和预处理阶段。这些函数可以帮助您识别和处理缺失值,这是确保数据质量和可靠性的关键步骤。

以下是一个使用 pandas.isna() 清洗和预处理数据集的示例:

import pandas as pd
 
# 加载数据集
df = pd.read_csv('dataset.csv')
 
# 识别缺失值
missing_values = df.isna().sum()
print(missing_values)
 
# 删除任何列中有缺失值的行
df = df.dropna()
 
# 用中位数填补 'age' 列的缺失值
df['age'] = df['age'].fillna(df['age'].median())
 
# 创建一个新列,指示 'income' 列中是否有缺失值
df['has_m.
```python
df['missing_income'] = df['income'].isna()

在这个例子中,我们首先使用 df.isna().sum() 来识别每个列中缺失值的数量。然后,我们删除任何列中存在缺失值的行,并用中位数填充 'age' 列中的缺失值。最后,我们创建一个新列,指示 'income' 列中是否存在缺失值。

处理时间序列数据中的缺失值

在处理时间序列数据时,处理缺失值可能特别具有挑战性。pandas.isnull()pandas.isna() 可以与其他时间序列特定的函数结合使用,来处理这些数据集中的缺失值。

import pandas as pd
 
# 创建一个示例时间序列 DataFrame
df = pd.DataFrame({'A': [1, 2, None, 4, 5], 'B': [5, None, 7, 8, 9]},
                  index=pd.date_range('2022-01-01', periods=5, freq='D'))
 
# 识别缺失值
print(df.isna())
#             A     B
# 2022-01-01 False False
# 2022-01-02 False  True
# 2022-01-03  True False
# 2022-01-04 False False
# 2022-01-05 False False
 
# 插值缺失值
df = df.interpolate()
print(df)
#             A    B
# 2022-01-01  1  5.0
# 2022-01-02  2  6.0
# 2022-01-03  3  7.0
# 2022-01-04  4  8.0
# 2022-01-05  5  9.0

在这个例子中,我们创建了一个包含缺失值的示例时间序列 DataFrame。然后,我们使用 interpolate() 方法来估计缺失值,基于周围的数据点。

处理机器学习模型中的缺失值

缺失值可能会对机器学习模型的性能产生重大影响。pandas.isnull()pandas.isna() 可用于在将数据输入机器学习模型之前识别和处理缺失值。

import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LinearRegression
 
# 加载数据集
df = pd.read_csv('dataset.csv')
 
# 识别缺失值
missing_values = df.isna().sum()
print(missing_values)
 
# 处理缺失值
```使用平均值插补填充缺失值
imputer = SimpleImputer(strategy='mean')
X = imputer.fit_transform(df.drop('target', axis=1))
y = df['target']
 
# 训练线性回归模型
model = LinearRegression()
model.fit(X, y)

在这个例子中,我们首先使用 df.isna().sum() 识别数据集中的缺失值。然后我们使用 scikit-learn 中的 SimpleImputer 来使用每个特征的平均值来填充缺失值。最后,我们在填充后的数据上训练一个线性回归模型。

处理缺失值是为机器学习模型准备数据的关键步骤,因为许多模型无法直接处理缺失值。通过使用 pandas.isnull()pandas.isna(),您可以确保

函数

函数是执行特定任务的可重用代码块。它们可以接受输入,执行操作,并返回输出。函数有助于组织和模块化您的代码,使其更具可读性和可维护性。

下面是一个简单的计算矩形面积的函数示例:

def calculate_area(length, width):
    """
    计算矩形的面积。
 
    参数:
        length (float): 矩形的长度。
        width (float): 矩形的宽度。
 
    返回:
        float: 矩形的面积。
    """
    area = length * width
    return area
 
# 使用
rectangle_length = 5.0
rectangle_width = 3.0
rectangle_area = calculate_area(rectangle_length, rectangle_width)
print(f"矩形的面积是 {rectangle_area} 平方单位。")

在这个例子中, calculate_area 函数接受两个参数 lengthwidth,并返回计算出的面积。该函数还包含一个文档字符串,提供了函数的简要描述以及预期的参数和返回值。

模块和包

Python 的标准库提供了广泛的内置模块,这些模块是函数、类和变量的集合。您也可以创建自己的模块。 这里有一个如何创建简单模块的示例:

# my_module.py
def greet(name):
    """
    向给定名字的人问候。
 
    参数:
        name (str): 要问候的人的名字。
 
    返回:
        str: 问候消息。
    """
    return f"你好, {name}!"

要使用这个模块,你可以在另一个 Python 文件中导入它:

# main.py
import my_module
 
greeting = my_module.greet("Alice")
print(greeting)  # 输出: 你好, Alice!

包是组织模块的一种方式,它们被组织成目录结构。这里有一个创建简单包的示例:

my_package/
    __init__.py
    utils/
        __init__.py
        math_functions.py
        string_functions.py

__init__.py 文件用于定义包的结构,以及当导入包时应该导入哪些模块。

# my_package/utils/math_functions.py
def add(a, b):
    return a + b
 
def subtract(a, b):
    return a - b
# main.py
from my_package.utils import math_functions
 
result = math_functions.add(5, 3)
print(result)  # 输出: 8

异常

异常是程序执行过程中出现的事件,会中断程序的正常执行流程。Python 内置了异常处理机制,允许你处理和管理这些意外情况。

这里有一个处理 ZeroDivisionError 异常的示例:

def divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("错误: 除数为零。")
        return None
 
print(divide(10, 2))  # 输出: 5.0
print(divide(10, 0))  # 输出: 错误: 除数为零。

在这个例子中,divide 函数尝试将第一个参数除以第二个参数。如果出现 ZeroDivisionError 异常,程序会打印一条错误消息并返回 None。 当 DivisionError 发生时,该函数捕获异常并打印错误消息,然后返回 None

您也可以通过定义继承自内置 Exception 类或其子类的自定义异常类来创建自定义异常。

class NegativeValueError(Exception):
    """当遇到负值时引发。"""
    pass
 
def calculate_square_root(number):
    if number < 0:
        raise NegativeValueError("无法计算负数的平方根。")
    return number ** 0.5
 
try:
    print(calculate_square_root(16))  # 输出: 4.0
    print(calculate_square_root(-4))
except NegativeValueError as e:
    print(e)  # 输出: 无法计算负数的平方根。

在这个例子中,calculate_square_root 函数在输入数字为负数时引发自定义的 NegativeValueError 异常。该异常在 try-except 块中被捕获和处理。

文件 I/O

Python 提供了内置的函数和方法来读取和写入文件。最常见的处理文件的方式是使用 open() 函数,它返回一个文件对象,可用于执行各种文件操作。

下面是一个读取和写入文件的示例:

# 写入文件
with open("example.txt", "w") as file:
    file.write("这是第一行。\n")
    file.write("这是第二行。\n")
 
# 读取文件
with open("example.txt", "r") as file:
    contents = file.read()
    print(contents)
    # 输出:
    # 这是第一行。
    # 这是第二行。

在这个例子中,open() 函数用于以写模式 ("w") 打开名为 "example.txt" 的文件,并写入两行文本。然后,文件以读模式 ("r") 打开,内容被读取并打印。

使用 with 语句可以确保即使发生异常,文件也会被正确关闭。

您也可以逐行读取文件。 使用 for 循环逐行读取文件:

with open("example.txt", "r") as file:
    for line in file:
        print(line.strip())
    # 输出:
    # This is the first line.
    # This is the second line.

在这个例子中,strip() 方法用于删除每行末尾的换行符。

正则表达式

正则表达式是一种强大的模式匹配和文本操作工具。Python 的内置 re 模块提供了一组全面的函数和方法来处理正则表达式。

以下是一个使用正则表达式验证电子邮件地址的例子:

import re
 
def is_valid_email(email):
    """
    检查给定的电子邮件地址是否有效。
 
    参数:
        email (str): 要验证的电子邮件地址。
 
    返回:
        bool: 如果电子邮件地址有效,返回 True,否则返回 False。
    """
    pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
    if re.match(pattern, email):
        return True
    else:
        return False
 
print(is_valid_email("example@example.com"))  # 输出: True
print(is_valid_email("invalid_email"))  # 输出: False

在这个例子中,is_valid_email 函数接受一个电子邮件地址作为输入,并使用一个正则表达式模式来检查该电子邮件地址是否有效。re.match() 函数用于将模式应用于电子邮件地址并返回一个布尔结果。

正则表达式可用于广泛的文本处理任务,例如:

  • 在文本中搜索特定模式
  • 从文本中提取信息
  • 根据模式替换或修改文本
  • 验证输入数据

虽然正则表达式非常强大,但对于更高级的用例来说,它们也可能变得复杂和难以阅读。重要的是要在使用正则表达式和其他文本处理技术(如字符串操作和内置字符串方法)之间保持平衡。

结论

在本教程中,您已经学习了一些中级 Python 编程的相关知识。 记住,提高 Python 技能的最佳方式是实践、实验和持续学习。探索 Python 标准库,阅读文档,并参与在线社区,以扩展您的知识并跟上 Python 生态系统的最新发展。

祝您编码愉快!

MoeNagy Dev.