为何Pandas 2.x更新列时数据类型不改变,而1.x会改变?
Pandas 1.x与2.x列类型更新行为差异的原因分析
在修改DataFrame列的值或数据类型时,Pandas 1.x与2.x存在明显行为差异,以示例中的e列为例:
- Pandas 1.x:使用
pd.to_datetime更新列时,会解析日期并同步更改列的数据类型 - Pandas 2.x:使用
pd.to_datetime更新列时,仅完成日期解析,但不会更改列的数据类型
是什么变更导致了这一差异?
示例代码
import pandas as pd # 创建示例DataFrame df = pd.DataFrame({ 'a': ['1', '2'], 'b': ['1.0', '2.0'], 'c': ['True', 'False'], 'd': ['2024-03-07', '2024-03-06'], 'e': ['07/03/2024', '06/03/2024'], 'f': ['aa', 'bb'], }) # 修改现有列的数据类型 df.loc[:, 'a'] = df.a.astype('int') df.loc[:, 'b'] = df.b.astype('float') df.loc[:, 'c'] = df.c.astype('bool') # 解析日期并修改类型 df.loc[:, 'd'] = pd.to_datetime(df.d) df.loc[:, 'e'] = pd.to_datetime(df.e, format='%d/%m/%Y') # 修改现有列的值 df.loc[:, 'f'] = df.f + 'cc' # 创建新列 df.loc[:, 'g'] = [1, 2]
Pandas 1.5.2执行结果
In [2]: df Out[2]: a b c d e f g 0 1 1.0 True 2024-03-07 2024-03-07 aacc 1 1 2 2.0 True 2024-03-06 2024-03-06 bbcc 2 In [3]: df.dtypes Out[3]: a int64 b float64 c bool d datetime64[ns] e datetime64[ns] f object g int64 dtype: object
Pandas 2.1.4执行结果
In [2]: df Out[2]: a b c d e f g 0 1 1.0 True 2024-03-07 00:00:00 2024-03-07 00:00:00 aacc 1 1 2 2.0 True 2024-03-06 00:00:00 2024-03-06 00:00:00 bbcc 2 In [3]: df.dtypes Out[3]: a object b object c object d object e object f object g int64 dtype: object
差异原因
这个行为变化是Pandas 2.0引入的严格类型赋值规则导致的:
- Pandas 1.x中,使用
df.loc[:, col]赋值时,会自动尝试将右侧数据的类型同步替换为目标列的新类型,或者直接修改列的类型以匹配右侧数据。 - Pandas 2.x之后,为了避免意外的类型转换、保证数据一致性,当右侧数据类型与目标列原有类型不匹配时,默认不会自动修改列类型,而是将数据以兼容原有列类型的形式存储(比如把datetime对象存到object类型列中)。
你的示例里,初始DataFrame的所有列都是object类型。在Pandas 1.x中,df.loc[:, 'a'] = df.a.astype('int')这类操作会直接把列类型改成int64;但在Pandas 2.x中,因为目标列原本是object类型,赋值时不会自动切换列类型,int值、datetime对象都会被存在object列里,所以最终原列类型都保持为object,只有新创建的g列是int64。
如果要恢复Pandas 1.x的行为,可以改用df[col] = ...的赋值方式,或者通过pd.set_option('future.no_silent_downcasting', False)关闭严格类型检查。
内容的提问来源于stack exchange,提问作者bpbutti
相关产品推荐
相关产品推荐

