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
相关产品推荐
相关产品推荐

