如何高效计算Pandas中Datetime列按日统计的差值?
高效计算Datetime列的按日差值
你需要处理百万行级别的DataFrame,计算两列datetime的日期差值(忽略时间部分),但直接用dt.date的方法速度太慢,这里提供两种高效的替代方案:
方案1:用dt.normalize()矢量化处理
normalize()会将datetime转换为当日的00:00:00时间点,属于pandas的矢量化操作,比dt.date快很多:
df["Date_Difference"] = (df["end_date"].dt.normalize() - df["start_date"].dt.normalize()).dt.days
如果需要结合条件过滤(比如示例中的Condition == "a"),可以配合np.where使用:
df["Date_Difference"] = np.where(df["Condition"] == "a", (df["end_date"].dt.normalize() - df["start_date"].dt.normalize()).dt.days, np.nan)
方案2:直接操作底层整数(性能最优)
pandas的datetime64类型底层以纳秒整数存储,我们可以直接将其转换为以天为单位的整数,再做差值运算,这是性能最好的方法,适合超大数据量:
# 一天的纳秒数:86400秒 × 10^9纳秒/秒 day_ns = 86400 * 10**9 start_days = df["start_date"].view('int64') // day_ns end_days = df["end_date"].view('int64') // day_ns df["Date_Difference"] = end_days - start_days
同样结合条件过滤:
df["Date_Difference"] = np.where(df["Condition"] == "a", end_days - start_days, np.nan)
示例验证
用测试数据验证两种方案的正确性:
import pandas as pd import numpy as np data = {'Condition' :["a", "a", "b"], 'start_date': [pd.Timestamp('2022-01-01 23:00:00.000000'), pd.Timestamp('2022-01-01 23:00:00.000000'), pd.Timestamp('2022-01-01 23:00:00.000000')], 'end_date': [pd.Timestamp('2022-01-02 01:00:00.000000'), pd.Timestamp('2022-02-01 23:00:00.000000'), pd.Timestamp('2022-01-02 01:00:00.000000')]} df = pd.DataFrame(data) # 方案1实现 df["Normalize_Diff"] = np.where(df["Condition"] == "a", (df["end_date"].dt.normalize() - df["start_date"].dt.normalize()).dt.days, np.nan) # 方案2实现 day_ns = 86400 * 10**9 start_days = df["start_date"].view('int64') // day_ns end_days = df["end_date"].view('int64') // day_ns df["View_Diff"] = np.where(df["Condition"] == "a", end_days - start_days, np.nan) # 原正确结果 df["Right_Diff"] = np.where(df["Condition"] == "a", (df["end_date"].dt.date - df["start_date"].dt.date).dt.days, np.nan) # 原错误结果(时间戳直接相减) df["Wrong_Diff"] = np.where(df["Condition"] == "a", (df["end_date"] - df["start_date"]).dt.days, np.nan) print(df)
运行后可见,Normalize_Diff和View_Diff的结果与Right_Diff完全一致,但运算速度远快于原方法。
为什么dt.date速度慢?
df["col"].dt.date会将每个datetime64元素转换为Python标准库的date对象,这是Python级别的逐元素操作,对于百万行数据来说开销极大;而上面两种方案都是基于pandas的矢量化运算或底层数组操作,属于C级别的计算,性能提升非常明显。
内容的提问来源于Stack Exchange,提问作者Jan B.
相关产品推荐
相关产品推荐

