游乐游手机版
首页/编程语言/文章详情

Python如何提取日期列中的年和月_通过dt访问器获取year与month属性

时间:2026-04-28 13:04
Python如何提取日期列中的年和月?通过dt访问器获取year与month属性 为什么直接用 df[ date ] year 会报 AttributeError? 很多朋友在提取日期信息时,会下意识地直接调用 df[ date ] year,结果迎面就是一个 AttributeError。问题出在

Python如何提取日期列中的年和月?通过dt访问器获取year与month属性

Python如何提取日期列中的年和月_通过dt访问器获取year与month属性

为什么直接用 df['date'].year 会报 AttributeError?

很多朋友在提取日期信息时,会下意识地直接调用 df['date'].year,结果迎面就是一个 AttributeError。问题出在哪?其实,Series 对象本身并没有 year 这个属性。只有那些已经被明确转换为 datetime64 类型的 Series,才能通过专门的 .dt 访问器来获取年、月、日等时间属性。如果你的日期列还是字符串或者 object 类型,直接调用 .dt.year,系统就会抛出那句经典的错误提示:AttributeError: Can only use .dt accessor with datetimelike values

所以,正确的操作顺序应该是:

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

  • 先看类型:用 df['date'].dtype 看一眼,只要不是 datetime64[ns],就别想直接用 .dt
  • 强制转换:老老实实先做转换:df['date'] = pd.to_datetime(df['date'])。默认情况下,pandas 会尽力解析,遇到实在看不懂的值,会设为 NaT(Not a Time)。
  • 处理异常:如果数据里混着像 "2023-13-01" 这种不合法的日期,建议加上参数 errors='coerce',让 pandas 安静地把它们变成 NaT,而不是直接报错中断整个流程。

如何安全提取 year 和 month 并避免 NaN 引发的类型问题?

成功转换后,用 .dt.year.dt.month 提取似乎很简单,但这里有个暗坑:它们返回的是 Int64 类型,这是一种支持 NaN 的整数类型。当你兴冲冲地想把结果拿去拼接字符串或做计算时,NaN 可能会带来意想不到的兼容性问题。尤其要注意,.dt.month 对于正常日期返回 1 到 12,但对于 NaT,它返回的是 NaN,而不是 0。

因此,提取之后不能掉以轻心:

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

  • 检查缺失:先看一眼有多少缺失值:df['date'].dt.year.isna().sum(),做到心中有数。
  • 谨慎填充:如果需要填充,可以用 .fillna(0).astype(int)。但要特别注意业务逻辑——把月份填成 0 通常没有意义。很多时候,保留 NaN 或者直接过滤掉异常行是更稳妥的选择。
  • 拼接字符串的陷阱:如果想生成“年-月”格式的字符串(比如“2023-05”),千万别直接用 df['date'].dt.year.astype(str) + '-' + df['date'].dt.month.astype(str)。因为一旦遇到 NaN,转成字符串就成了 "nan",结果会变成“2023-nan”。有更优雅的方法:df['date'].dt.to_period('M').astype(str)

dt.to_period('M') 比手动拼 year/month 更可靠吗?

答案是肯定的。手动拼接年份和月份,看似直接,实则麻烦不少:你得操心月份是不是单数要补零(避免出现“2023-5”而不是“2023-05”),还得处理 NaT 带来的字符串污染问题。而 .dt.to_period('M') 这个方法,可以说是为生成年月标识量身定做的。它返回一个 PeriodIndex,格式天生就是归一化的、不可变的,并且支持高效的向量化运算。NaT 在这里也会被自动转为 NaT,不会污染你的字符串结果。

具体可以这么用:

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

  • 首选方法:生成年月列,直接用 df['ym'] = df['date'].dt.to_period('M')
  • 转为字符串:需要显示时,调用 .astype(str),结果保证是标准的 "YYYY-MM" 格式。
  • 分组统计:后续如果要按年月分组聚合,df.groupby('ym') 比用两个独立的整数列更简洁,语义也更清晰。
  • 注意限制:当然,Period 类型不能直接进行数学运算。如果你需要计算月份差,得先转回时间戳:(p2.to_timestamp() - p1.to_timestamp()) / np.timedelta64(1, 'M')

从字符串列提取年月时,format 参数能提升性能吗?

不仅能,而且提升非常明显。当你的日期字符串格式统一且已知时(比如全是 "%Y/%m/%d"),在调用 pd.to_datetime() 时传入 format 参数,pandas 就可以跳过耗时的格式自动推断过程。对于百万行级别的数据,这个操作带来的速度提升可能达到 5 到 10 倍。

性能优化的实操建议如下:

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

  • 确认格式:确保格式统一后,使用 pd.to_datetime(df['date'], format='%Y-%m-%d')
  • 错误处理:指定格式后,一旦遇到不匹配的字符串,pandas 会直接报 ValueError。初次尝试时,建议加上 errors='coerce' 来探查数据质量,看看有多少行无法解析。
  • 常见格式符号:记住几个常用的:%Y(四位年份)、%y(两位年份)、%m(01-12月)、%B(英文全称月份)、%b(英文缩写月份)。
  • 格式混杂怎么办:如果数据源格式不纯,比如混着“2023-05-01”和“05/01/2023”,那就别硬套 format 了。老老实实用默认解析,并配合 errors='coerce' 来处理,更为稳妥。

话说回来,实际工作中最容易踩坑的,往往不是这些明面上的规则,而是数据本身埋的“雷”。比如原始列里藏着看不见的空格、特殊字符,或者混合了字符串和浮点数时间戳。这些问题不会立刻导致程序崩溃,但可能会让 .dt.year 默默地返回一整列 NaN,或者产生难以察觉的数据截断。所以,动手处理前,养成好习惯:用 df['date'].head(10).apply(type) 看看类型是否纯粹,再用 df['date'].str.strip().head() 快速检查一下有没有隐藏字符。磨刀不误砍柴工,这一步探查能省去后面大量的调试时间。

来源:https://www.php.cn/faq/2382678.html
上一篇Golang 如何实现对大日志文件的实时监控 下一篇phpEnv怎么开启PHP的gmp扩展 phpEnv大整数运算支持
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
如何在Go中安全地创建和使用time.Ticker最佳实践指南
编程语言 · 2026-07-06

如何在Go中安全地创建和使用time.Ticker最佳实践指南

在Go中,time Ticker的创建位置直接影响并发安全。最佳实践是在goroutine外创建或完全限定在单个goroutine内使用,严禁无保护跨goroutine共享。无论采用哪种方式,都必须在使用完毕后调用Stop()释放底层定时器资源,防止goroutine泄露。停止后的Ticker不应再调用Reset以避免竞态。

Go跨文件cgo结构体类型不兼容的解决方案
编程语言 · 2026-07-06

Go跨文件cgo结构体类型不兼容的解决方案

cgo为每个Go包生成独立的C命名空间,导致跨文件使用同一C结构体时类型不兼容。解决方案是在中心包中定义Go封装类型(如typePointC point_t),并将所有构造、访问和业务逻辑封装其中,其他包仅引用Go类型,避免直接暴露C类型。

Go语言有符号整数二进制补码的正确输出方法
编程语言 · 2026-07-06

Go语言有符号整数二进制补码的正确输出方法

Go语言fmt Printf的%b格式对负数输出带负号的绝对值二进制,而非底层补码位模式。需注意,通过将相同位宽的有符号整数转换为无符号类型(例如将int8转为uint8),可获取真实的二进制补码比特序列,如-5输出11111011,即其补码。

Python列表按出现顺序批量替换重复字符串
编程语言 · 2026-07-06

Python列表按出现顺序批量替换重复字符串

Python列表遍历中,使用计数器对重复字符串(如“latest png”)按出现顺序依次替换为带递增编号的新字符串(如“latest1 png”),保持原列表不变。该方法时间复杂度O(n),无需额外库,严格匹配避免误改,不修改原始列表。

Go语言中如何正确读取io.Reader避免重复与内存污染
编程语言 · 2026-07-06

Go语言中如何正确读取io.Reader避免重复与内存污染

Go开发者使用io Reader Read()手动读取HTTP响应体时,因忽略实际读取字节数n和未正确处理io EOF,导致内容重复、空字节污染等问题。必须使用buf[:n]追加有效数据,将io EOF视为正常终止信号,并检查其他错误,从而避免内存污染与panic风险。