如何基于行列匹配从宽格式DataFrame中提取值并填充新列

3次阅读

如何基于行列匹配从宽格式DataFrame中提取值并填充新列

本文介绍使用pandas将宽格式DataFrame(年份为列名)中的值,根据另一DataFrame中对应的行标签(如NAME)和列名(如YEAR)动态映射到新列的高效方法,避免循环,核心依赖set_index().stack()与merge()组合。

本文介绍使用pandas将宽格式dataframe(年份为列名)中的值,根据另一dataframe中对应的行标签(如name)和列名(如year)动态映射到新列的高效方法,避免循环,核心依赖`set_index().stack()`与`merge()`组合。

在实际数据分析中,常遇到“宽表→长表”匹配场景:一个DataFrame(如df2)以类别(NAME)为行索引、时间维度(如2000, 2001, 2002)为列名存储指标值;另一个DataFrame(如df1)则包含相同类别的多条记录及对应的时间标签(YEAR),需据此查表生成新字段(如SCORE)。直接merge无法解决列名参与匹配的问题,此时应先将宽表重塑为规范的长格式,再执行标准连接。

关键步骤如下:

  1. 将宽表df2转换为长格式:使用set_index(“NAME”).stack()将列名(2000, 2001, 2002)转为行索引的第二级,并展开为一列;再用reset_index()恢复为普通列,并重命名新列;
  2. 与df1按NAME和YEAR合并:确保两表具有完全一致的键字段名(如将叠后的层级列命名为YEAR),即可通过merge完成精准映射。

以下是完整可运行示例代码:

import pandas as pd  # 构造示例数据 df1 = pd.DataFrame({     "NAME": ["Anna", "Mary", "Paul", "Paul", "Mary", "Anna", "Anna", "Mary", "Paul"],     "YEAR": [2002, 2001, 2000, 2001, 2002, 2001, 2000, 2000, 2002] })  df2 = pd.DataFrame({     "NAME": ["Anna", "Mary", "Paul"],     2000: [5, 3, 2],     2001: [4, 2, 3],     2002: [3, 5, 4] })  # 步骤1:重塑df2为长格式 df2_long = (df2.set_index("NAME")               .stack()               .reset_index(name="SCORE")               .rename(columns={"level_1": "YEAR"}))  # 步骤2:与df1合并 result = df1.merge(df2_long, on=["NAME", "YEAR"])  print(result)

输出结果为:

NAME  YEAR  SCORE 0  Anna  2002      3 1  Mary  2001      2 2  Paul  2000      2 3  Paul  2001      3 4  Mary  2002      5 5  Anna  2001      4 6  Anna  2000      5 7  Mary  2000      3 8  Paul  2002      4

注意事项:

  • stack()默认会将所有非索引列压平,若df2含多余列,建议先select_dtypes(include=’number’)过滤或显式指定列;
  • YEAR列在df2_long中默认为str类型(若原始列为整数,stack()后仍保持原类型),但务必确保与df1[“YEAR”]类型一致,否则merge可能静默失败——可统一用astype(int)校验;
  • 替代方案包括melt()(更语义化),但set_index().stack()在处理单指标宽表时更简洁;若需保留多变量,应优先选用melt(id_vars=”NAME”, var_name=”YEAR”, value_name=”SCORE”)。

该方法完全向量化,性能远优于Python循环,是pandas处理“列名即条件”的标准范式。

text=ZqhQzanResources