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

pandas报InvalidIndexError:仅唯一值索引可重索引问题排查

Pandas 宽表转换报InvalidIndexError解决方案

报错原因

报错和原始DataFrame列名无关,核心原因是按date分组后,部分日期对应的time列表中存在重复的时间值,手动拼接生成列名时会出现重复的1 {时间} {字段名}格式列名,pandas做concat拼接操作时要求索引、列名必须唯一,因此抛出异常。
同代码在5分钟粒度数据上可正常运行,是因为5分钟间隔的时间序列天然不会在单日出现重复时间点,生成的列名全唯一,不会触发校验。

你可以先运行以下代码定位存在重复时间点的日期,验证问题:

# 校验每个日期下是否存在重复时间
df['time'] = pd.to_datetime(df['time']).dt.time
has_dup_time = df.groupby('date')['time'].apply(lambda x: len(x) != len(set(x)))
print("存在重复时间点的日期:", has_dup_time[has_dup_time].index.tolist())

解决方法

方法1:去重后保留原有逻辑

如果重复时间点属于脏数据,先按date+time维度去重再执行原有转换逻辑即可:

df['time'] = pd.to_datetime(df['time']).dt.time
# 同日期同时间点仅保留第一条记录
df = df.drop_duplicates(subset=['date', 'time'], keep='first')
df = df.groupby('date').agg(list)

one_min_df = pd.concat([
    pd.concat([pd.DataFrame([row[col]], index=[index],
                columns=[f'1 {h} {col}' for h in row['time']])
    for col in row.index[1:]], axis=1) 
    for index, row in df.iterrows()
    ])

方法2:用pandas原生透视表实现(更推荐)

逐行遍历的写法性能差、容易出边界问题,直接用pivot_table实现长宽表转换更稳定,性能也更高,不需要手动拼接列名:

df['time'] = pd.to_datetime(df['time']).dt.time
# 构造列名前缀
df['time_label'] = '1 ' + df['time'].astype(str)
# 透视生成宽表,重复时间点自动取第一条记录
one_min_df = df.pivot_table(
    index='date',
    columns='time_label',
    values=['open', 'high', 'low', 'close'],
    aggfunc='first'
)
# 调整列名格式为目标结构
one_min_df.columns = [f'{time_col} {val_col}' for val_col, time_col in one_min_df.columns]
one_min_df = one_min_df.reset_index()

如果需要列按时间点顺序排列(即同一时间点的open/high/low/close排在一起),可以在生成列后对列名做自定义排序即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:57:18