如何在Pandas中基于列值与列名创建新列并赋值
问题描述
我有一个包含8列的DataFrame,命名为df:
Duration Location a b c d e f 3M Tuscaloosa 1 2 3 4 5 6 LCM Tuscaloosa 7 8 7 2 3 5 CW Tuscaloosa 9 1 0 0 3 1 PW Tuscaloosa 1 9 9 9 1 0 3M Miami 4 7 0 1 3 8 LCM Miami 8 2 7 8 8 1 CW Miami 1 3 5 7 9 1 PW Miami 8 8 4 4 2 0 3M New York 1 4 6 7 8 8 LCM New York 3 3 4 4 5 5 CW New York 1 1 1 2 2 2 PW New York 9 9 9 9 9 9 3M San Diego 9 3 5 6 7 1 LCM San Diego 1 8 9 0 0 1 CW San Diego 7 8 2 1 1 3 PW San Diego 0 9 4 6 1 4
我希望基于Duration列的值、a至f列的列名与数值创建新列,预期输出如下:
Duration Location a b c d e f 3Ma LCMa CWa PWa 3Mb LCMb CWb PWb 3Mc .... 3M Tuscaloosa 1 2 3 4 5 6 1 null null null 2 null null null 3 LCM Tuscaloosa 7 8 7 2 3 5 null 7 null null null 8 null null null CW Tuscaloosa 9 1 0 0 3 1 null null 9 null null null 1 null null PW Tuscaloosa 1 9 9 9 1 0 null null null 1 null null null 9 null 3M Miami 4 7 0 1 3 8 4 null null null 7 null null null 0 LCM Miami 8 2 7 8 8 1 null 8 null null null 2 null null null CW Miami 1 3 5 7 9 1 null null 1 null null null 3 null null PW Miami 8 8 4 4 2 0 null null null 8 null null null 8 null 3M New York 1 4 6 7 8 8 1 null null null 4 null null null 6 LCM New York 3 3 4 4 5 5 null 3 null null null 3 null null null CW New York 1 1 1 2 2 2 null null 1 null null null 1 null null PW New York 9 9 9 9 9 9 null null null 9 null null null 9 null 3M San Diego 9 3 5 6 7 1 9 null null null 3 null null null 5 LCM San Diego 1 8 9 0 0 1 null 1 null null null 8 null null null CW San Diego 7 8 2 1 1 3 null null 7 null null null 8 null null PW San Diego 0 9 4 6 1 4 null null null 0 null null null 9 null
我尝试过.unstack()方法,但不确定如何适配当前场景,使用normalize方法也未成功,恳请提供帮助。
解决方案
可以通过透视拼接的方式高效实现需求,以下是两种可行方案:
方案1:简洁向量化实现(推荐)
利用Pandas的透视功能直接生成目标列,避免逐行操作,适合大数据量场景:
import pandas as pd # 透视数据,将Duration转为列前缀 pivot_df = df.pivot(index=['Location', 'Duration'], columns='Duration', values=['a', 'b', 'c', 'd', 'e', 'f']) # 合并列层级,生成3Ma、LCMb这类格式的列名 pivot_df.columns = [f"{dur}{col}" for col, dur in pivot_df.columns] # 重置索引恢复原始的Location和Duration列 pivot_df = pivot_df.reset_index() # 和原DataFrame合并,保留所有原始列 result_df = df.merge(pivot_df, on=['Location', 'Duration'], how='left')
方案2:逐列生成(小数据量适用)
如果需要更直观的逻辑,可以遍历列和Duration值生成新列:
import pandas as pd # 获取Duration的所有唯一值 duration_values = df['Duration'].unique() # 存储新列的临时DataFrame new_cols = pd.DataFrame() # 遍历每个目标列(a到f) for col in ['a', 'b', 'c', 'd', 'e', 'f']: # 遍历每个Duration值生成对应新列 for dur in duration_values: new_col_name = f"{dur}{col}" # 仅当当前行Duration匹配时填充值,其余为NaN new_cols[new_col_name] = df.apply(lambda x: x[col] if x['Duration'] == dur else pd.NA, axis=1) # 拼接原df和新列 result_df = pd.concat([df, new_cols], axis=1)
两种方案都能生成符合预期的结果,方案1的向量化操作效率更高,优先推荐。
内容的提问来源于stack exchange,提问作者PureCrust
相关产品推荐
相关产品推荐

