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

如何高效将行式pandas DataFrame重构为采样后的列式结构?

优化方案:高效重构与重采样Pandas DataFrame

你的原始代码通过嵌套循环和逐次合并实现需求,但针对百万级别的数据量,这种方式效率低下。我们可以利用Pandas的向量化操作(如透视表pivot_table和批量重采样)来大幅提升性能,同时让代码更简洁Pythonic。

核心优化思路

  1. 透视表转换:将长格式的DataFrame转为宽格式(每个信号作为一列),避免逐列合并的开销。
  2. 批量重采样:对宽格式DataFrame一次性执行重采样和前向填充,替代循环内的逐列处理。
  3. 唯一列名处理(可选):如果不同CAN ID下存在同名信号,通过组合CAN ID和信号名生成唯一列名,避免数据覆盖。

优化后的代码

def restructure_data(df_phys, res):
    import pandas as pd
    
    if df_phys.empty:
        return pd.DataFrame()
    
    # 确保时间戳索引是有序的(重采样的前提)
    df_phys = df_phys.sort_index()
    
    # 生成唯一列名(若不同CAN ID下有同名信号,避免列名冲突)
    df_phys['Signal_Full'] = df_phys['CAN ID'].astype(str) + '_' + df_phys['Signal']
    
    # 转换为宽格式:时间戳为索引,每个Signal_Full为一列,值为Physical Value
    # aggfunc='last'用于处理同一时间戳下同一信号的多条记录
    df_wide = df_phys.pivot_table(
        index='TimeStamp',
        columns='Signal_Full',
        values='Physical Value',
        aggfunc='last'
    )
    
    # 按指定频率重采样并前向填充缺失值
    df_resampled = df_wide.resample(res).ffill()
    
    # 可选:移除所有列均为NaN的行(与原代码dropna()逻辑一致)
    df_resampled = df_resampled.dropna(how='all')
    
    # 若确认所有信号名在CAN ID间唯一,可跳过Signal_Full步骤,直接用Signal作为列名:
    # df_wide = df_phys.pivot_table(index='TimeStamp', columns='Signal', values='Physical Value', aggfunc='last')
    
    return df_resampled

为什么更快?

  • 向量化操作:pivot_table和resample都是Pandas底层优化的C实现,比Python循环快几个数量级。
  • 避免重复合并:原代码每次循环都执行merge_ordered,会产生大量中间DataFrame,而透视表只需一次转换。
  • 统一处理逻辑:重采样和填充在宽格式上批量完成,无需逐列单独处理。

关键细节说明

  • 排序索引:重采样要求时间戳索引有序,因此先执行sort_index确保正确性。
  • 唯一列名:Signal_Full解决了不同CAN ID下同名信号的冲突问题,若你的数据中信号名全局唯一,可直接用Signal作为列名。
  • aggfunc选择:last表示同一时间戳下同一信号保留最后一条记录,你可根据需求替换为first或mean等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:20:36