Pandas中计算不同数据类型列的差值问题求助
问题
需要计算DataFrame中col1与col2的差值,但每行数据类型不一致,尝试用np.where实现时遇到问题,无法正确将datetime类型的差值转换为天数。
输入数据
| prod | col1 | col2 |
|---|---|---|
| One | hi | hello |
| One | 18.0 | 19.52 |
| One | 2024-02-12 00:00:00 | 2024-03-07 00:00:00 |
| two | 2024-02-12 00:00:00 | 2024-02-11 00:00:00 |
| two | in-transit | in-stock |
计算逻辑
- 若
col1或col2为字符串类型,差值返回"not same" - 若为datetime类型,差值返回
(col2 - col1).days的绝对值 - 其他数值类型直接计算
col2 - col1
尝试的错误代码
import numpy as np import pandas as pd from datetime import datetime df["difference"] = np.where( df['col2'].apply(lambda x: isinstance(x, str)), "not same", df["col2"].apply(lambda x: isinstance(x, datetime)), (df['col2'] - df['col1']).dt.days, df['old_value'] - df['new_value'])
问题点
np.where仅支持三元表达式,无法直接实现多分支判断,代码语法错误- datetime类型的差值未正确转换为天数,且未处理负数的情况(如第四行日期差为-1,预期输出为1)
预期输出
| prod | col1 | col2 | difference |
|---|---|---|---|
| One | hi | hello | not same |
| One | 18.0 | 19.52 | 1.52 |
| One | 2024-02-12 00:00:00 | 2024-03-07 00:00:00 | 25 |
| two | 2024-02-12 00:00:00 | 2024-02-11 00:00:00 | 1 |
| two | in-transit | in-stock | not same |
解决方案
方法1:逐行判断(直观易懂)
使用apply逐行处理,适合小数据量:
import pandas as pd # 先将字符串日期转换为Timestamp类型,非日期内容保持原样 df['col1'] = pd.to_datetime(df['col1'], errors='ignore') df['col2'] = pd.to_datetime(df['col2'], errors='ignore') def calc_diff(row): c1, c2 = row['col1'], row['col2'] # 判断是否为字符串 if isinstance(c1, str) or isinstance(c2, str): return "not same" # 判断是否为datetime类型 elif isinstance(c1, pd.Timestamp) and isinstance(c2, pd.Timestamp): return abs((c2 - c1).days) # 数值类型直接计算 else: return c2 - c1 df['difference'] = df.apply(calc_diff, axis=1)
方法2:多条件批量处理(高效)
使用np.select实现多分支判断,性能更优,适合大数据量:
import pandas as pd import numpy as np # 解析日期列 df['col1'] = pd.to_datetime(df['col1'], errors='ignore') df['col2'] = pd.to_datetime(df['col2'], errors='ignore') # 定义判断条件 conditions = [ (df['col1'].apply(lambda x: isinstance(x, str))) | (df['col2'].apply(lambda x: isinstance(x, str))), (df['col1'].apply(lambda x: isinstance(x, pd.Timestamp))) & (df['col2'].apply(lambda x: isinstance(x, pd.Timestamp))) ] # 对应条件的结果 choices = [ "not same", abs((df['col2'] - df['col1']).dt.days), df['col2'] - df['col1'] ] # 应用条件生成结果 df['difference'] = np.select(conditions, choices, default=df['col2'] - df['col1'])
关键说明
- 必须先通过
pd.to_datetime(..., errors='ignore')将字符串格式的日期转为pd.Timestamp,否则无法识别为datetime类型 - 预期输出中第四行取了绝对值,因此代码中加入
abs()处理负天数 np.select比嵌套np.where更清晰,适合多条件场景
内容的提问来源于stack exchange,提问作者Kavya shree
相关产品推荐
相关产品推荐

