0

0

Pandas整数类型默认行为与测试断言策略

心靈之曲

心靈之曲

发布时间:2025-09-25 12:10:24

|

298人浏览过

|

来源于php中文网

原创

pandas整数类型默认行为与测试断言策略

本文探讨了在64位Python环境中,Pandas Series在显式指定dtype=int时可能默认使用int32而非int64的问题,及其对DataFrame测试中严格类型检查的影响。文章提出了一种自定义的assert_frame_equiv函数作为解决方案,通过在比较前统一等效数据类型,实现了更灵活且鲁棒的DataFrame断言,避免了手动类型转换或完全禁用类型检查的弊端。

Pandas整数类型默认行为概述

在64位Python环境中,我们通常期望Pandas在处理整数数据时默认使用int64类型,以充分利用系统架构的优势并避免潜在的溢出问题。然而,实际操作中可能会观察到一些不一致的行为。例如,当创建一个pd.Series并显式指定dtype=int时,其数据类型可能被推断为int32,即使在不指定dtype而让Pandas自动推断时,它可能正确地选择int64。

import pandas as pd
import platform
import sys

# 验证Python环境为64位
assert platform.architecture()[0] == "64bit"
assert sys.maxsize > 2**32
print(f"Python环境:{platform.architecture()[0]}")

# 显式指定 dtype=int
series_int_explicit = pd.Series([1, 2, 3], dtype=int)
print(f"pd.Series([1,2,3], dtype=int) 的类型: {series_int_explicit.dtype}")

# 不指定 dtype,让Pandas自动推断
series_int_inferred = pd.Series([1, 2, 3])
print(f"pd.Series([1,2,3]) 的类型: {series_int_inferred.dtype}")

从上述代码的输出可以看出,即使在64位环境中,dtype=int的显式指定有时会导致Pandas选择int32,而自动推断则可能选择int64。这种差异本身可能不是一个功能性错误,因为int32足以存储大部分常见整数值,但在进行严格的DataFrame比较测试时,它会成为一个障碍。

严格的类型检查与测试挑战

Pandas提供了一个强大的测试工具pd.testing.assert_frame_equal,用于比较两个DataFrame是否相等。默认情况下,这个函数会执行非常严格的检查,包括数据类型(dtype)的精确匹配。这意味着,如果一个DataFrame的某一列是int32而另一个DataFrame的对应列是int64,即使它们包含相同的数值,assert_frame_equal也会因为类型不匹配而抛出AssertionError。

import pandas as pd

df_int32 = pd.DataFrame({'IntCol': [1, 2, 3], 'FloatCol': [0.5, 1.5, 2.5]})
df_int32['IntCol'] = df_int32['IntCol'].astype('int32')
df_int32['FloatCol'] = df_int32['FloatCol'].astype('float32')

df_int64 = pd.DataFrame({'IntCol': [1, 2, 3], 'FloatCol': [0.5, 1.5, 2.5]})
df_int64['IntCol'] = df_int64['IntCol'].astype('int64')
df_int64['FloatCol'] = df_int64['FloatCol'].astype('float64')

try:
    pd.testing.assert_frame_equal(df_int32, df_int64)
    print("DataFrame相等(包含类型)")
except AssertionError as err:
    print(f"断言失败:\n{err}")

输出清晰地表明,int32和int64被视为不同的类型,导致断言失败。虽然assert_frame_equal允许通过设置check_dtype=False来禁用类型检查,但这会使得测试失去对数据类型完整性的验证能力,从而可能掩盖潜在的问题。在许多场景下,我们希望验证数据内容和“等效”的数据类型,而非“精确”的数据类型。

自定义DataFrame等效性断言函数

为了解决上述问题,我们可以创建一个自定义的断言函数,它在比较DataFrame之前,将等效的数据类型(如int32和int64,或float32和float64)统一为同一种类型。这样既能保留类型检查的价值,又能允许在类型等效但具体位数不同的情况下通过测试。

以下是assert_frame_equiv函数的实现:

import pandas as pd
import numpy as np

def assert_frame_equiv(left: pd.DataFrame, right: pd.DataFrame) -> None:
    """
    在比较前将等效数据类型统一,以实现更灵活的DataFrame等效性断言。

    参数:
        left (pd.DataFrame): 左侧DataFrame。
        right (pd.DataFrame): 右侧DataFrame。

    Raises:
        AssertionError: 如果DataFrame不相等。
    """
    # 1. 首先检查列名是否相同(顺序不重要)
    pd.testing.assert_index_equal(left.columns, right.columns, check_order=False)

    # 创建DataFrame的副本以避免修改原始数据
    left_copy = left.copy()
    right_copy = right.copy()

    # 2. 遍历列,如果数据类型等效,则统一为右侧DataFrame的类型
    for col_name in left_copy.columns:
        lcol = left_copy[col_name]
        rcol = right_copy[col_name]

        # 检查是否为整数类型且等效(如int32 vs int64)
        is_lcol_int = pd.api.types.is_integer_dtype(lcol)
        is_rcol_int = pd.api.types.is_integer_dtype(rcol)

        # 检查是否为浮点类型且等效(如float32 vs float64)
        is_lcol_float = pd.api.types.is_float_dtype(lcol)
        is_rcol_float = pd.api.types.is_float_dtype(rcol)

        if (is_lcol_int and is_rcol_int) or (is_lcol_float and is_rcol_float):
            # 如果是等效的整数或浮点类型,则将左侧列转换为右侧列的dtype
            left_copy[col_name] = lcol.astype(rcol.dtype)
        # 对于其他不兼容或非数值类型,保持不变,让assert_frame_equal处理
        # 例如,如果一边是int,另一边是float,这里不会自动转换,
        # pd.testing.assert_frame_equal会因dtype不匹配而失败,这是期望的行为。

    # 3. 最后使用pd.testing.assert_frame_equal进行最终比较
    # check_like=True 允许列和行的顺序不同,但我们已经在前面检查了列名。
    # 这里的关键是经过类型统一后,dtype将匹配。
    return pd.testing.assert_frame_equal(left_copy, right_copy, check_like=True)

函数逻辑说明:

Runway
Runway

Runway是一个AI创意工具平台,它提供了一系列强大的功能,旨在帮助用户在视觉内容创作、设计和开发过程中提高效率和创新能力。

下载
  1. 列名检查: 首先确保两个DataFrame具有相同的列名,这是进行后续比较的基础。check_order=False允许列顺序不同。
  2. 创建副本: 为了不修改原始DataFrame,对输入DataFrame进行深拷贝。
  3. 类型统一: 遍历DataFrame的每一列。如果两列都是整数类型(int32、int64等)或都是浮点类型(float32、float64等),则将左侧列的数据类型强制转换为右侧列的数据类型。这确保了在数值类型等效的情况下,它们的dtype能够匹配。pd.api.types.is_integer_dtype和pd.api.types.is_float_dtype是判断数据类型是否为整数或浮点的推荐方法。
  4. 最终断言: 在类型统一之后,调用标准的pd.testing.assert_frame_equal进行最终的比较。此时,由于等效类型已统一,dtype检查将通过。

示例与应用

让我们使用之前定义的df_int32和df_int64来测试assert_frame_equiv函数。

# 重新定义DataFrame以确保干净状态
a = pd.DataFrame({'Int': [1, 2, 3], 'Float': [0.57, 0.179, 0.213]})
# 强制为32位类型
b = a.copy()
b['Int'] = b['Int'].astype('int32')
b['Float'] = b['Float'].astype('float32')
# 强制为64位类型
c = a.copy()
c['Int'] = c['Int'].astype('int64')
c['Float'] = c['Float'].astype('float64')

print("使用pd.testing.assert_frame_equal进行比较:")
try:
    pd.testing.assert_frame_equal(b, c)
    print('成功:DataFrame相等')
except AssertionError as err:
    print(f'失败:\n{err}')

print("\n使用assert_frame_equiv进行比较:")
try:
    assert_frame_equiv(b, c)
    print('成功:DataFrame等效')
except AssertionError as err:
    print(f'失败:\n{err}')

通过assert_frame_equiv函数,尽管b和cDataFrame在内部使用了不同的整数和浮点位数,但由于它们的数据内容和等效类型一致,测试成功通过。这提供了一种在测试中处理灵活数据类型要求而又不完全牺牲类型检查的有效方法。

总结与展望

在64位Python环境中,Pandas Series在显式指定dtype=int时可能默认使用int32,这在与默认推断的int64或其他显式转换的类型进行严格比较时会引发问题。标准的pd.testing.assert_frame_equal函数由于其严格的类型检查机制,无法直接处理int32与int64之间的等效性。

本文提出的assert_frame_equiv自定义函数,通过在比较前智能地统一等效数值类型,为解决这一测试挑战提供了一个健壮且灵活的解决方案。它允许开发者在测试中关注数据内容的等效性,同时保留对数据类型大类的验证,避免了手动频繁转换类型或完全禁用类型检查的麻烦。

值得一提的是,Pandas社区也认识到这种需求,并已存在关于在pd.testing.assert_frame_equal中添加类似check_dtype='equiv'选项的功能请求(如GitHub issue #59182)。这表明未来Pandas版本可能会原生支持这种更灵活的类型比较方式,届时自定义函数的使用场景可能会有所变化。但在那之前,assert_frame_equiv提供了一个即时可用的强大工具。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

760

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

639

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

763

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

619

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1285

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

709

2023.08.11

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

11

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 5.1万人学习

Django 教程
Django 教程

共28课时 | 3.2万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号