如何更高效地在Python中转换生成目标DataFrame?
宽表转长表的高效Pandas实现方案
需求说明
我有一组需要转换的数据,原始数据结构如下(实际数据集包含更多列,此处简化展示):
原始数据
| lVoterUniqueID | sElectionAbbr1 | sElectionAbbr2 | sElectionAbbr3 | sElectionAbbr4 | sElectionAbbr5 |
|---|---|---|---|---|---|
| 371527 | 2024PR | 2022Gen | 2022PR | 2020GEN | 2020PR |
| 1843949 | 2024PR | null | null | null | null |
| 2813398 | 2024PR | 2022Gen | null | 2020GEN | 2020PR |
需要完成两个核心转换:
- 将
lVoterUniqueID重命名为ID - 将所有
sElectionAbbr[X]列合并为单一的Election_Code列,剔除空值并去重
期望输出示例
| ID | Election_Code |
|---|---|
| 371527 | 2024PR |
| 1843949 | 2024PR |
| 371527 | 2022Gen |
| 371527 | 2022PR |
| 2813398 | 2022Gen |
| ... | ... |
现有实现方式
SQL实现
通过多次UNION拼接结果:
select distinct lVoterUniqueID, sElectionAbbr1 as Election_Code from data_set where sElectionAbbr1 != '' union select distinct lVoterUniqueID, sElectionAbbr2 from data_set where sElectionAbbr2 != '' union ...
现有Python代码
已用Pandas实现,但过程繁琐:
import pandas as pd df = pd.read_csv([path to data file]) # 筛选选举相关列 selected_columns = [column for column in df.columns if column.startswith("sElection")] # 添加选民ID列 selected_columns.insert(0,'lVoterUniqueID') # 创建空的结果DataFrame rcdp_voters_prod = pd.DataFrame(columns=['ID','Election_Code']) def access_elements(list_var, list_index): # 根据索引提取列表元素 result = [list_var[i] for i in list_index] return result # 获取选举列的索引 python_indices = [index for (index, item) in enumerate(selected_columns) if item != "lVoterUniqueID"] union_dict = {} # 构建每个选举列与ID列的组合 for index in python_indices: union_dict.update({index:access_elements(selected_columns,[0,index])}) dataframe_list = [] # 逐个处理列组合,去重、重命名后存入列表 for key in union_dict: loop_df = df.filter(items=union_dict[key]).drop_duplicates() loop_df.rename(columns={'lVoterUniqueID':'ID',union_dict[key][1]:'Election_Code'}, inplace= True) dataframe_list.append(loop_df) # 合并所有DataFrame final_frame_form = pd.concat(dataframe_list) # 剔除选举编码为空的行 final_frame_form=final_frame_form[final_frame_form['Election_Code'].notnull()]
更高效的Python实现方法
利用Pandas内置的melt函数(专门处理宽表转长表的向量化操作),可以大幅简化代码并提升性能:
import pandas as pd df = pd.read_csv([path to data file]) # 核心转换:宽表转长表 result = df.melt( id_vars=['lVoterUniqueID'], # 保留的标识列 value_vars=[col for col in df.columns if col.startswith('sElection')], # 需要转换的选举列 value_name='Election_Code' # 转换后的值列名 ) # 后续处理:重命名、去重、剔除空值 result = result.rename(columns={'lVoterUniqueID': 'ID'}) \ .drop_duplicates() \ .dropna(subset=['Election_Code']) # 若原数据中空值以空字符串形式存在,可添加此过滤 # result = result[result['Election_Code'] != '']
代码说明
melt函数:一步完成原代码中循环列组合、合并DataFrame的工作,是Pandas原生的向量化操作,处理大规模数据时效率远高于手动循环。- 逻辑清晰:后续仅需执行重命名、去重、空值剔除三个步骤,代码可读性大幅提升。
- 兼容性强:自动适配任意数量的
sElectionAbbr[X]列,无需修改代码即可处理扩展后的数据集。
内容的提问来源于stack exchange,提问作者MPJ567
相关产品推荐
相关产品推荐

