Pandas技术问询:如何以attributes列值为表头扩展多列数据至宽格式
如何用attributes列的值作为表头扩展相关列?
刚好我之前也遇到过类似的需求,咱们一步一步来解决这个问题:
首先先看一下原始的数据结构,先把代码贴出来,方便复现:
import pandas as pd x = pd.DataFrame({ 'id':[11,998,3923], 'count':[7,7,7], 'attributes':['VIS,TEMP,MIN','MIN,VIS,TEMP','MIN,VIS'], 'attribute_values':['0,4,2','2,3,0','0,9'], 'attribute_years':['2000,2001,2002','2001,2002,2003','2008,2009'] })
咱们的需求很明确:不管attributes列里的属性顺序有多乱,甚至有缺失,都要把attribute_values和attribute_years拆成以属性为后缀的新列,比如attribute_values_VIS、attribute_years_MIN,对应的值要准确匹配,缺的属性就用NaN填充。
解决方案代码
直接上可以运行的代码,每一步我都给你解释清楚:
# 定义一个处理单行数据的函数,负责把属性和对应的值转成规范的列名-值对 def expand_single_row(row): # 把逗号分隔的字符串拆成列表 attr_list = row['attributes'].split(',') val_list = row['attribute_values'].split(',') year_list = row['attribute_years'].split(',') # 生成值列和年份列的字典,键就是我们要的新列名 value_dict = {f'attribute_values_{attr}': val for attr, val in zip(attr_list, val_list)} year_dict = {f'attribute_years_{attr}': year for attr, year in zip(attr_list, year_list)} # 合并两个字典,返回成Pandas Series,这样才能和原表合并 return pd.Series({**value_dict, **year_dict}) # 对原表每一行应用函数,得到扩展后的列,然后和原表合并 expanded_result = x.join(x.apply(expand_single_row, axis=1)) # 删掉原来的三个属性相关列,保留我们需要的新列 expanded_result = expanded_result.drop(['attributes', 'attribute_values', 'attribute_years'], axis=1) # 可选:把数值列转成合适的类型,避免是字符串(用Int64支持NaN的整数类型) value_columns = [col for col in expanded_result.columns if 'attribute_values' in col] year_columns = [col for col in expanded_result.columns if 'attribute_years' in col] expanded_result[value_columns] = expanded_result[value_columns].astype('Int64') expanded_result[year_columns] = expanded_result[year_columns].astype('Int64') # 打印结果看看 print(expanded_result)
运行结果
执行完上面的代码,你就能得到想要的格式:
id count attribute_values_VIS attribute_values_TEMP attribute_values_MIN attribute_years_VIS attribute_years_TEMP attribute_years_MIN 0 11 7 0 4 2 2000 2001 2002 1 998 7 3 0 2 2002 2003 2001 2 3923 7 9 <NA> 0 2009 <NA> 2008
代码解释
expand_single_row函数:专门处理每一行,把拆分后的属性和对应的值/年份绑定,生成我们需要的新列名字典,返回Series方便后续合并。x.apply(..., axis=1):按行处理原表,得到所有扩展列的DataFrame,再用join和原表合并。- 类型转换:用
Int64(大写I)是因为它支持空值NaN,普通的int类型会报错。
内容的提问来源于stack exchange,提问作者There
相关产品推荐
相关产品推荐

