如何处理含NaT的日期数组在Python中计算平均十进制年份的方法?

2026-04-29 08:222阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计771个文字,预计阅读时间需要4分钟。

如何处理含NaT的日期数组在Python中计算平均十进制年份的方法?

要使用pandas对两个datetime数组的元素进行按元素计算,并计算其平均年份,同时自动跳过NaN值,可以按照以下步骤操作:

在时间序列分析或地球科学等场景中,常需将日期转换为“十进制年份”(如 2023.5 表示 2023 年 7 月 2 日左右)以支持线性建模或插值。当处理成对的时间数据(如起始/终止时间、观测/参考时间)时,若存在缺失(NaT),需稳健地计算其平均值:仅当两侧均非 NaT 时取算术平均;仅一侧有效时直接采用该值;两侧均为 NaT 时结果也为 NaT

以下为完整、可复用的解决方案:

import pandas as pd import numpy as np def decimal_year(dates: pd.Series) -> pd.Series: """将 datetime Series 转换为十进制年份(考虑闰年,使用 365.25 天/年)""" # 过滤 NaT 后计算,保留原始索引结构 valid = dates.notna() result = pd.Series(np.nan, index=dates.index, dtype=float) if valid.any(): dt = dates[valid] result.loc[valid] = dt.dt.year + dt.dt.dayofyear / 365.25 return result # 示例数据(实际使用时替换为你的两个 Series) s1 = pd.to_datetime(['2009-07-03', '2009-07-03', '2009-07-03', '2003-02-07', '2004-04-09', 'NaT']) s2 = pd.to_datetime(['NaT', 'NaT', '2015-04-12', '2013-09-17', '2014-02-19', 'NaT']) # 转换为十进制年份 y1 = decimal_year(s1) y2 = decimal_year(s2) # 按行取平均,自动忽略 NaN(即跳过 NaT 对应位置) # 注意:mean(axis=1, skipna=True) 在 Series.concat 后对 DataFrame 操作更清晰 df_y = pd.concat([y1, y2], axis=1) avg_decimal_year = df_y.mean(axis=1, skipna=True) # 将全 NaN 行(即原位置 s1[i] 和 s2[i] 均为 NaT)显式转为 NaT avg_decimal_year = avg_decimal_year.where(df_y.notna().any(axis=1), other=pd.NaT) print("十进制年份数组 1:", y1.tolist()) print("十进制年份数组 2:", y2.tolist()) print("平均十进制年份:", avg_decimal_year.tolist())

关键要点说明:

  • 使用 365.25 而非 365 计算 dayofyear 比例,更合理地近似闰年周期;
  • pd.concat(..., axis=1).mean(axis=1, skipna=True) 是核心——它天然满足“单侧有效即取该值”的逻辑;
  • where(..., other=pd.NaT) 确保双 NaT 位置最终输出 pd.NaT(而非 NaN),保持时间类型一致性;
  • 封装 decimal_year() 函数提升复用性与可读性,避免重复转换逻辑。

⚠️ 注意事项:

立即学习“Python免费学习笔记(深入)”;

  • 若需更高精度(如跨世纪闰年校正),可改用 dateutil.relativedelta 或自定义儒略日转换;
  • dayofyear 基于公历,不适用于历史儒略历日期;
  • 对于超大数组,可考虑向量化 np.where 替代 concat+mean 以节省内存,但可读性略降。

该方法兼顾准确性、健壮性与工程实践性,可直接集成至数据清洗或特征工程 pipeline 中。

标签:Python

本文共计771个文字,预计阅读时间需要4分钟。

如何处理含NaT的日期数组在Python中计算平均十进制年份的方法?

要使用pandas对两个datetime数组的元素进行按元素计算,并计算其平均年份,同时自动跳过NaN值,可以按照以下步骤操作:

在时间序列分析或地球科学等场景中,常需将日期转换为“十进制年份”(如 2023.5 表示 2023 年 7 月 2 日左右)以支持线性建模或插值。当处理成对的时间数据(如起始/终止时间、观测/参考时间)时,若存在缺失(NaT),需稳健地计算其平均值:仅当两侧均非 NaT 时取算术平均;仅一侧有效时直接采用该值;两侧均为 NaT 时结果也为 NaT

以下为完整、可复用的解决方案:

import pandas as pd import numpy as np def decimal_year(dates: pd.Series) -> pd.Series: """将 datetime Series 转换为十进制年份(考虑闰年,使用 365.25 天/年)""" # 过滤 NaT 后计算,保留原始索引结构 valid = dates.notna() result = pd.Series(np.nan, index=dates.index, dtype=float) if valid.any(): dt = dates[valid] result.loc[valid] = dt.dt.year + dt.dt.dayofyear / 365.25 return result # 示例数据(实际使用时替换为你的两个 Series) s1 = pd.to_datetime(['2009-07-03', '2009-07-03', '2009-07-03', '2003-02-07', '2004-04-09', 'NaT']) s2 = pd.to_datetime(['NaT', 'NaT', '2015-04-12', '2013-09-17', '2014-02-19', 'NaT']) # 转换为十进制年份 y1 = decimal_year(s1) y2 = decimal_year(s2) # 按行取平均,自动忽略 NaN(即跳过 NaT 对应位置) # 注意:mean(axis=1, skipna=True) 在 Series.concat 后对 DataFrame 操作更清晰 df_y = pd.concat([y1, y2], axis=1) avg_decimal_year = df_y.mean(axis=1, skipna=True) # 将全 NaN 行(即原位置 s1[i] 和 s2[i] 均为 NaT)显式转为 NaT avg_decimal_year = avg_decimal_year.where(df_y.notna().any(axis=1), other=pd.NaT) print("十进制年份数组 1:", y1.tolist()) print("十进制年份数组 2:", y2.tolist()) print("平均十进制年份:", avg_decimal_year.tolist())

关键要点说明:

  • 使用 365.25 而非 365 计算 dayofyear 比例,更合理地近似闰年周期;
  • pd.concat(..., axis=1).mean(axis=1, skipna=True) 是核心——它天然满足“单侧有效即取该值”的逻辑;
  • where(..., other=pd.NaT) 确保双 NaT 位置最终输出 pd.NaT(而非 NaN),保持时间类型一致性;
  • 封装 decimal_year() 函数提升复用性与可读性,避免重复转换逻辑。

⚠️ 注意事项:

立即学习“Python免费学习笔记(深入)”;

  • 若需更高精度(如跨世纪闰年校正),可改用 dateutil.relativedelta 或自定义儒略日转换;
  • dayofyear 基于公历,不适用于历史儒略历日期;
  • 对于超大数组,可考虑向量化 np.where 替代 concat+mean 以节省内存,但可读性略降。

该方法兼顾准确性、健壮性与工程实践性,可直接集成至数据清洗或特征工程 pipeline 中。

标签:Python