DataFrame应用函数报错:计算df['start']日期至月末天数遇AttributeError
calendar.monthrange with Pandas Datetime Series/DataFrame 嘿,我帮你拆解这个问题的核心原因——你想用calendar.monthrange计算每个日期到当月月末的天数,但在pandas的Series/DataFrame上操作时触发了AttributeError,本质上是没有正确给calendar.monthrange传递它需要的参数类型,或者误把它当成了Timestamp对象的方法来调用。
为什么会报错?
calendar.monthrange的要求很明确:它需要接收两个整数类型的参数——year和month,返回包含当月第一天星期数和当月总天数的元组。但如果你直接把pandas的Timestamp对象(也就是df['start']里的每个元素)扔给它,或者在apply里写法不对,就会出问题:
举个典型的错误写法例子:
import calendar import pandas as pd df = pd.DataFrame({'start': pd.date_range('2024-01-05', periods=3)}) df['count'] = df['start'].apply(calendar.monthrange) # 错误!
这段代码会直接抛出AttributeError: 'Timestamp' object has no attribute 'monthrange',因为Python会误以为你要调用Timestamp对象的monthrange方法,但这个方法根本不存在——calendar.monthrange是独立函数,不是datetime对象的方法。
正确的实现方式
方式一:在apply里正确提取年、月参数
先写一个辅助函数,从Timestamp里提取年份和月份的整数,再传给calendar.monthrange,最后计算到月末的天数:
import calendar import pandas as pd df = pd.DataFrame({'start': pd.date_range('2024-01-05', periods=3)}) def calculate_days_to_end(date): # 拿到当月总天数 _, total_days = calendar.monthrange(date.year, date.month) # 总天数减去当前日期的日数,就是到月末的天数 return total_days - date.day df['count'] = df['start'].apply(calculate_days_to_end)
方式二:用pandas原生功能更高效(推荐)
如果你的数据量比较大,apply逐行处理的效率会偏低,用pandas的偏移量工具可以实现向量式计算,速度更快:
# 先拿到当月最后一天的日期 df['month_end'] = df['start'] + pd.offsets.MonthEnd(0) # 计算两个日期的差值,再提取天数 df['count'] = (df['month_end'] - df['start']).dt.days
总结一下
这个错误的核心就是对calendar.monthrange的使用方式理解有误:它是一个需要传入整数年、月的独立函数,不能直接把Timestamp对象丢进去,也不能把它当成Timestamp的方法调用。只要正确提取年、月的整数值,或者改用pandas原生的日期偏移功能,就能解决问题啦。
内容的提问来源于stack exchange,提问作者pars_eval

