
在Pandas DataFrame中对包含混合数据类型的行进行求和时,直接使用`df.sum(axis=1, numeric_only=True)`可能因列中存在非纯数值类型而返回0。本文将详细介绍如何通过`pd.to_numeric(errors='coerce')`将非数值条目转换为`NaN`,然后进行精确求和,并进一步展示如何将总秒数格式化为更易读的时间间隔。
当我们在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。
要解决这个问题,我们需要在求和之前,显式地将目标列中的非数值条目转换为可计算的数值类型。
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_hours 0 514 alexis 0.0 1 2414 donald 144660.0 2 3225 mackenzie 172020.0 3 3434 louisa 120720.0 4 3864 olga 100320.0 5 4716 rick 173700.0 6 5793 roberta 175560.0
现在,total_hours列正确地显示了每行中所有可转换数值的总和。sum()函数在默认情况下会忽略NaN值,这正是我们想要的行为。
原始数据中的工作时间以秒为单位记录。为了提高可读性,我们可以将总秒数转换为更友好的时间格式,例如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_duration 0 514 alexis 0.0 0 days 00:00:00 1 2414 donald 144660.0 1 days 16:11:00 2 3225 mackenzie 172020.0 1 days 23:47:00 3 3434 louisa 120720.0 1 days 09:32:00 4 3864 olga 100320.0 1 days 03:52:00 5 4716 rick 173700.0 2 days 00:15:00 6 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']])在Pandas中对DataFrame行进行求和时,如果遇到因混合数据类型导致numeric_only=True失效并返回0的情况,核心解决方案是:
掌握这些技巧,将使您在处理真实世界中复杂且不一致的数据时,能够更高效、更准确地进行数据分析和计算。
以上就是解决Pandas DataFrame行求和为0的常见问题:混合数据类型处理指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号