Pandas合并(Concat/Merge/Join)不同结构DataFrame:表头转行并设为索引
嘿,我来帮你搞定这个Pandas数据合并的需求!结合你描述的“合并不同结构的DataFrame、将原表头转为新行、把初始列标题转成索引”这几个核心点,我给你分两种场景实现,你可以根据实际需求选择:
场景1:将原表头作为分组标识行,保留宽表结构合并
这种方式会把每个DataFrame的列名作为单独的一行插入到数据上方,然后把两个df按行合并(列数不同的位置自动补NaN),最后可以将原列标题相关的信息设置为索引。
步骤1:创建示例DataFrame
首先修正你的代码——pd.DataFrame.from_items已经被弃用了,我们用from_dict来创建更稳妥:
import pandas as pd # 创建df1(3列3行) list1 = [('A', ['1','2', '3']), ('B', ['4', '5','6']), ('C', ['7','8','9'])] df1 = pd.DataFrame.from_dict(dict(list1)) # 创建df2(4列2行,和df1规模不同) list2 = [('X', ['10','11']), ('Y', ['12', '13']), ('Z', ['14','15']), ('W', ['16','17'])] df2 = pd.DataFrame.from_dict(dict(list2))
步骤2:给每个DataFrame添加表头行
我们可以创建一个只包含列名的临时行,然后用pd.concat把它和原DataFrame合并:
# 处理df1:添加表头行 df1_with_header = pd.concat([pd.DataFrame([df1.columns.tolist()], columns=df1.columns), df1], ignore_index=True) # 处理df2:添加表头行 df2_with_header = pd.concat([pd.DataFrame([df2.columns.tolist()], columns=df2.columns), df2], ignore_index=True)
步骤3:合并两个处理后的DataFrame
因为两个df列数不同,用pd.concat按行合并即可,缺失的位置会自动填充NaN:
merged_df = pd.concat([df1_with_header, df2_with_header], ignore_index=True)
步骤4:将初始列标题转换为索引(可选)
如果你想把原DataFrame的标识(比如“df1表头”“df1数据”“df2表头”“df2数据”)作为索引,可以手动设置:
# 手动创建索引标签 index_labels = ['df1表头', 'df1数据1', 'df1数据2', 'df1数据3', 'df2表头', 'df2数据1', 'df2数据2'] merged_df.index = index_labels
最终的merged_df结构大概是这样:
| A | B | C | X | Y | Z | W | |
|---|---|---|---|---|---|---|---|
| df1表头 | A | B | C | NaN | NaN | NaN | NaN |
| df1数据1 | 1 | 4 | 7 | NaN | NaN | NaN | NaN |
| df1数据2 | 2 | 5 | 8 | NaN | NaN | NaN | NaN |
| df1数据3 | 3 | 6 | 9 | NaN | NaN | NaN | NaN |
| df2表头 | NaN | NaN | NaN | X | Y | Z | W |
| df2数据1 | NaN | NaN | NaN | 10 | 12 | 14 | 16 |
| df2数据2 | NaN | NaN | NaN | 11 | 13 | 15 | 17 |
场景2:转成长表,将原列标题设为索引
这种方式更适合后续的数据分析,把宽表转成“列名-值”的长表结构,同时保留原DataFrame的标识,最后把原列标题设为索引。
步骤1:同样先创建示例DataFrame(和场景1一致)
import pandas as pd list1 = [('A', ['1','2', '3']), ('B', ['4', '5','6']), ('C', ['7','8','9'])] df1 = pd.DataFrame.from_dict(dict(list1)) list2 = [('X', ['10','11']), ('Y', ['12', '13']), ('Z', ['14','15']), ('W', ['16','17'])] df2 = pd.DataFrame.from_dict(dict(list2))
步骤2:将每个df转成长表,添加来源标识
用melt方法把宽表转成长表,同时添加一列标记数据来自哪个df:
# 处理df1:转成长表,添加来源列 df1_long = df1.melt(var_name='原列标题', value_name='值').assign(来源='df1') # 处理df2:转成长表,添加来源列 df2_long = df2.melt(var_name='原列标题', value_name='值').assign(来源='df2')
步骤3:合并两个长表
直接用pd.concat按行合并即可:
merged_long_df = pd.concat([df1_long, df2_long], ignore_index=True)
步骤4:将初始列标题设为索引
把原列标题列设置为索引:
merged_long_df.set_index('原列标题', inplace=True)
最终的merged_long_df结构大概是这样:
| 值 | 来源 | |
|---|---|---|
| 原列标题 | ||
| A | 1 | df1 |
| A | 2 | df1 |
| A | 3 | df1 |
| B | 4 | df1 |
| B | 5 | df1 |
| B | 6 | df1 |
| C | 7 | df1 |
| C | 8 | df1 |
| C | 9 | df1 |
| X | 10 | df2 |
| X | 11 | df2 |
| Y | 12 | df2 |
| Y | 13 | df2 |
| Z | 14 | df2 |
| Z | 15 | df2 |
| W | 16 | df2 |
| W | 17 | df2 |
补充说明
- 如果你的两个DataFrame有可以关联的键,也可以用
merge或join来合并,但因为你提到列名不同、规模不同,concat是更通用的选择。 from_items在Pandas 0.23之后就被移除了,所以建议用from_dict或者直接传入字典创建DataFrame。
内容的提问来源于stack exchange,提问作者SmokingGun
相关产品推荐
相关产品推荐

