Concat DataFrame Reindexing 仅对具有唯一值的 Index 对象有效

Posted

技术标签:

【中文标题】Concat DataFrame Reindexing 仅对具有唯一值的 Index 对象有效【英文标题】:Concat DataFrame Reindexing only valid with uniquely valued Index objects 【发布时间】:2016-05-07 03:52:50 【问题描述】:

我正在尝试连接以下数据框:

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 - 但我根本不知道出了什么问题。

【问题讨论】:

pd.concat 是做什么的? @gmoshkin 它将数据帧作为一个数据帧放在一起 - 在轴上连接。 我已经从 df1 和 df2 中删除了列时间戳,并尝试使用 df1.dropna() 和 df2.dropna() 删除和 NA;问题依旧...... @gmoshkin,我假设 pd 作为 pandas 的别名:import pandas as pd,df1 和 df2 是 pandas DataFrame 对象 要查找的其他内容,我遇到了类似的错误,因为我的数据框中有重复的列 【参考方案1】:

您无需更改数据或删除重复数据即可缓解此错误。只需使用DataFrame.reset_index 创建一个新索引:

df = df.reset_index()

旧索引作为列保存在数据框中,但如果您不需要它,您可以这样做:

df = df.reset_index(drop=True)

有些人更喜欢:

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

【讨论】:

这应该被标记为正确答案,因为它在不丢失信息的情况下解决了问题。数据集上的重复记录并不总是错误的。 我仍然收到错误,即使我对数据集执行此转换 如果这不起作用怎么办? pd.concat([df_1a.reset_index()[common_features], df_1b.reset_index()[common_features]]) > InvalidIndexError:重新索引仅对具有唯一值的索引对象有效 就我而言,我有一个重复的列(希望对其他人有帮助!)。【参考方案2】:

pd.concat 要求 索引 是唯一的。要remove rows with duplicate indices,请使用

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

【讨论】:

【参考方案3】:

列名重复!

在我的情况下,问题是因为我有重复的列名。

【讨论】:

【参考方案4】:

当您搜索错误但答案不完整时,此帖子出现在顶部,所以让我添加我的。发生此错误的另一个原因是:如果您的数据框中有重复的列,您将无法连接并引发此错误。事实上,即使在最初的问题中,也有两列称为timestamp。因此,最好检查 len(df.columns) == len(set(df.columns)) 是否适用于您尝试连接的所有数据帧。

【讨论】:

重复列是我的问题。【参考方案5】:

作为 Nicholas Morley 回答的补充,当您发现即使这样也行不通时:

df = df.reset_index(drop=True)

您应该检查列是否唯一。当它们不是时,即使重置索引也不起作用。应首先删除重复的列以使其正常工作。

【讨论】:

【参考方案6】:

此页面的最佳解决方案: https://pandas.pydata.org/pandas-docs/version/0.20/merging.html

df = pd.concat([df1, df2], axis=1, join_axes=[df1.index])

【讨论】:

【参考方案7】:

当您在列名中有重复时也会发生这种情况。

【讨论】:

【参考方案8】:

两个 DF 之间的相同索引

此问题的另一个原因可能是 df1df2 可能在彼此之间具有相同的索引。例如,两个 dfs 可能具有相同的索引 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)

【讨论】:

以上是关于Concat DataFrame Reindexing 仅对具有唯一值的 Index 对象有效的主要内容,如果未能解决你的问题,请参考以下文章

pandas中,dataframe 进行数据合并-pd.concat()

为 pandas.DataFrame 复制 GROUP_CONCAT

pandas使用pd.concat纵向合并多个dataframe实战:多个dataframe的纵向合并为纵向合并的多个dataframe设置标识符指定数据来源

python 将concat dir文件导入Dataframe

Pandas DataFrame concat vs append

Pandas 基础 - 用 concat 组合 dataframe