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

Pandas:通过转换修复损坏对角矩阵遇瓶颈

修复左侧损坏的对角矩阵实现方案

我正在处理一个左侧存在损坏(NaN值)的对角矩阵(需从右往左读取),需要按照以下规则修复矩阵:

  • 规则1:找到每行损坏前的第一个有效数值,例如dim1=e的行中,损坏前的数值是H1列的6.1
  • 规则2:在无损坏的行(dim1=b、c、d,对应原数据的第0、1、2行)的对应列中,找到与该数值最接近的两个值
  • 规则3:取这两行的H0列平均值作为H0_miss,对应列的平均值作为H_max_miss,将这两个新列添加到原数据中

初始代码

import pandas as pd
import numpy as np

df_flat = pd.DataFrame({
    'dim1': ['b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd', 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g'],
    'dim2': ['H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3'],
    'val': [2, 4, 3, 3.1, 3.2, 3.3, 6, 2.1, 2.2, 4.1, 3.4, 3.5, np.nan, 6.1, 2.3, 1.2, np.nan, np.nan, 2.4, 2.5, np.nan, np.nan, np.nan, 2.5]})

new_df = df_flat.set_index(['dim1', 'dim2']).unstack()
new_df.columns = new_df.columns.droplevel(0)

预期输出

df_flat = pd.DataFrame({
'dim1': ['b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd', 'd', 'd', 'e', 'e', 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'f', 'f','g', 'g', 'g', 'g', 'g', 'g'],
'dim2': ['H0', 'H1', 'H2', 'H3', 'H0_miss', 'H_max_miss', 'H0', 'H1', 'H2', 'H3', 'H0_miss', 'H_max_miss', 'H0', 'H1', 'H2', 'H3', 'H0_miss', 'H_max_miss', 'H0', 'H1', 'H2', 'H3', 'H0_miss', 'H_max_miss', 'H0', 'H1', 'H2', 'H3', 'H0_miss', 'H_max_miss', 'H0', 'H1', 'H2', 'H3', 'H0_miss', 'H_max_miss'],
'val': [2, 4, 3, 3.1, np.nan, np.nan, 3.2, 3.3, 6, 2.1, np.nan, np.nan, 2.2, 4.1, 3.4, 3.5, np.nan, np.nan, np.nan, 6.1, 2.3, 1.2, 4.05, 2.1, np.nan, np.nan, 2.4, 2.5, 3.2, 2.1, np.nan, np.nan, np.nan, 2.5, 2.6, 2.6]})

new_df = df_flat.set_index(['dim1', 'dim2']).unstack()
new_df.columns = new_df.columns.droplevel(0)

当前卡住的代码片段

a = new_df.to_numpy()
m = np.isnan(a)
col = m.argmin(axis=1)

完整解决方案代码

基于已有的代码片段,以下是完成修复的完整实现:

import pandas as pd
import numpy as np

# 初始数据加载
df_flat = pd.DataFrame({
    'dim1': ['b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd', 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g'],
    'dim2': ['H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3', 'H0', 'H1', 'H2', 'H3'],
    'val': [2, 4, 3, 3.1, 3.2, 3.3, 6, 2.1, 2.2, 4.1, 3.4, 3.5, np.nan, 6.1, 2.3, 1.2, np.nan, np.nan, 2.4, 2.5, np.nan, np.nan, np.nan, 2.5]})

new_df = df_flat.set_index(['dim1', 'dim2']).unstack()
new_df.columns = new_df.columns.droplevel(0)

# 1. 获取每行损坏前的列索引(第一个非NaN列的索引)
a = new_df.to_numpy()
m = np.isnan(a)
col_indices = m.argmin(axis=1)

# 2. 提取无损坏行(所有列都没有NaN的行)
good_rows = new_df[~m.any(axis=1)]

# 3. 为每个损坏行计算H0_miss和H_max_miss
h0_miss_vals = []
hmax_miss_vals = []

for idx in range(len(new_df)):
    row = new_df.iloc[idx]
    # 无损坏行直接添加NaN
    if not m[idx].any():
        h0_miss_vals.append(np.nan)
        hmax_miss_vals.append(np.nan)
        continue
    
    # 获取损坏前列的索引和对应值
    target_col_idx = col_indices[idx]
    target_col = new_df.columns[target_col_idx]
    target_val = row[target_col]
    
    # 找到无损坏行中对应列最接近的两个值
    diffs = np.abs(good_rows[target_col] - target_val)
    top2_closest = good_rows.iloc[diffs.nsmallest(2).index]
    
    # 计算平均值
    h0_avg = top2_closest['H0'].mean()
    hmax_avg = top2_closest[target_col].mean()
    
    h0_miss_vals.append(h0_avg)
    hmax_miss_vals.append(hmax_avg)

# 4. 添加新列到宽表
new_df['H0_miss'] = h0_miss_vals
new_df['H_max_miss'] = hmax_miss_vals

# 5. 转换回扁平格式,匹配预期输出
result_df_flat = new_df.stack().reset_index(name='val')

# 查看结果
print(result_df_flat)

代码解释

  • 步骤1:通过np.isnan标记NaN值,argmin(axis=1)定位每行第一个非NaN列的索引,即损坏前的列位置。
  • 步骤2:筛选出所有列无NaN的行,作为修复的参考基准。
  • 步骤3:遍历每行,对损坏行提取目标值,在参考行中找到最接近的两个样本,计算对应列的平均值作为新列值。
  • 步骤4-5:将带新列的宽表转换为扁平格式,与预期输出结构一致。

内容的提问来源于stack exchange,提问作者Lata

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 09:45:30