解决Pandas DataFrame行求和为0的常见问题:混合数据类型处理指南

解决pandas dataframe行求和为0的常见问题:混合数据类型处理指南

在Pandas DataFrame中对包含混合数据类型的行进行求和时,直接使用`df.sum(axis=1, numeric_only=True)`可能因列中存在非纯数值类型而返回0。本文将详细介绍如何通过`pd.to_numeric(errors=’coerce’)`将非数值条目转换为`NaN`,然后进行精确求和,并进一步展示如何将总秒数格式化为更易读的时间间隔。

理解numeric_only参数的局限性

当我们在Pandas DataFrame中尝试对行进行求和,并期望只计算数值列时,一个常见的做法是使用df.sum(axis=1, numeric_only=True)。然而,如果DataFrame中的某些列虽然包含看起来像数字的字符串(例如’29160’),但也混杂了其他非数值字符串(例如’No hours logged’)甚至列表(例如[10:02, Odd number: missing entry]),那么numeric_only=True参数的行为可能与预期不符。

根据Pandas的官方文档,numeric_only=True的含义是“仅包含浮点、整数、布尔列”。这意味着,如果一整列中哪怕只有一个非数值类型的值(例如字符串),Pandas就会将该列视为非数值列,从而在求和时完全排除该列。在本例中,所有日期列都包含至少一个字符串值(如’No hours logged’),因此它们都被numeric_only=True排除,导致最终的total_hours列全部为0.0。

正确处理混合数据类型并进行行求和

要解决这个问题,我们需要在求和之前,显式地将目标列中的非数值条目转换为可计算的数值类型。

步骤1:数据预处理——将非数值转换为NaN

Pandas提供了pd.to_numeric()函数,它能够尝试将Series或DataFrame中的值转换为数值类型。结合errors=’coerce’参数,我们可以优雅地处理转换失败的情况:任何无法转换为数字的值都将被替换为NaN(Not a Number)。

import pandas as pd# 示例数据准备 (与原文提供的数据一致)data = {    'id': {0: 514, 1: 2414, 2: 3225, 3: 3434, 4: 3864, 5: 4716, 6: 5793},    'name': {0: 'alexis', 1: 'donald', 2: 'mackenzie', 3: 'louisa', 4: 'olga', 5: 'rick', 6: 'roberta'},    '2023-11-28': {0: 'No hours logged', 1: '29160', 2: '28500', 3: '25380', 4: '15600', 5: '30180', 6: '29220'},    '2023-11-29': {0: 'No hours logged', 1: '29160', 2: '28620', 3: '18840', 4: '19080', 5: '28800', 6: '29220'},    '2023-11-30': {0: 'No hours logged', 1: '28860', 2: '28560', 3: '26040', 4: '14400', 5: '28740', 6: '29460'},    '2023-12-01': {0: 'No hours logged', 1: '28620', 2: '28620', 3: 'No hours logged', 4: '13800', 5: '28620', 6: '29280'},    '2023-12-02': {0: 'No hours logged', 1: '[10:02, Odd number: missing entry]', 2: '28980', 3: '25560', 4: '5220', 5: '28680', 6: '29340'},    '2023-12-03': {0: 'No hours logged', 1: 'No hours logged', 2: 'No hours logged', 3: 'No hours logged', 4: '17820', 5: 'No hours logged', 6: 'No hours logged'},    '2023-12-04': {0: 'No hours logged', 1: 'No hours logged', 2: 'No hours logged', 3: 'No hours logged', 4: 'No hours logged', 5: 'No hours logged', 6: 'No hours logged'},    '2023-12-05': {0: 'No hours logged', 1: '28860', 2: '28740', 3: '24900', 4: '14400', 5: '28680', 6: '29040'},}df = pd.DataFrame(data)# 假设daily_logs列已经展开,如果未展开,需要先执行类似 df = pd.concat([df,pd.DataFrame(list(df['daily_logs']))],axis=1).drop(columns='daily_logs') 的操作# 在本示例中,我们直接使用已展开的df# 选择需要求和的列(从索引为2的列开始,即跳过'id'和'name')# 对这些列应用pd.to_numeric,并将无法转换的值设为NaN# 然后对转换后的结果进行行求和df['total_hours'] = (    df.iloc[:, 2:]      .apply(lambda x: pd.to_numeric(x, errors='coerce'))      .sum(axis=1))print(df[['id', 'name', 'total_hours']])

输出结果:

     id       name  total_hours0   514     alexis          0.01  2414     donald     144660.02  3225  mackenzie     172020.03  3434     louisa     120720.04  3864       olga     100320.05  4716       rick     173700.06  5793    roberta     175560.0

现在,total_hours列正确地显示了每行中所有可转换数值的总和。sum()函数在默认情况下会忽略NaN值,这正是我们想要的行为。

关键点:

df.iloc[:, 2:]: 确保只选择包含工作时间数据的列。iloc是基于整数位置的索引,[:, 2:]表示选择所有行,并从第3列(索引为2)开始到最后一列。请根据实际DataFrame的结构调整起始列索引。.apply(lambda x: pd.to_numeric(x, errors=’coerce’)): 这会遍历选定DataFrame中的每一列(x代表一个Series),并对该列应用pd.to_numeric函数。errors=’coerce’是这里的关键,它将所有无法解析为数字的条目(如’No hours logged’或'[10:02, Odd number: missing entry]’)转换为NaN。.sum(axis=1): 在所有相关列都被成功转换为数值类型(或NaN)之后,对这些列进行行方向(axis=1)的求和。

优化时间格式显示

原始数据中的工作时间以秒为单位记录。为了提高可读性,我们可以将总秒数转换为更友好的时间格式,例如HH:MM:SS。Pandas的pd.to_timedelta()函数非常适合这个任务。

# 将总秒数转换为timedelta对象df['total_duration'] = pd.to_timedelta(df['total_hours'], unit='s')print(df[['id', 'name', 'total_hours', 'total_duration']])

输出结果:

     id       name  total_hours total_duration0   514     alexis          0.0 0 days 00:00:001  2414     donald     144660.0 1 days 16:11:002  3225  mackenzie     172020.0 1 days 23:47:003  3434     louisa     120720.0 1 days 09:32:004  3864       olga     100320.0 1 days 03:52:005  4716       rick     173700.0 2 days 00:15:006  5793    roberta     175560.0 2 days 00:46:00

total_duration列现在以timedelta64[ns]类型存储,并以天、小时、分钟和秒的格式显示,极大地提升了数据的可读性。

完整的解决方案函数

将上述步骤封装到一个函数中,可以方便地应用于任何类似的DataFrame:

def calculate_total_working_hours(df_input):    """    计算DataFrame中每行的总工作时间(秒),并添加一个格式化的时间持续时间列。    参数:    df_input (pd.DataFrame): 包含工作时间数据的DataFrame。                             假设工作时间数据从第三列(索引2)开始。    返回:    pd.DataFrame: 包含 'total_hours' (总秒数) 和 'total_duration' (时间持续时间) 列的DataFrame。    """    df = df_input.copy() # 避免修改原始DataFrame    # 1. 选择需要求和的列并转换为数值,将非数值强制转换为NaN    # 注意:这里假设 'id' 和 'name' 是前两列,实际使用时请根据DataFrame结构调整列索引    df['total_hours'] = (        df.iloc[:, 2:]          .apply(lambda x: pd.to_numeric(x, errors='coerce'))          .sum(axis=1)    )    # 2. 将总秒数转换为timedelta格式    df['total_duration'] = pd.to_timedelta(df['total_hours'], unit='s')    return df# 使用示例df_results = calculate_total_working_hours(df.copy()) # 传入原始df的副本print(df_results[['id', 'name', 'total_hours', 'total_duration']])

注意事项

列索引的准确性: 在使用df.iloc[:, 2:]时,请务必确认2是您希望开始求和的列的正确索引。如果您的DataFrame结构不同,例如有更多的非数值前置列,您需要调整这个索引。errors=’coerce’的副作用: errors=’coerce’会将所有无法转换为数值的值替换为NaN。这意味着,如果您的数据中存在其他有意义的非数值字符串(例如,表示特殊状态的文本,而非简单的“未记录”),并且您希望保留这些信息或以不同方式处理它们,那么这种方法可能需要进一步细化。但对于本例中的“No hours logged”和格式错误的列表,这是一种非常有效的处理方式。数据类型一致性: 理想情况下,数据在加载到DataFrame之前就应该进行清理,确保数值列只包含数值。但在面对真实世界中的混合数据时,上述方法提供了强大的弹性。

总结

在Pandas中对DataFrame行进行求和时,如果遇到因混合数据类型导致numeric_only=True失效并返回0的情况,核心解决方案是:

精确选择需要求和的列。使用pd.to_numeric(errors=’coerce’)将这些列中的非数值条目统一转换为NaN。然后对转换后的结果执行sum(axis=1),Pandas会自动忽略NaN值。对于时间数据,可以进一步利用pd.to_timedelta()进行格式化,提升数据可读性。

掌握这些技巧,将使您在处理真实世界中复杂且不一致的数据时,能够更高效、更准确地进行数据分析和计算。

以上就是解决Pandas DataFrame行求和为0的常见问题:混合数据类型处理指南的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1381156.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 22:42:48
下一篇 2025年12月14日 22:43:04

相关推荐

  • Python实现文本文件行号自动递增写入教程

    本教程详细介绍了如何使用python向文本文件追加数据时,自动为每行添加一个格式化的递增序列号。通过巧妙利用文件读写模式和文件指针定位,我们能够准确获取现有行数,并生成如”001″、”002″等格式的序列号,确保每次写入的数据都带有正确的行号。 Pyt…

    好文分享 2025年12月14日
    000
  • 解决cuDF与Numba集成中的NVVM缺失问题:CUDA开发环境配置指南

    在使用cuDF与Numba进行GPU加速计算时,若遇到FileNotFoundError: /usr/local/cuda/nvvm/lib64错误,通常是由于Docker环境中使用了精简的CUDA“runtime”镜像。该镜像缺少Numba进行即时编译(JIT)所需的NVVM等开发工具。解决此问题…

    2025年12月14日
    000
  • 使用SQLAlchemy声明式ORM指定数据库表Schema的教程

    本文详细介绍了如何在sqlalchemy声明式orm中为数据库表指定特定的schema,而非使用数据库的默认schema。通过利用模型类中的`__table_args__`属性,并设置`schema`参数,开发者可以灵活地控制表在不同命名空间中的创建位置。文章将提供具体的代码示例和使用指南,并探讨此…

    2025年12月14日
    000
  • 高效合并Python中嵌套字典的实用教程

    本文旨在提供一种高效且pythonic的方法来合并两个或多个可能包含嵌套结构的字典,同时确保所有数据得以保留。通过利用python字典的`setdefault()`和`update()`方法,可以优雅地处理键冲突并实现深层合并(针对第一层嵌套),适用于处理大型数据集。 在Python编程中,合并字典…

    2025年12月14日
    000
  • 在WSL Conda环境中安装LightGBM GPU版本:CUDA加速指南

    本文旨在提供在wsl conda环境下安装lightgbm cuda gpu加速版本的详细教程。文章将明确区分opencl和cuda两种gpu加速类型,并重点介绍通过官方脚本从源码构建或使用pip从pypi安装cuda版本lightgbm的两种推荐方法。此外,还将指导如何在python代码中正确配置…

    2025年12月14日
    000
  • 深入理解vgamepad库:正确模拟虚拟手柄按键操作

    使用`vgamepad`库模拟虚拟手柄按键时,`press_button()`函数要求传入`xusb_button`枚举常量,而非直接的整数值。直接使用整数虽然可能不报错,但无法实现预期的按键效果。本文将深入解析`vgamepad`库的正确按键模拟方法,指导开发者有效利用其功能。 在使用 Pytho…

    2025年12月14日
    000
  • Python中交互式控制子进程:非阻塞I/O与生命周期管理

    本文探讨了在python中通过`subprocess`模块实现对外部python脚本的交互式控制。针对传统阻塞式i/o的局限性,我们介绍了一种结合`threading`和`queue`的非阻塞读取策略,以实现对子进程标准输出和错误流的异步获取。教程将展示如何启动、管理子进程的生命周期,并处理其输出,…

    2025年12月14日
    000
  • Python CSV写入格式化问题:使用标准库csv模块避免常见陷阱

    手动拼接字符串来生成csv行是一种常见的错误源,尤其当数据字段本身包含逗号或特殊字符时,极易导致格式错乱。本文将深入探讨手动csv写入的陷阱,并推荐使用python标准库中的csv模块,通过其自动引用和转义机制,确保数据以正确的csv格式写入,从而避免数据字段混淆的问题。 手动CSV拼接的陷阱 在处…

    2025年12月14日
    000
  • Telethon中移除消息图片:event.edit的局限性与消息删除策略

    本教程探讨了在telethon中从消息中移除图片的方法。针对用户尝试使用`event.edit(file=none)`无效的问题,文章解释了`event.edit`在移除现有媒体方面的局限性。核心解决方案是利用telethon的`delete_messages`方法来彻底删除包含图片的原始消息,并提…

    2025年12月14日
    000
  • 在Rust的pyO3中检查Python自定义类的实例类型

    在使用Rust的pyO3库与Python交互时,若需判断一个`PyAny`对象是否为Python自定义类的实例,应避免直接使用`PyTypeInfo`和`is_type_of`检查实例。正确的做法是先通过`py.import`和`getattr`获取到Python自定义类的类型对象,然后调用`PyA…

    2025年12月14日
    000
  • Python 技巧:高效反转嵌套字典,避免内存溢出

    本文旨在解决在 Python 中反转大型嵌套字典时可能出现的内存问题。我们将探讨如何利用生成器和自定义字典类 ReverseDict,以实现高效且节省内存的反转操作,避免一次性加载整个字典到内存中。 在处理大型数据集时,反转嵌套字典可能会导致内存溢出。传统的反转方法通常需要将整个字典加载到内存中,这…

    2025年12月14日
    000
  • Python实战:为文本文件新增行自动添加序列号

    本教程详细介绍了如何使用python为文本文件的新增行自动添加一个带零填充的顺序号。通过巧妙运用文件读写模式(a+)、文件指针定位和f-string格式化,我们能够高效地在文件末尾追加新数据,并确保每行都有唯一的、格式化的序列标识符,从而实现日志或数据记录的自动化编号。 在日常的编程任务中,我们经常…

    2025年12月14日
    000
  • Tkinter Menubutton与Menu正确关联指南

    本教程详细探讨了Tkinter中`Menubutton`无法显示其关联`Menu`的常见问题。核心在于`Menu`组件的父级设置不当。文章将通过分析错误原因,提供正确的父子关系建立方法,并辅以完整的代码示例,确保`Menubutton`能够正确弹出其菜单,从而帮助开发者构建功能完善的用户界面。 Tk…

    2025年12月14日
    000
  • Polars LazyFrames中高效实现除索引列外的多列乘法操作

    本教程详细介绍了如何在polars lazyframes中对两个数据帧进行除指定索引列(如时间列)外的所有数值列执行元素级乘法操作。通过利用polars的结构体(`struct`)表达式、高效的连接(`join`)机制以及解嵌套(`unnest`)功能,我们能够优雅地解决在pandas中常见的跨da…

    2025年12月14日
    000
  • Python子进程的非阻塞I/O与生命周期管理

    本教程详细探讨了如何在python中使用`subprocess`模块实现对外部进程(尤其是python脚本)的非阻塞i/o操作及生命周期管理。文章首先指出传统`readline()`方法的阻塞问题,随后介绍了一种基于多线程和队列的解决方案,通过异步读取标准输出和标准错误流,并在进程超时或结束后统一收…

    2025年12月14日
    000
  • Python字符串处理:从指定关键词处截取右侧内容

    本文详细介绍了在Python中如何高效地从字符串中提取指定关键词右侧的内容。针对语音转文本等场景中常见的需求,文章通过对比传统方法与正则表达式,重点讲解了如何使用`re`模块的`sub()`和`search()`函数,以简洁、健壮的方式实现字符串的精确截取,并涵盖了关键词存在性检查等实用技巧,确保处…

    2025年12月14日
    000
  • 解决Tkinter Menubutton菜单不显示问题:正确关联子菜单

    本教程旨在解决tkinter应用中menubutton无法正确显示其关联menu的常见问题。核心在于menu组件的父级关系设置不当。我们将详细解释如何通过将menu创建为menubutton的子组件来建立正确的关联,从而确保菜单能够按预期弹出并正常工作。 理解Tkinter Menubutton与M…

    2025年12月14日
    000
  • Python面向对象:深入理解继承中父类属性的初始化与传递

    本文旨在解析python类继承中,子类如何正确初始化和访问父类属性的常见误区。我们将探讨`super().__init__()`的工作机制,以及在子类实例化时如何有效传递参数以定制继承属性。文章还将对比“继承”与“组合”两种设计模式,指导开发者根据实际需求选择最合适的策略,确保父类属性在子类中得到预…

    2025年12月14日
    000
  • 数据库中检查重复项并报告是否创建了新记录

    本文旨在提供一种使用单个SQL查询在数据库中检查重复记录并报告新记录是否创建的方法。通过在`name`列上创建唯一索引,并结合`ON CONFLICT DO NOTHING`语句,可以有效地避免重复插入,并根据操作结果返回相应的信息。本文将详细介绍实现步骤,并提供示例代码。 在数据库操作中,经常需要…

    2025年12月14日
    000
  • Python中print(input())赋值导致变量为None的解析与修正

    本文深入探讨了python中将`print(input())`的执行结果赋值给变量时,变量为何会变为`none`,并最终导致`typeerror`的常见问题。文章详细解释了`input()`和`print()`函数的返回值机制,并通过具体代码示例展示了错误产生的原因及其正确的修正方法,旨在帮助开发者…

    2025年12月14日
    000

发表回复

登录后才能评论
关注微信