You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中实现与Excel一致的日期月份差计算

用Polars计算日期的月份差值(匹配Excel结果)

需求说明

需要计算两列日期的月份差值,而非天数,但尝试多种方法后未能得到和Excel一致的结果。

测试数据

import polars as pl
from datetime import datetime

test_df = pl.DataFrame(
    {
        "dt_end": [datetime(2022, 1, 1).date(), datetime(2022, 1, 2).date()],
        "dt_start": [datetime(2021, 5, 7).date(), datetime(2020, 7, 8).date()],
    }
)

初始尝试:得到天数差值

直接对日期列相减,得到的是天数差:

test_df.with_columns(
    diff_months = pl.col('dt_end') - pl.col('dt_start')
)

输出:

dt_end      dt_start    diff_months
date        date        duration[ms]
2022-01-01  2021-05-07  239d
2022-01-02  2020-07-08  543d

错误尝试:直接用duration构造月份差

以下代码无法正常运行:

test_df.with_columns(
    diff_months = pl.duration(months = pl.col('dt_end') - pl.col('dt_start'))
)

更新:年月份相减法(与Excel结果不一致)

通过年份和月份的差值计算,但结果和Excel不匹配:

test_df.with_columns(
    diff_months = (pl.col('dt_end').dt.year() - pl.col('dt_start').dt.year()) * 12 +
                    (pl.col('dt_end').dt.month().cast(pl.Int32) - pl.col('dt_start').dt.month().cast(pl.Int32)) 
)

输出:

dt_end      dt_start    diff_months
date        date        i32
2022-01-01  2021-05-07  8
2022-01-02  2020-07-08  18

更新2:按平均天数换算(结果不准确)

尝试用每月平均30.42天换算成月份,结果仍不符合预期:

test_df.with_columns(
    diff_months = pl.col('dt_end') - pl.col('dt_start')
).with_columns(
    diff_months = (pl.col('diff_months').dt.days()/30.42).floor().cast(pl.Int8)
)

输出:

dt_end      dt_start    diff_months
date        date        i8
2022-01-01  2021-05-07  7
2022-01-02  2020-07-08  17

更新3:匹配Excel参考值的对比测试

使用包含Excel参考值的实际数据进行测试:

# 测试数据
snapshot_df = pl.DataFrame(
    {
        "Reporting Month": [datetime(2000, 7, 20).date(), datetime(2000, 8, 20).date(), datetime(2000, 9, 20).date()],
        "Origination date": [datetime(1999, 12, 19).date(), datetime(1999, 12, 19).date(), datetime(1999, 12, 19).date()],
        "Excel_Reference_Age": [7,8,9]
    }
)

对比三种计算方式的结果:

snapshot_df.with_columns(
    diff_months = pl.col('Reporting Month') - pl.col('Origination date')
).with_columns(
    diff_months = (pl.col('diff_months').dt.days()/30.42).floor().cast(pl.Int16),

    diff_months_1 = (pl.col('Reporting Month').dt.year() - pl.col('Origination date').dt.year()) * 12 +
                    (pl.col('Reporting Month').dt.month().cast(pl.Int32) - pl.col('Origination date').dt.month().cast(pl.Int32)) ,

    diff_months_2 = pl.date_range(pl.col("Origination date"), pl.col("Reporting Month"), "1mo").list.lengths()
).select('Excel_Reference_Age','diff_months','diff_months_1','diff_months_2')

输出:

Excel_Reference_Age  diff_months  diff_months_1  diff_months_2
i64                  i16          i32            u32
7                    7            7              8
8                    8            8              9
9                    9            9              10

结论

从对比结果可以看出,diff_months_1(年份差乘12加月份差)的结果和Excel参考值完全一致,说明Excel计算月份差的逻辑是仅计算年份和月份的差值,不考虑具体日期。


内容的提问来源于stack exchange,提问作者ViSa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:35:05