You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

代码中的错误分析

  1. 核心错误:列名匹配条件完全错误
    你的判断条件if f's{sample}_' in col:假设列名格式是s{sample}_xxx,但你的实际列名是r1、hg1这种格式,根本不包含s和下划线,所以这个条件永远不会成立,导致df_tmp始终是空的,最终DF自然没有数据。

  2. 逻辑缺陷:无法同时获取radius和Hg_vol
    即使匹配条件正确,你每次循环列时都会重新初始化df_tmp,这会导致radius和Hg_vol的数据被覆盖,无法同时保留在同一个临时DataFrame中。

  3. 方法过时: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:02:27