Pandas如何对非字符串列名/索引的DataFrame执行assign赋值
Pandas非字符串列名的无副作用赋值方案
方法特性说明
Pandas DataFrame的assign方法本身是做列赋值的最优选择:它会返回携带新列/更新列的新DataFrame对象,不会就地修改原数据,也就不会意外改动指向同一份数据的浅拷贝、引用对象。
但这个方法的使用存在两个容易踩的限制:
- 直接传入命名参数的写法受Python语法约束,参数名必须是合法标识符,纯数字这类非字符串列名无法直接作为参数名使用
- 用
**解包字典传参的写法受Python函数传参规则约束,解包出的关键字必须是字符串类型,整数、元组等非字符串列名会触发类型错误
比如对于整数列名的示例DataFrame:
import pandas as pd df = pd.DataFrame({ 0: [1, 2, 3], 1: [4, 5, 6] })
两种常见的错误写法都会执行失败:
# 触发SyntaxError: expression cannot contain assignment, perhaps you meant "=="? df.assign(0=df[[0]] + 1) # 触发TypeError: keywords must be strings df.assign(**{0: df[[0]] + 1})
如果退而求其次用直接下标赋值、loc赋值,会就地修改原数据,导致关联的浅拷贝对象被意外改动;如果先做全量copy()再修改,又会复制所有列的数据,大表场景下会产生不必要的内存和性能开销。
正确实现
直接将列名到列值的映射字典作为位置参数传入assign即可,不需要做**解包:
df_new = df.assign({0: df[0] + 1})
这个写法完全满足需求:
- 无语法/传参错误:Pandas内部会直接处理传入的字典映射,不依赖Python的关键字参数解析逻辑,支持任意可哈希对象作为列名(整数、元组、自定义对象都可以)
- 无副作用:和常规
assign调用行为完全一致,返回全新的DataFrame,原对象及其关联的浅拷贝引用都不会被修改 - 无冗余开销:未被修改的列会在新DataFrame中复用原内存块,仅新赋值的列会生成新的数据块,没有全量深拷贝的额外成本
内容的提问来源于stack exchange,提问作者anymous.asker
相关产品推荐
相关产品推荐

