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

Pandas处理DataFrame:赋值后无法移除指定行的技术问题

问题描述

需要对一组包含测量数据的DataFrame执行以下预处理步骤:

  1. 删除不需要的列;
  2. 为每行逐步赋值,遇到值11111111时,切换为samples列表中的下一个值;
  3. 删除NaN列和包含11111111的行。

现有代码中前两步正常执行,但最后无法移除包含11111111的行,最终结果仍保留了这些行。

原实现代码:

frames = [df_JSON, df_CBOR, df_mSEED, df_bSEED]
samples=[250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000]

for df in frames:
    
    df.drop(df.columns[5:], axis=1, inplace=True) # 删除不需要的列
    
    df['samples']='' # 创建新列用于存放赋值结果
    counter=0
    for index, row in df.iterrows():
        if row['tg']!=11111111: # 未遇到11111111时,使用当前sample值
            row['samples']=samples[counter] 
            df.iloc[index]=row
        else: 
            counter+=1 # 遇到11111111时,切换到下一个sample值
    df.dropna(axis=1, inplace=True) # 删除NaN列
    rslt_df=df.loc[df['tg']!=11111111] # 筛选不含11111111的行
    df=rslt_df # 尝试覆盖原DataFrame

补充测试代码:

xls = pd.ExcelFile('testdata.xlsx')
df_JSON = pd.read_excel(xls, 1)
df_CBOR = pd.read_excel(xls, 2)
df_mSEED = pd.read_excel(xls, 3)
df_bSEED = pd.read_excel(xls, 4)

frames = [df_JSON, df_CBOR, df_mSEED, df_bSEED]

samples=[250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000]

for df in frames:
    
    df.drop(df.columns[5:], axis=1, inplace=True) # 删除不需要的列
    
    df['samples']='' # 创建新列用于存放赋值结果
    counter=0
    for index, row in df.iterrows():
        if row['tg']!=11111111: # 未遇到11111111时,使用当前sample值
            row['samples']=samples[counter] 
            df.iloc[index]=row
        else: 
            counter+=1 # 遇到11111111时,切换到下一个sample值
    df.dropna(axis=1, inplace=True) # 删除NaN列
    rslt_df=df.loc[df['tg']!=11111111] # 筛选不含11111111的行
    df=rslt_df # 尝试覆盖原DataFrame

问题原因与解决方案

核心问题

循环中df = rslt_df仅修改了循环变量的临时引用,并未更新frames列表中原有的DataFrame对象。Python列表迭代时,循环变量是原对象的副本,重新赋值不会改变列表内的元素。此外,iterrows()遍历赋值效率较低,适合改用向量化操作优化。

优化后的代码

import pandas as pd

xls = pd.ExcelFile('testdata.xlsx')
df_JSON = pd.read_excel(xls, 1)
df_CBOR = pd.read_excel(xls, 2)
df_mSEED = pd.read_excel(xls, 3)
df_bSEED = pd.read_excel(xls, 4)

frames = [df_JSON, df_CBOR, df_mSEED, df_bSEED]
samples = [250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000]

# 通过索引遍历列表,直接修改原列表中的DataFrame
for i in range(len(frames)):
    df = frames[i]
    
    # 1. 保留前5列,删除其余列
    df = df.iloc[:, :5]
    
    # 2. 生成samples列:遇到11111111切换到下一个sample值
    split_points = df['tg'] == 11111111
    # 计算每个行对应的sample索引(累计分隔点数量)
    sample_indices = split_points.cumsum()
    # 避免索引超出samples列表长度
    sample_indices = sample_indices.clip(upper=len(samples)-1)
    # 为非分隔行赋值对应的sample值
    df['samples'] = sample_indices.map(lambda x: samples[x])
    
    # 3. 删除NaN列和含11111111的行
    df = df.dropna(axis=1)
    df = df[df['tg'] != 11111111]
    
    # 更新frames列表中的原DataFrame对象
    frames[i] = df

# 处理后的DataFrame可从frames列表中取出使用
df_JSON_processed = frames[0]
df_CBOR_processed = frames[1]

关键改动说明

  1. 索引遍历更新列表:通过range(len(frames))遍历,直接修改frames[i],确保原列表中的DataFrame对象被更新。
  2. 向量化替代循环赋值:用cumsum()计算分隔点累计次数,映射到samples列表,比iterrows()效率提升显著。
  3. 简化列操作:用iloc[:, :5]直接选取前5列,逻辑更直观。
  4. 显式更新列表元素:处理完成后将新DataFrame赋值回frames[i],彻底解决引用失效问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:55:21