Pandas实现单行多列键值对转换为多行(1:n)
解决DataFrame多组键值对转多行的问题
嘿,这个重塑DataFrame的需求太常见了!咱们直接用Pandas的工具来搞定,分两种情况给你演示,不管你有多少前置列、多少组键值对都能hold住。
方法一:用wide_to_long(最适合规律列名)
这个函数专门为这种“前缀+数字”的列名设计,比如你的key1/value1、key2/value2,用它最省心。
先处理你的示例数据
import pandas as pd # 你的原始DataFrame values = [['John', 'somekey1', 'somevalue1', 'somekey2', 'somevalue2']] df = pd.DataFrame(values, columns=['name', 'key1', 'value1', 'key2', 'value2']) # 核心转换代码 df_long = pd.wide_to_long( df, stubnames=['key', 'value'], # 列名的前缀部分 i='name', # 需要保留的前置列(如果有多个就用列表,比如['name', 'age']) j='pair_num', # 生成的用来标记第几组键值对的列名 sep='' # 前缀和数字之间的分隔符,这里没有分隔符所以用空字符串 ).reset_index().dropna(subset=['key', 'value']) # 重置索引,过滤可能的空值 print(df_long)
运行后输出就是你要的多行格式:
name pair_num key value 0 John 1 somekey1 somevalue1 1 John 2 somekey2 somevalue2
扩展到多前置列的情况
如果你的原始数据还有其他前置列(比如age、gender),只需要把所有前置列放到i参数的列表里就行:
# 模拟多前置列的场景 values = [['John', 30, 'Male', 'somekey1', 'somevalue1', 'somekey2', 'somevalue2', 'somekey3', 'somevalue3']] df = pd.DataFrame(values, columns=['name', 'age', 'gender', 'key1', 'value1', 'key2', 'value2', 'key3', 'value3']) # 转换代码 df_long = pd.wide_to_long( df, stubnames=['key', 'value'], i=['name', 'age', 'gender'], # 所有前置列都放这里 j='pair_num', sep='' ).reset_index().dropna(subset=['key', 'value']) print(df_long)
输出会保留所有前置列,同时把每组键值对拆成单独一行:
name age gender pair_num key value 0 John 30 Male 1 somekey1 somevalue1 1 John 30 Male 2 somekey2 somevalue2 2 John 30 Male 3 somekey3 somevalue3
方法二:用melt(更灵活,适合列名不那么规律的情况)
如果你的键值对列名不是严格的keyN/valueN格式,或者需要更灵活的处理,可以用melt来拆分后合并:
# 还是用你的示例DataFrame import pandas as pd values = [['John', 'somekey1', 'somevalue1', 'somekey2', 'somevalue2']] df = pd.DataFrame(values, columns=['name', 'key1', 'value1', 'key2', 'value2']) # 第一步:分离前置列和键值对列 id_vars = [col for col in df.columns if not col.startswith('key') and not col.startswith('value')] key_cols = [col for col in df.columns if col.startswith('key')] value_cols = [col.replace('key', 'value') for col in key_cols] # 第二步:分别拆分key列和value列 df_keys = df.melt(id_vars=id_vars, value_vars=key_cols, var_name='pair_num', value_name='key') df_values = df.melt(id_vars=id_vars, value_vars=value_cols, var_name='pair_num', value_name='value') # 第三步:合并拆分后的结果 df_long = pd.merge(df_keys, df_values, on=id_vars + ['pair_num']) # 可选:清理pair_num列,去掉前缀 df_long['pair_num'] = df_long['pair_num'].str.replace('key', '') print(df_long)
这个方法也能得到和第一种方法一样的结果,适合列名规则不太统一的场景。
内容的提问来源于stack exchange,提问作者Matthias
相关产品推荐
相关产品推荐

