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

Pandas中如何将DataFrame每行按每3值切分后纵向堆叠为3列

问题描述

我有一个100行、126900列的大型Pandas DataFrame,每行对应一辆车辆的单段道路行程:

  • 列按longitude(经度)、latitude(纬度)、timestamp(时间戳)的固定顺序循环重复排列
  • 每行存储车辆按秒采集的瞬时位置序列
    需求是:针对每一行(单段行程),将重复排列的列按每3个为一组拆分后纵向堆叠,最终转换为仅含3列的DataFrame。目标转换效果参考:
    转换效果参考
    最初我尝试用iterrows()写双重for循环实现,代码框架如下:
for index, row in df.iterrows():
    for i in range(len(df)):

但我不清楚后续逻辑如何编写,同时我了解到对大型DataFrame使用行/列遍历性能通常很差,不符合Pandas开发最佳实践,希望得到可行的解决方案。

解决方案

给你两个无Python层循环的高效实现,处理你这个规模的数据性能比手写循环高数百倍:

方法1:Numpy维度重塑(推荐,性能最高)

核心是直接利用numpy的数组重塑能力,没有额外的索引处理开销,是这类宽表转长表场景下的最优方案:

import pandas as pd
import numpy as np

# 把(100, 126900)的二维数组重塑为(100, 采样点数量, 3)的三维数组
# 126900 / 3 = 42300,也就是单段行程共有42300个秒级采样点
reshaped = df.to_numpy().reshape(len(df), -1, 3)

# 把三维数组展平为(行程数*采样点数, 3)的二维结构
stacked = reshaped.reshape(-1, 3)

# 转为DataFrame并设置列名
result = pd.DataFrame(stacked, columns=['longitude', 'latitude', 'timestamp'])

# 如果需要保留原行对应的行程ID,可以加这一行
result['trip_id'] = np.repeat(df.index, reshaped.shape[1])

注意:这个方案要求你的列严格按照经度、纬度、时间戳的顺序循环排列,无错位,否则会出现字段值匹配错误。

方法2:Pandas原生API实现(可读性更好)

如果你不想直接操作numpy数组,可以用wide_to_long接口实现,逻辑更直观,方便后续调试修改:

import pandas as pd
import numpy as np

# 先给列重命名,给每个采样点加序号,格式为 字段名_采样点序号
sample_count = len(df.columns) // 3
field_names = np.tile(['longitude', 'latitude', 'timestamp'], sample_count)
sample_idx = np.repeat(np.arange(sample_count), 3)
df.columns = [f"{f}_{i}" for f, i in zip(field_names, sample_idx)]

# 调用宽转长接口完成转换
result = pd.wide_to_long(
    df.reset_index().rename(columns={'index': 'trip_id'}),
    stubnames=['longitude', 'latitude', 'timestamp'],
    i='trip_id',
    j='sample_seq',
    sep='_'
).reset_index(drop=True)

性能对比

  • 两种方法的核心运算都在C层实现,处理你当前规模的数据耗时都在1秒以内,其中方法1比方法2快2~3倍
  • 你最初尝试的iterrows()双重循环属于Python层逐元素遍历,处理这个规模的数据可能需要数十分钟,完全不建议使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:51:24