pandas.DataFrame.T 实现行列结构翻转,需预先设置有意义索引以避免列名丢失;若需按某列值展开为多列,则必须用 pivot() 或 pivot_table(),melt() 与之配合完成宽长表转换。

用 pandas.DataFrame.T 做基础转置,但要注意索引和列名的互换
df.T 是最直接的行转列操作,它会把原 DataFrame 的行索引变成列名,列名变成新行索引。这不是“数据透视”,而是纯结构翻转——适合行列语义对等、不需要聚合的场景。
常见错误是转置后发现列名变成了奇怪的 RangeIndex 或丢失了原始信息。这是因为如果原 df 没有显式设置有意义的索引(比如用 set_index()),T 后的新列名就是默认数字,难以读取。
- 转置前建议先确认:是否希望某列成为新列名?如果是,先用
set_index('col_name') - 转置后若列名是数字且不可读,可用
df.T.rename(columns={0: 'a', 1: 'b'})重命名,或直接赋值df.T.columns = ['a', 'b'] - 注意:含混合数据类型(如 str + int)的列转置后可能触发
object类型广播,数值列变字符串——这不是 bug,是 pandas 类型推断行为
用 pandas.pivot() 实现带逻辑的“行转列”,而非单纯翻转
当你说“行转列”,实际常指把某列的值“摊开”成多个列(比如把 category 列的 'A', 'B', 'C' 变成三列),这时 .T 完全不适用,必须用 pivot()。
关键点在于:你得明确指定 index(新行依据)、columns(要摊开的列)、values(填入单元格的值)。漏掉任一参数都会报 KeyError 或 ValueError: Index contains duplicate entries。
立即学习“Python免费学习笔记(深入)”;
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 如果
index和columns组合不唯一(即同一组 index+columns 对应多行),pivot()直接报错;此时改用pivot_table()并指定aggfunc -
pivot()不接受重复键,但pivot_table(index='x', columns='y', values='z', aggfunc='first')可以兜底 - 转置后新列名默认是
columns列的原始值,若含空格或特殊字符,会被自动转成合法标识符(如'sales Q1'→'sales_Q1'),可通过rename()手动还原
用 pandas.melt() 和 pivot() 配合处理宽表 ↔ 长表转换
真正复杂的“行转列”往往出现在宽表(wide format)和长表(long format)互转中。melt() 是“列转行”的逆操作,而 pivot() 是它的反向搭档——两者配合才能闭环。
例如原始数据是长表:id, variable, value,想按 id 分组、把 variable 的每个唯一值变成列、填入对应 value,就得先 df.pivot(index='id', columns='variable', values='value')。
- 如果
value列有缺失,pivot()默认填NaN;需要填 0 可加.fillna(0),但注意这会改变 dtype(如int64→float64) - 转置结果若列顺序混乱,可用
reindex(columns=['A', 'B', 'C'])强制排序,避免依赖原始数据顺序 - 性能上,
pivot()比循环 +groupby().apply()快一个数量级,但内存占用略高——大数据量时留意MemoryError
为什么 transpose() 方法和 .T 属性效果一样,但别混用链式调用?
df.transpose() 和 df.T 功能完全一致,都是调用底层 NDFrame.transpose()。区别只在可读性和链式写法兼容性。
容易被忽略的是:在方法链中(比如 df.query(...).groupby(...).T),.T 是属性访问,不能传参;而 .transpose() 是方法,支持传 copy=True 或 axes=...。但绝大多数情况无需这些参数。
- 不要写
df.T().reset_index()——.T后面不能加括号,这是语法错误 - 如果需在转置后立即重命名列,用
df.T.rename(columns=str.title)比先赋值再 rename 更紧凑 - 涉及 MultiIndex 时,
.T会交换整个层级结构(level 0 ↔ level 1),不是只翻转最外层;若只想翻转某一层,得用swaplevel()配合sort_index()
df.duplicated(subset=['index_col', 'pivot_col']).any() 和 df['pivot_col'].is_unique,比报错后再调试快得多。

















