ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Pandas 表格布局重塑实战:从排序到 pivot / pivot_table / melt 的长宽格式转换

Pandas 表格布局重塑实战:从排序到 pivot / pivot_table / melt 的长宽格式转换 Pandas 表格布局重塑实战从排序到 pivot / pivot_table / melt 的长宽格式转换【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas本教程源自 pandas 官方入门系列《10 minutes to pandas》中的「How to reshape the layout of tables」以 titanic.csv 与 air_quality_long.csv 两份真实数据集为线索系统讲解表格行排序、长表转宽表pivot、带聚合的透视表pivot_table以及宽表转长表melt四类最常用的表格布局重塑操作。读完本文你将能够熟练地在长格式long/tidy format与宽格式wide format之间自由切换数据表布局并理解其底层源码实现逻辑。本文所有示例代码均可在 pandas 源码仓库的 pandas/core/frame.py、pandas/core/reshape/pivot.py 与 pandas/core/reshape/melt.py 中找到对应的实现依据。教程数据集准备本教程使用两个数据集均位于仓库的doc/data/目录下。泰坦尼克号乘客数据titanic.csvimport pandas as pd titanic pd.read_csv(doc/data/titanic.csv) titanic.head()这份数据包含每位乘客的船舱等级Pclass、姓名、性别、年龄Age、票价Fare、是否幸存等字段用于演示表格行排序。空气质量长表数据air_quality_long.csv空气质量数据来自 OpenAQ 项目记录了巴黎FR04014、安特卫普BETR801与伦敦London Westminster三个测量站点的NO₂与PM2.5浓度值用于演示长表与宽表之间的相互转换。air_quality pd.read_csv( doc/data/air_quality_long.csv, index_coldate.utc, parse_datesTrue ) air_quality.head()该数据集的列结构如下city传感器所在城市Paris / Antwerp / Londoncountry传感器所在国家FR / BE / GBlocation传感器 IDFR04014 / BETR801 / London Westminsterparameter被测参数no2或 Particulate mattervalue测量值unit测量单位µg/m³DataFrame 的索引为datetime即测量时刻。说明该空气质量数据以长格式long format存储——每个观测值占据独立的一行每个变量占据独立的一列。长格式也被称为 tidy data format是数据科学中最推荐的存储形态之一。排序表格行sort_values按单个列排序需求按乘客年龄排序泰坦尼克数据。titanic.sort_values(byAge).head()执行后表格行会按照Age列从低到高重新排列输出结果将年龄最小的乘客排在最前面。按多个列排序含降序需求按船舱等级与年龄排序且均为降序。titanic.sort_values(by[Pclass, Age], ascendingFalse).head()通过DataFrame.sort_values表格行会按照定义的列可为一个或多个进行排序且索引会跟随行序一起移动。ascending参数既可以传单个布尔值也可以传与by等长的布尔列表实现部分列升序、部分列降序的混合排序。源码视角sort_values 的参数细节从 pandas/core/frame.py#L9195-L9206 的签名可以看到DataFrame.sort_values支持以下关键参数参数默认值作用by必填排序依据的列名或列名列表axis0index沿行方向还是沿列方向排序ascendingTrue是否升序传列表可为每列单独指定kindquicksort排序算法quicksort / mergesort / heapsort / stablena_positionlast缺失值排在末尾first则排在最前ignore_indexFalse为True时重排索引为 0..n-1keyNone排序前对值应用的向量化 key 函数类似内置sorted的 key但要求接收并返回 Series其中mergesort与stable是仅有的稳定排序算法能保持相等键的原始相对顺序key参数则允许你自定义排序规则例如忽略大小写、按绝对值排序等。更详细的排序讲解可参见 用户指南 sorting 章节 中关于排序的说明。长表转宽表pivot我们先用空气质量数据构造一个小规模的演示子集只保留no2数据且每个站点location只取前两条测量记录。# 只保留 no2 数据 no2 air_quality[air_quality[parameter] no2] # 按时间排序后对每个站点用 head(2) 取前两条记录 no2_subset no2.sort_index().groupby([location]).head(2) no2_subset此时no2_subset仍然是一个长表同一站点、不同时刻的测量值分布在多行中。需求将三个站点的数值并排展示为独立列no2_subset.pivot(columnslocation, valuesvalue)DataFrame.pivot是纯数据重排操作它要求每个 index/column 组合只对应一个唯一的值不做任何聚合。转换后location的每个取值BETR801、FR04014、London Westminster成为新 DataFrame 的列原有的 datetime 索引保持不变。注意当pivot不显式指定index参数时会沿用现有的索引行标签。长转宽的实际价值多序列同时绘图由于 pandas 天然支持对多列数据直接绘图参见 绘图教程长表转宽表后即可在同一个坐标系中绘制三个站点的 NO₂ 时间序列曲线no2.head() no2.pivot(columnslocation, valuesvalue).plot()这一用法正是长转宽最典型的实战场景——把时间序列从堆叠的长表变成并列的宽表以便对比可视化。源码视角pivot 的纯重排语义从 pandas/core/frame.py#L13926-L14075 的实现看DataFrame.pivot的完整签名是pivot(*, columns, indexno_default, valuesno_default)columns必填用于构成新 DataFrame 的列index可选用于构成新 DataFrame 的索引不传则使用现有索引values可选用于填充新 DataFrame 的数值列不指定则使用其余所有列并生成层级化MultiIndex列。该方法内部委托给 pandas/core/reshape/pivot.py 中的模块级pivot函数执行。当某个index/columns组合存在多个值时会抛出ValueError: Index contains duplicate entries, cannot reshape——此时就需要改用支持聚合的pivot_table。源码 docstring 中给出了多列、多索引组合 pivot 的完整示例例如df.pivot(indexfoo, columns[lev2, lev3], valuesvalues)会生成两级层级列。透视表pivot_table带聚合需求汇总各站点 NO₂ 与 PM2.5 的平均浓度当同一个 index/column 组合对应多个取值本例中同一站点、同一参数有多个时刻的测量值时pivot无法处理必须使用pivot_table并通过聚合函数合并这些值air_quality.pivot_table( valuesvalue, indexlocation, columnsparameter, aggfuncmean )输出结果中行索引为三个站点列parameter分为no2与 Particulate matter单元格为各自浓度的均值。aggfuncmean表示对同一location, parameter组合下的多个测量值取平均。添加行列小计marginspivot_table 是电子表格软件中非常经典的概念。若需要同时输出行/列维度的小计subtotals将margins参数设为Trueair_quality.pivot_table( valuesvalue, indexlocation, columnsparameter, aggfuncmean, marginsTrue, )结果会在末尾追加一行和一列All分别给出按列、按行聚合的均值。源码视角pivot_table 与 groupby 的等价关系pivot_table与DataFrame.groupby存在直接的内在联系——同一结果完全可以通过按parameter与location分组推导出来air_quality.groupby([parameter, location])[[value]].mean()从 pandas/core/frame.py#L14077-L14090 的签名可见DataFrame.pivot_table支持远比教程示例更丰富的参数参数默认值作用valuesNone要聚合的列可多个index/columnsNone分组键可传列名、Grouper、数组或它们的序列aggfuncmean聚合函数可传函数、函数列表或 dictdict 时 key 为列名fill_valueNone聚合后用于替换缺失值的标量marginsFalse是否添加All行列小计margins_nameAll小计行列的名称dropnaTrue是否排除全为 NaN 的列同时影响 margins 的计算observedTrue当分组键为 Categorical 时是否只显示实际出现的类别sortTrue结果是否排序当aggfunc传入函数列表时结果列会形成以函数名如mean、sum为顶层、原列名为次层的层级列结构当传入 dict 时可以为不同列指定不同聚合函数。fill_value则是在聚合完成后统一回填缺失值如 0。更完整的说明见 用户指南 pivot tables 章节。宽表转长表melt从上一节生成的宽表出发先用reset_index为 DataFrame 添加一个新索引no2_pivoted no2.pivot(columnslocation, valuesvalue).reset_index() no2_pivoted.head()此时三个站点的测量值分布在三列BETR801、FR04014、London Westminster中date.utc作为普通列保留这是一个典型的宽表。需求将所有 NO₂ 测量值收集到单列长格式no_2 no2_pivoted.melt(id_varsdate.utc) no_2.head()DataFrame.melt将宽表转换为长表所有未在id_vars中列出的列会被融化合并到两列中——一列存放原列头名称默认名为variable一列存放对应的数值默认名为value。更精细地控制 melt 的参数melt的参数可以显式定义以获得更可读的输出no_2 no2_pivoted.melt( id_varsdate.utc, value_vars[BETR801, FR04014, London Westminster], value_nameNO_2, var_nameid_location, ) no_2.head()各参数的作用如下value_vars指定要融化合并的列不指定则默认融化除id_vars外的所有列value_name自定义数值列的列名替代默认的valuevar_name自定义存放原列头名称的列名缺省时取索引名或默认的variable。简言之value_name与var_name只是两个生成列的命名参数真正决定融化哪些列的是id_vars与value_vars。源码视角melt 的完整参数与实现从 pandas/core/frame.py#L14729-L14867 与 pandas/core/reshape/melt.py#L44-L53 可以看到melt还额外支持两个参数col_level当列是 MultiIndex 时指定熔化的层级ignore_index默认True为False时保留原始索引索引标签会按需重复。此外melt对应的模块级函数pd.melt(frame, ...)与DataFrame.melt行为完全一致。melt 的实现会先通过ensure_list_vars将id_vars/value_vars规范化为列表再将各列数据对齐堆叠。当列是 MultiIndex 且参数未以元组列表形式给出时会抛出ValueError。melt 在实战中的典型应用包括宽表数据入库前转换为长表、多个测量列合并为指标 数值两列、以及为绘图库如 seaborn准备tidy输入。宽转长的更多细节见 用户指南 melt 章节。速记要点按一列或多列排序使用sort_valuespivot只是数据的纯重排long → widepivot_table额外支持聚合pivot的逆操作是meltwide → long二者互为反向遇到同一 index/column 组合有多个值时pivot会抛ValueError应改用pivot_tablepivot_table与groupby等价air_quality.groupby([parameter, location])[[value]].mean()可复现同一结果。完整的表格重塑与透视操作总览参见 用户指南 reshaping and pivoting 章节以及本教程所在系列 入门教程索引。【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进