DataFrame的串联和重新索引仅适用于唯一值索引对象。

103
我正在尝试连接以下数据框:df1。
                                price   side timestamp
timestamp           
2016-01-04 00:01:15.631331072   0.7286  2   1451865675631331
2016-01-04 00:01:15.631399936   0.7286  2   1451865675631400
2016-01-04 00:01:15.631860992   0.7286  2   1451865675631861
2016-01-04 00:01:15.631866112   0.7286  2   1451865675631866

和:

df2

                                bid     bid_size offer  offer_size
timestamp               
2016-01-04 00:00:31.331441920   0.7284  4000000 0.7285  1000000
2016-01-04 00:00:53.631324928   0.7284  4000000 0.7290  4000000
2016-01-04 00:01:03.131234048   0.7284  5000000 0.7286  4000000
2016-01-04 00:01:12.131444992   0.7285  1000000 0.7286  4000000
2016-01-04 00:01:15.631364096   0.7285  4000000 0.7290  4000000

随着

 data = pd.concat([df1,df2], axis=1)  

但我得到了以下输出:

InvalidIndexError                         Traceback (most recent call last)
<ipython-input-38-2e88458f01d7> in <module>()
----> 1 data = pd.concat([df1,df2], axis=1)
      2 data = data.fillna(method='pad')
      3 data = data.fillna(method='bfill')
      4 data['timestamp'] =  data.index.values#converting to datetime
      5 data['timestamp'] = pd.to_datetime(data['timestamp'])#converting to datetime

/usr/local/lib/python2.7/site-packages/pandas/tools/merge.pyc in concat(objs, axis, join, join_axes, ignore_index, keys, levels, names, verify_integrity, copy)
    810                        keys=keys, levels=levels, names=names,
    811                        verify_integrity=verify_integrity,
--> 812                        copy=copy)
    813     return op.get_result()
    814 

/usr/local/lib/python2.7/site-packages/pandas/tools/merge.pyc in __init__(self, objs, axis, join, join_axes, keys, levels, names, ignore_index, verify_integrity, copy)
    947         self.copy = copy
    948 
--> 949         self.new_axes = self._get_new_axes()
    950 
    951     def get_result(self):

/usr/local/lib/python2.7/site-packages/pandas/tools/merge.pyc in _get_new_axes(self)
   1013                 if i == self.axis:
   1014                     continue
-> 1015                 new_axes[i] = self._get_comb_axis(i)
   1016         else:
   1017             if len(self.join_axes) != ndim - 1:

/usr/local/lib/python2.7/site-packages/pandas/tools/merge.pyc in _get_comb_axis(self, i)
   1039                 raise TypeError("Cannot concatenate list of %s" % types)
   1040 
-> 1041         return _get_combined_index(all_indexes, intersect=self.intersect)
   1042 
   1043     def _get_concat_axis(self):

/usr/local/lib/python2.7/site-packages/pandas/core/index.pyc in _get_combined_index(indexes, intersect)
   6120             index = index.intersection(other)
   6121         return index
-> 6122     union = _union_indexes(indexes)
   6123     return _ensure_index(union)
   6124 

/usr/local/lib/python2.7/site-packages/pandas/core/index.pyc in _union_indexes(indexes)
   6149 
   6150         if hasattr(result, 'union_many'):
-> 6151             return result.union_many(indexes[1:])
   6152         else:
   6153             for other in indexes[1:]:

/usr/local/lib/python2.7/site-packages/pandas/tseries/index.pyc in union_many(self, others)
    959             else:
    960                 tz = this.tz
--> 961                 this = Index.union(this, other)
    962                 if isinstance(this, DatetimeIndex):
    963                     this.tz = tz

/usr/local/lib/python2.7/site-packages/pandas/core/index.pyc in union(self, other)
   1553                 result.extend([x for x in other._values if x not in value_set])
   1554         else:
-> 1555             indexer = self.get_indexer(other)
   1556             indexer, = (indexer == -1).nonzero()
   1557 

/usr/local/lib/python2.7/site-packages/pandas/core/index.pyc in get_indexer(self, target, method, limit, tolerance)
   1890 
   1891         if not self.is_unique:
-> 1892             raise InvalidIndexError('Reindexing only valid with uniquely'
   1893                                     ' valued Index objects')
   1894 

InvalidIndexError: Reindexing only valid with uniquely valued Index objects  

我已经删除了额外的列,并在可能存在冲突的地方删除了重复项和NA值,但我不知道问题出在哪里。


我已经从df1和df2中删除了时间戳列,并尝试使用df1.dropna()和df2.dropna()来删除NA值;但问题仍然存在... - noidea
1
@gmoshkin,我假设pd是pandas的别名:import pandas as pd,并且df1和df2是pandas DataFrame对象。 - jugovich
6
尝试在pd.concat中传递ignore_index=True参数。 - lunguini
10
另外需要注意的是,我曾因数据框中有重复列而遇到类似的错误。 - Tom G.
7
注意,如果其中一个数据框中存在重复的列,也可能导致此错误(https://github.com/pandas-dev/pandas/pull/38654)。 - Angel
显示剩余3条评论
14个回答

105

您可以在不更改数据或删除重复项的情况下缓解此错误。只需使用DataFrame.reset_index创建一个新索引即可:

df = df.reset_index()

旧索引作为数据帧中的一列被保留,但如果您不需要它,可以执行以下操作:

但如果你不需要它,你可以这样做:

df = df.reset_index(drop=True)

有些人喜欢:

df.reset_index(inplace=True, drop=True)

22
应该将这标记为正确答案,因为它解决了问题而不会丢失信息。并非在数据集中始终都是重复记录出现了问题。 - Juanu
19
即使我对数据集进行了这个转换,我仍然收到错误信息。 - BHouwens
2
如果这个方法不起作用怎么办? pd.concat([df_1a.reset_index()[common_features], df_1b.reset_index()[common_features]])
InvalidIndexError: 重新索引只适用于具有唯一值的索引对象
- Soren
14
我的情况是,我有一列重复的数据(希望能帮到其他人!)。 - João
2
对我来说,我需要将一个对象系列更改为日期时间。在一个系列上它可以正常工作,但在另外三个系列上我会得到以上错误。所以我的问题是,为什么我的数据框允许我对一个系列进行操作,而对另一个系列却不行? - JQTs
显示剩余3条评论

97

重复的列名!

在我的情况下,问题是由于我有重复的列名造成的。


1
请参考以下代码,以删除重复的列名:https://dev59.com/a2Up5IYBdhLWcg3w3ad1#40435354 - jsta
1
这是一个不错的提示!在我的情况下,我使用 df1 = df1.append(df2) 进行连接。然而,16列中有2列是不同的,导致了问题。 - LanternD
1
我认为错误通常发生在列名上,因为大多数人会沿行轴拼接(即 axis=0 或未指定)。 在这种情况下,索引必须是唯一的 axis=1。 使用 axis=0 时,索引不需要唯一,但列必须唯一。这是因为否则就不清楚如何将不同数据帧中的重复列对齐。 在 axis=1 的情况下,列可以有重复项,但索引必须唯一,原因相同,例如应该在不同数据帧之间对齐哪些行。 - Herbert
这在我的情况下发生是因为我将所有列名转换为大写,使其中两个相同。 - Kaizzen
重复的列名 + 尝试合并具有不同列长度的数据框示例:df1:列-> ["A","B"] df2:列->["A","A","B",C]pd.concat([df1,df2])将显示此错误。为解决此问题,请重命名重复的列名。 - david.t_92
错误 InvalidIndexError 应该更改为更具说明性的内容。 - ChaimG

60

pd.concat要求索引唯一。如需删除具有重复索引的行,请使用

df = df.loc[~df.index.duplicated(keep='first')]

import pandas as pd
from pandas import Timestamp

df1 = pd.DataFrame(
    {'price': [0.7286, 0.7286, 0.7286, 0.7286],
     'side': [2, 2, 2, 2],
     'timestamp': [1451865675631331, 1451865675631400,
                  1451865675631861, 1451865675631866]},
    index=pd.DatetimeIndex(['2000-1-1', '2000-1-1', '2001-1-1', '2002-1-1']))


df2 = pd.DataFrame(
    {'bid': [0.7284, 0.7284, 0.7284, 0.7285, 0.7285],
     'bid_size': [4000000, 4000000, 5000000, 1000000, 4000000],
     'offer': [0.7285, 0.729, 0.7286, 0.7286, 0.729],
     'offer_size': [1000000, 4000000, 4000000, 4000000, 4000000]},
    index=pd.DatetimeIndex(['2000-1-1', '2001-1-1', '2002-1-1', '2003-1-1', '2004-1-1']))


df1 = df1.loc[~df1.index.duplicated(keep='first')]
#              price  side         timestamp
# 2000-01-01  0.7286     2  1451865675631331
# 2001-01-01  0.7286     2  1451865675631861
# 2002-01-01  0.7286     2  1451865675631866

df2 = df2.loc[~df2.index.duplicated(keep='first')]
#                bid  bid_size   offer  offer_size
# 2000-01-01  0.7284   4000000  0.7285     1000000
# 2001-01-01  0.7284   4000000  0.7290     4000000
# 2002-01-01  0.7284   5000000  0.7286     4000000
# 2003-01-01  0.7285   1000000  0.7286     4000000
# 2004-01-01  0.7285   4000000  0.7290     4000000

result = pd.concat([df1, df2], axis=0)
print(result)
               bid  bid_size   offer  offer_size   price  side     timestamp
2000-01-01     NaN       NaN     NaN         NaN  0.7286     2  1.451866e+15
2001-01-01     NaN       NaN     NaN         NaN  0.7286     2  1.451866e+15
2002-01-01     NaN       NaN     NaN         NaN  0.7286     2  1.451866e+15
2000-01-01  0.7284   4000000  0.7285     1000000     NaN   NaN           NaN
2001-01-01  0.7284   4000000  0.7290     4000000     NaN   NaN           NaN
2002-01-01  0.7284   5000000  0.7286     4000000     NaN   NaN           NaN
2003-01-01  0.7285   1000000  0.7286     4000000     NaN   NaN           NaN
2004-01-01  0.7285   4000000  0.7290     4000000     NaN   NaN           NaN

注意还有 pd.join,它可以基于索引连接DataFrame,并根据how参数处理非唯一索引。具有重复索引的行不会被删除。
In [94]: df1.join(df2)
Out[94]: 
             price  side         timestamp     bid  bid_size   offer  \
2000-01-01  0.7286     2  1451865675631331  0.7284   4000000  0.7285   
2000-01-01  0.7286     2  1451865675631400  0.7284   4000000  0.7285   
2001-01-01  0.7286     2  1451865675631861  0.7284   4000000  0.7290   
2002-01-01  0.7286     2  1451865675631866  0.7284   5000000  0.7286   

            offer_size  
2000-01-01     1000000  
2000-01-01     1000000  
2001-01-01     4000000  
2002-01-01     4000000  

In [95]: df1.join(df2, how='outer')
Out[95]: 
             price  side     timestamp     bid  bid_size   offer  offer_size
2000-01-01  0.7286     2  1.451866e+15  0.7284   4000000  0.7285     1000000
2000-01-01  0.7286     2  1.451866e+15  0.7284   4000000  0.7285     1000000
2001-01-01  0.7286     2  1.451866e+15  0.7284   4000000  0.7290     4000000
2002-01-01  0.7286     2  1.451866e+15  0.7284   5000000  0.7286     4000000
2003-01-01     NaN   NaN           NaN  0.7285   1000000  0.7286     4000000
2004-01-01     NaN   NaN           NaN  0.7285   4000000  0.7290     4000000

24

当你搜索这个错误时,这篇帖子会排在最前面,但是答案并不完整,所以让我来补充一下。造成这个错误的另一个原因是:如果你的数据框中有重复的列,则无法进行连接和提升。事实上,在原始问题中甚至有两个名为timestamp的列。因此最好检查所有要合并的数据框是否满足len(df.columns) == len(set(df.columns))


重复的列是我的问题。 - Lewis Morris
或者你可以使用:assert df.columns.is_unique, df.loc[:,df.columns.duplicated()]:这会断言列是唯一的,并显示重复的列(如果它们不是唯一的)。 - Wouter

8
作为尼古拉斯·莫利的回答的补充,当你发现即使这个方法也不起作用时:
df = df.reset_index(drop=True)

你应该检查列是否唯一。如果不唯一,即使重置索引也无效。必须先删除重复的列才能使其起作用。


4
这是因为您有重复的列。在连接之前,请分别删除每个DataFrame中的重复列,方法如下:
df = df.loc[:,~df.columns.duplicated()].reset_index(drop=True)

4
这也会发生在列名中存在重复的情况下。

3

两个数据框具有相同索引

这个问题的另一个原因可能是df1df2之间具有相同的索引。例如,两个数据框可能都具有相同的索引idx1

要检查是否存在此问题,您可以查看以下输出是否不为空列表:

print([org_name for org_name in cum_df.index if org_name in df_from_2002.index])

我的建议是重命名索引(所以df1仍然有idx1,而你需要在df2中将idx1更改为idx2),然后在连接(df1 = pd.concat([df1, df2]))之后,使用以下代码组合两个索引(如果你需要对它们求和):

df1.iloc[idx1] = df1.iloc[[idx1, idx2]].sum()

然后删除idx2

df1.drop([idx2], inplace=True)

2

当我试图连接两个有重复列名的数据框时,发生了这种情况!

假设我想删除第一个重复的列:

duplicated_column = 'column'

df_tmp = df[duplicated_column].T
df_tmp = df_tmp.iloc[1: , :]

df = df.drop([duplicated_column], axis=1)
df = pd.concat([df, df_tmp.T], axis=1)

2
对于我来说,问题在于重复的列标签,就像其他许多人在这里提到的那样。 为了仅保留重复项中的第一列,我使用了以下方法:
df=df.T[~df.T.index.duplicated(keep='first')].T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接