基于唯一ID将2D DataFrame转换为3D NumPy数组的方法
解决方案
步骤1:数据预处理与格式转换
先确保数据按ID和时间排序,再将长格式DataFrame转为宽格式(行对应时间步,列对应ID),最终转换为目标3D NumPy数组:
import pandas as pd import numpy as np # 重命名列以适配后续处理 df = df.rename(columns={'time column': 'time', 'ID column': 'id', 'Value': 'value'}) # 按ID和时间排序,保证每个ID的时间序列连续无乱序 df = df.sort_values(['id', 'time']) # 透视成宽表:行=时间,列=ID,值=Value wide_df = df.pivot(index='time', columns='id', values='value') # 转换为2D NumPy数组,形状为(时间步数, ID数) data_2d = wide_df.values # 扩展维度得到目标3D数组,形状为(时间步数, 1, ID数) data_3d = data_2d[:, np.newaxis, :]
步骤2:构建滞后特征向量
针对大规模数据(500+ID),提供两种实现方式生成滞后特征(比如用前N个时间步的Value作为当前步的特征):
方式1:循环实现(直观易懂)
def create_lag_features(data, window_size): num_samples = data.shape[0] num_features = window_size num_ids = data.shape[2] # 初始化滞后特征数组,形状为(有效时间步数, 窗口大小, ID数) lag_data = np.zeros((num_samples - window_size, num_features, num_ids)) for i in range(num_samples - window_size): # 取当前时间步之前的window_size个时间步的数据 lag_data[i] = data[i:i+window_size, 0, :] return lag_data # 示例:设置滞后窗口为3(用前3个时间步的Value作为特征) window_size = 3 lag_3d_data = create_lag_features(data_3d, window_size)
方式2:向量化实现(高效处理大规模数据)
避免循环,利用NumPy的 stride trick 提升处理效率:
def create_lag_features_vectorized(data, window_size): # 去掉中间的单特征维度,转为(时间步数, ID数)的2D数组 data_2d = data.squeeze(axis=1) # 用滑动窗口生成滞后特征 shape = (data_2d.shape[0] - window_size + 1, window_size, data_2d.shape[1]) strides = (data_2d.strides[0], data_2d.strides[0], data_2d.strides[1]) lag_data = np.lib.stride_tricks.as_strided(data_2d, shape=shape, strides=strides) # 调整形状,丢弃前window_size个无足够滞后数据的样本 return lag_data[:-1] # 生成滞后特征 lag_3d_data = create_lag_features_vectorized(data_3d, window_size=3)
注意事项
- 数据完整性检查:提前用
df.groupby('id').size()确认每个ID的时间样本数一致,否则透视后会出现NaN值,需根据业务需求填充(如wide_df.fillna(0))或删除异常ID。 - 滞后窗口选择:根据时间序列频率(此处为15分钟)和业务场景调整窗口大小,保证特征的有效性。
内容的提问来源于stack exchange,提问作者outeredge1
相关产品推荐
相关产品推荐

