Pandas DataFrame重塑后仅显示列名的问题排查及数据格式转换实现
问题:重塑DataFrame时无数据显示的错误分析与解决
问题背景
你的原始DataFrame结构如下:
import pandas as pd data = { 'r1': [109.103997, 104.398943, 101.588474, 98.545553, 96.181582], 'hg1': [0.029037, 0.058043, 0.067700, 0.067700, 0.067700], 'r9': [114.866800, 111.862452, 108.366790, 105.601846, 103.472787], 'hg9': [0.000000, 0.000000, 0.000000, 0.009368, 0.009368], 'r21': [93.585901, 90.804183, 88.609266, 87.105383, 85.537507], 'hg21': [0.00000, 0.01389, 0.01389, 0.01389, 0.01389], 'r26': [106.478206, 98.849199, 93.517657, 85.366761, 81.155126], 'hg26': [0.000000, 0.032482, 0.032482, 0.032482, 0.032482], 'r32': [111.376940, 108.826358, 105.428324, 103.639928, 99.231445], 'hg32': [0.000000, 0.040981, 0.053592, 0.053592, 0.066203], 'r37': [81.984848, 80.291790, 78.619017, 77.153464, 75.831122], 'hg37': [0.000000, 0.000000, 0.000000, 0.030494, 0.060886], 'r49': [110.608805, 108.184069, 105.082983, 103.223035, 100.004874], 'hg49': [0.000000, 0.000000, 0.005768, 0.005768, 0.005768], 'r52': [109.289841, 106.213753, 103.472787, 100.396127, 97.201738], 'hg52': [0.060737, 0.167000, 0.235316, 0.242896, 0.242896], 'r105': [106.389980, 103.140119, 101.028560, 98.318994, 93.859710], 'hg105': [0.006827, 0.006827, 0.006827, 0.013678, 0.013678], 'r118': [105.775941, 102.727230, 100.553468, 97.497147, 94.342876], 'hg118': [0.001492, 0.004468, 0.005960, 0.005960, 0.005960] } df = pd.DataFrame(data)
你希望将所有以r开头的列作为radius,以hg开头的列作为Hg_vol,并按sample分组,于是编写了如下代码,但运行后新生成的DF只有列名没有数据:
samples = list(set([col.replace('r', '').replace('hg', '') for col in df.columns])) DF = pd.DataFrame(columns = ['sample', 'radius', 'Hg_vol']) for sample in samples: df_tmp = pd.DataFrame() for col in df.columns: if f's{sample}_' in col: df_tmp['sample'] = len(df[col])*[sample] if col.startswith('r'): df_tmp['radius'] = df[col] else: df_tmp['Hg_vol'] = df[col] DF = DF.append(df_tmp) DF['sample'] = DF['sample'].astype(int) DF = DF.sort_values(by = 'sample', ignore_index = True) DF['sample'] = DF['sample'].astype(str) DF
代码中的错误分析
核心错误:列名匹配条件完全错误
你的判断条件if f's{sample}_' in col:假设列名格式是s{sample}_xxx,但你的实际列名是r1、hg1这种格式,根本不包含s和下划线,所以这个条件永远不会成立,导致df_tmp始终是空的,最终DF自然没有数据。逻辑缺陷:无法同时获取radius和Hg_vol
即使匹配条件正确,你每次循环列时都会重新初始化df_tmp,这会导致radius和Hg_vol的数据被覆盖,无法同时保留在同一个临时DataFrame中。方法过时:append已被弃用
Pandas的append方法已经被官方标记为弃用,推荐使用pd.concat来合并DataFrame,更高效且更稳定。
正确的解决方法
方法一:使用pd.wide_to_long(最简便高效)
Pandas专门提供了wide_to_long函数来处理这种"前缀+编号"的宽格式数据,一行代码就能完成重塑:
# 重塑数据 DF = pd.wide_to_long(df, stubnames=['r', 'hg'], i=df.index, j='sample').reset_index() # 重命名列名 DF = DF.rename(columns={'r': 'radius', 'hg': 'Hg_vol'}) # 调整列顺序并排序 DF = DF[['sample', 'radius', 'Hg_vol']].sort_values('sample').reset_index(drop=True) # 将sample转为字符串类型 DF['sample'] = DF['sample'].astype(str) print(DF.head())
方法二:修复你的循环代码
如果你想保留循环的思路,可以按照以下方式修改:
# 获取所有sample编号并按数字排序 samples = sorted(list(set([col.replace('r', '').replace('hg', '') for col in df.columns])), key=int) # 用列表存储每个sample的临时DataFrame DF_list = [] for sample in samples: # 获取当前sample对应的r和hg列 r_col = f'r{sample}' hg_col = f'hg{sample}' # 创建临时DataFrame df_tmp = pd.DataFrame({ 'sample': [str(sample)] * len(df), 'radius': df[r_col], 'Hg_vol': df[hg_col] }) DF_list.append(df_tmp) # 合并所有临时DataFrame DF = pd.concat(DF_list, ignore_index=True) print(DF.head())
这两种方法都能生成你需要的包含sample、radius、Hg_vol三列的DataFrame,且数据完整。
内容的提问来源于stack exchange,提问作者akshahi17
相关产品推荐
相关产品推荐

