如何通过拆分行创建新的Pandas DataFrame?
Pandas高效转换宽表为长表:拆分个体数据的最佳实践
首先,你的需求非常典型——把宽格式数据(同一行包含多个实体的信息)转换为长格式数据(每行对应一个实体),这种转换在统计分析中非常常见,而且确实应该避免行迭代,用Pandas的向量化操作来实现,效率会高很多。
一、高效实现方法
最直观且高效的方式是分别提取市长和面包师的数据集,重命名列后合并,全程用Pandas的内置操作(都是向量化处理,比循环快几个数量级):
步骤1:准备原始数据(先修正你示例中的小问题,保证各列长度一致)
import pandas as pd data_1 = { "city" : ["Cherbourg", "Calais", "Nevers"], "name_mayor" : ["Robert", "Michel", "Guy"], "age_mayor" : [10,20,30], "name_baker" : ["Jack", "Russel", None], "age_baker" : [40,50, None] } df_1 = pd.DataFrame(data_1) # 目标数据示例(用于对比) data_2 = { 0:["Cherbourg", "Robert", 10], 1:["Calais", "Michel", 20], 2:["Nevers", "Guy", 30], 3:["Cherbourg", "Jack", 40], 4:["Calais", "Russel", 50] } df_2 = pd.DataFrame.from_dict(data_2, orient='index', columns=["city", "name", "age"])
步骤2:拆分并合并数据
# 提取市长数据,并重命名列匹配目标格式 df_mayor = df_1[["city", "name_mayor", "age_mayor"]].rename( columns={"name_mayor": "name", "age_mayor": "age"} ) # 提取面包师数据,重命名后过滤空值(因为部分城市没有面包师) df_baker = df_1[["city", "name_baker", "age_baker"]].rename( columns={"name_baker": "name", "age_baker": "age"} ).dropna(subset=["name", "age"]) # 只删除面包师信息为空的行 # 合并两个数据集,重置索引得到目标结果 df_final = pd.concat([df_mayor, df_baker], ignore_index=True)
运行后df_final就和你想要的df_2完全一致了。
如果你偏好更简洁的写法,也可以用melt函数(适合多组列的批量转换):
# 用melt批量处理,指定id列为city,然后配对名称和年龄列 df_melted = df_1.melt( id_vars="city", value_vars=[("name_mayor", "age_mayor"), ("name_baker", "age_baker")], var_name="role", value_name=["name", "age"] ).dropna(subset=["name", "age"]).drop(columns="role").reset_index(drop=True)
这种方式适合有更多角色(比如医生、教师)的场景,但第一种方法更直观,容易理解和调试。
二、这种处理方式的合理性
非常合理!甚至可以说是统计分析的标准操作:
- 长格式数据更符合Pandas的设计逻辑,后续做统计(比如计算所有个体的平均年龄、按城市分组统计)时,用
df_final.groupby("city")["age"].mean()这类代码就能轻松实现,不需要重复处理多列; - 避免了数据冗余,结构更清晰,每个行只对应一个个体的信息,便于后续的清洗、可视化和建模;
- 处理缺失值更灵活,比如可以直接过滤无面包师的行,或者标记缺失角色,而不会影响市长的数据。
内容的提问来源于stack exchange,提问作者rponthieu dev
相关产品推荐
相关产品推荐

