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

Pandas合并多DataFrame时Reindex无效索引错误的解决方法

问题

我尝试合并多个从yfinance获取的DataFrame,但运行代码时出现InvalidIndexError: Reindexing only valid with uniquely valued Index objects错误。我的代码如下:

import yfinance as yf
import pandas as pd
ltick=['SOLB.BR', 'HOLN.SW', 'NOKIA.HE', 'ACA.PA']
end_date=max(df.index.get_level_values(0))
y_l=[]
for tick in sorted(ltick):
    y=yf.Ticker(tick).history(start='2002-04-22', end=end_date)[['Dividends', 'Stock Splits']]
    y['ISIN']=[my_dict2[tick]]*len(y)
    form = [ts.strftime('%Y-%m-%d') for ts in y.index]
    y.index=form
    y.index.names = ['Date']
    y = y.set_index('ISIN', append=True)
    y_l.append(y)
df=yf.Ticker("SPY").history(start='2002-04-22', end=end_date)[['Dividends', 'Stock Splits']]
df = pd.concat([df, pd.concat(y_l)], axis=1)

错误详情:

pd.concat([df, pd.concat(y_l)], axis=1)

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\util\_decorators.py:331, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs)
    325 if len(args) > num_allow_args:
    326     warnings.warn(
    327         msg.format(arguments=_format_argument_list(allow_args)),
    328         FutureWarning,
    329         stacklevel=find_stack_level(),
    330     )
--> 331 return func(*args, **kwargs)

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\core\reshape\concat.py:381, in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
    159 """
    160 Concatenate pandas objects along a particular axis.
    161 
   (...)
    366 1   3   4
    367 """
    368 op = _Concatenator(
    369     objs,
    370     axis=axis,
   (...)
    378     sort=sort,
    379 )
--> 381 return op.get_result()

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\core\reshape\concat.py:612, in _Concatenator.get_result(self)
    610         obj_labels = obj.axes[1 - ax]
    611         if not new_labels.equals(obj_labels):
--> 612             indexers[ax] = obj_labels.get_indexer(new_labels)
    614     mgrs_indexers.append((obj._mgr, indexers))
    616 new_data = concatenate_managers(
    617     mgrs_indexers, self.new_axes, concat_axis=self.bm_axis, copy=self.copy
    618 )

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\core\indexes\base.py:3904, in Index.get_indexer(self, target, method, limit, tolerance)
   3901 self._check_indexing_method(method, limit, tolerance)
   3903 if not self._index_as_unique:
--> 3904     raise InvalidIndexError(self._requires_unique_msg)
   3906 if len(target) == 0:
   3907     return np.array([], dtype=np.intp)

InvalidIndexError: Reindexing only valid with uniquely valued Index objects
解决方法

错误根源

你要合并的两个对象索引结构不匹配:

  • SPY的df是单索引(DatetimeIndex)
  • pd.concat(y_l)是多层索引(Date + ISIN)

按列合并(axis=1)时,pandas无法对齐两种不同结构的索引,触发了索引唯一性检查错误。

方案一:统一索引结构(推荐)

将SPY的df也转换成和其他个股DataFrame一致的多层索引,再合并:

import yfinance as yf
import pandas as pd
ltick=['SOLB.BR', 'HOLN.SW', 'NOKIA.HE', 'ACA.PA']
end_date=max(df.index.get_level_values(0))
y_l=[]
for tick in sorted(ltick):
    y=yf.Ticker(tick).history(start='2002-04-22', end=end_date)[['Dividends', 'Stock Splits']]
    y['ISIN']=[my_dict2[tick]]*len(y)
    # 统一日期索引为字符串格式,避免类型不一致
    y.index = y.index.strftime('%Y-%m-%d')
    y.index.names = ['Date']
    y = y.set_index('ISIN', append=True)
    y_l.append(y)

# 处理SPY数据,添加虚拟ISIN标识,统一为多层索引
df_spy = yf.Ticker("SPY").history(start='2002-04-22', end=end_date)[['Dividends', 'Stock Splits']]
df_spy['ISIN'] = ['SPY'] * len(df_spy)
df_spy.index = df_spy.index.strftime('%Y-%m-%d')
df_spy.index.names = ['Date']
df_spy = df_spy.set_index('ISIN', append=True)

# 所有DataFrame索引结构一致,直接合并
df = pd.concat([df_spy] + y_l)

方案二:转成宽表后合并

如果需要将不同ISIN的分红、拆股数据作为独立列展示,先把个股数据转成宽表,再和SPY数据合并:

import yfinance as yf
import pandas as pd
ltick=['SOLB.BR', 'HOLN.SW', 'NOKIA.HE', 'ACA.PA']
end_date=max(df.index.get_level_values(0))
y_l=[]
for tick in sorted(ltick):
    y=yf.Ticker(tick).history(start='2002-04-22', end=end_date)[['Dividends', 'Stock Splits']]
    isin = my_dict2[tick]
    # 重命名列,添加ISIN标识区分不同个股
    y.columns = [f'{col}_{isin}' for col in y.columns]
    # 统一日期索引格式
    y.index = y.index.strftime('%Y-%m-%d')
    y_l.append(y)

# 合并个股宽表
df_stocks = pd.concat(y_l, axis=1)

# 处理SPY数据,统一索引格式
df_spy = yf.Ticker("SPY").history(start='2002-04-22', end=end_date)[['Dividends', 'Stock Splits']]
df_spy.index = df_spy.index.strftime('%Y-%m-%d')

# 合并SPY和个股数据
df = pd.concat([df_spy, df_stocks], axis=1)

额外注意点

  • 确保所有DataFrame的日期索引格式完全一致(统一为字符串%Y-%m-%d或DatetimeIndex),避免因格式/类型差异导致对齐错误
  • 检查my_dict2中每个tick对应的ISIN是否唯一,防止重复ISIN造成索引重复

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:47:12