更新包后np.timedelta64 'M'单位不支持,如何计算日期月差?
计算日期间月份差的替代方案(适配Pandas 2.1.4+、Numpy 1.26.2+)
问题背景
之前通过(df['to_date']-df['from_date'])/np.timedelta64(1, 'M')计算日期月份差的方式,在升级Pandas到2.1.4、Numpy到1.26.2后触发报错:
ValueError: Unit M is not supported. Only unambiguous timedelta values durations are supported. Allowed units are 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns'
这是因为Numpy不再支持模糊时间单位(比如月份,不同月份天数不同)的直接转换。
解决方案
推荐三种可靠的计算方式:
方法1:整数月份差(精确)
通过年份差乘以12加上月份差,得到精确的整数月份数:
import pandas as pd import numpy as np df = pd.DataFrame({'from_date': ['01-10-2003', '15-12-2004', '01-08-2012', '09-07-2001'], 'to_date': ['01-11-2003', '15-12-2006', '01-09-2012', '09-12-2001']}) df['from_date'] = pd.to_datetime(df['from_date'], format='%d-%m-%Y') df['to_date'] = pd.to_datetime(df['to_date'], format='%d-%m-%Y') # 计算整数月份差 df['Months'] = (df['to_date'].dt.year - df['from_date'].dt.year) * 12 + (df['to_date'].dt.month - df['from_date'].dt.month) df
适合需要精确整数月份的场景,比如两个日期同月同日时,结果就是完整的月份数。
方法2:Period对象相减(简洁)
将日期转换为月度周期(Period)后直接相减,得到整数月份差:
import pandas as pd import numpy as np df = pd.DataFrame({'from_date': ['01-10-2003', '15-12-2004', '01-08-2012', '09-07-2001'], 'to_date': ['01-11-2003', '15-12-2006', '01-09-2012', '09-12-2001']}) df['from_date'] = pd.to_datetime(df['from_date'], format='%d-%m-%Y') df['to_date'] = pd.to_datetime(df['to_date'], format='%d-%m-%Y') # 转换为月度Period后计算差值 df['Months'] = df['to_date'].dt.to_period('M') - df['from_date'].dt.to_period('M') # 若需要转为数值类型,添加: # df['Months'] = df['Months'].dt.n df
结果默认是Period对象,添加dt.n可转为整数。
方法3:近似小数月份(兼容旧逻辑)
如果需要类似之前的小数月份结果(考虑当月天数比例),可手动计算:
import pandas as pd import numpy as np df = pd.DataFrame({'from_date': ['01-10-2003', '15-12-2004', '01-08-2012', '09-07-2001'], 'to_date': ['01-11-2003', '15-12-2006', '01-09-2012', '09-12-2001']}) df['from_date'] = pd.to_datetime(df['from_date'], format='%d-%m-%Y') df['to_date'] = pd.to_datetime(df['to_date'], format='%d-%m-%Y') # 总天数除以公历平均月天数(30.4375) df['Months'] = (df['to_date'] - df['from_date']).dt.days / 30.4375 df
这种方式是近似值,适合不需要绝对精确的场景。
内容的提问来源于stack exchange,提问作者gtomer
相关产品推荐
相关产品推荐

