【问题标题】:Pandas "Can only compare identically-labeled DataFrame objects" error熊猫“只能比较相同标签的 DataFrame 对象”错误
【发布时间】:2013-08-31 12:54:12
【问题描述】:

我正在使用 Pandas 比较加载到两个数据帧(uat、prod)中的两个文件的输出: ...

uat = uat[['Customer Number','Product']]
prod = prod[['Customer Number','Product']]
print uat['Customer Number'] == prod['Customer Number']
print uat['Product'] == prod['Product']
print uat == prod

The first two match exactly:
74357    True
74356    True
Name: Customer Number, dtype: bool
74357    True
74356    True
Name: Product, dtype: bool

对于第三次打印,我收到一个错误: 只能比较具有相同标签的 DataFrame 对象。如果前两个比较好,第三个有什么问题?

谢谢

【问题讨论】:

  • 使用pd.concat 后出现此问题,对此question 的回答有帮助
  • 遇到了这个问题,对我来说有点用,说你想比较 id 值:(df_1.sort_values('id').id.values == df_2.sort_values('id').id.values).all()

标签: python pandas


【解决方案1】:

这里有一个小例子来证明这一点(它只适用于 DataFrames,而不是 Series,直到 Pandas 0.19 它适用于两者):

In [1]: df1 = pd.DataFrame([[1, 2], [3, 4]])

In [2]: df2 = pd.DataFrame([[3, 4], [1, 2]], index=[1, 0])

In [3]: df1 == df2
Exception: Can only compare identically-labeled DataFrame objects

一个解决方案是先sort the index(注:some functions require sorted indexes):

In [4]: df2.sort_index(inplace=True)

In [5]: df1 == df2
Out[5]: 
      0     1
0  True  True
1  True  True

注意:== 也是sensitive to the order of columns,所以你可能不得不使用sort_index(axis=1):

In [11]: df1.sort_index().sort_index(axis=1) == df2.sort_index().sort_index(axis=1)
Out[11]: 
      0     1
0  True  True
1  True  True

注意:这仍然会引发(如果索引/列在排序后没有相同的标签)。

【讨论】:

  • sort_index 将我的数据框更改为非类型。这将我从“ValueError:只能比较标记相同的系列对象”中得到的错误更改为“AttributeError:'NoneType'对象没有属性'join'”。
  • @R.Cox 我猜你正在做类似df = df.sort_index(inplace=True) 的事情,如果你使用inplace 你不需要df = ,它会修改/更新df DataFrame/变量,并且表达式返回无。
  • step1:- df1.reset_index(drop=True,inplace=True) step2:- df2.reset_index(drop=True,inplace=True) step3:- df1 == df2
【解决方案2】:

如果不需要比较,也可以尝试删除索引列:

print(df1.reset_index(drop=True) == df2.reset_index(drop=True))

我在单元测试中使用了同样的技术,如下所示:

from pandas.util.testing import assert_frame_equal

assert_frame_equal(actual.reset_index(drop=True), expected.reset_index(drop=True))

【讨论】:

  • 上帝保佑你。我一直在努力解决类似行无法在不同 DataFrame 之间进行比较的问题,并且删除索引允许它执行比较。
  • 您可以考虑添加inplace=True 以确保索引为下游比较。
  • 当上述答案没有帮助时,这会有所帮助。谢谢! :)
【解决方案3】:

在问这个问题的时候,Pandas 中没有另一个函数来测试相等性,但它已经在不久前添加了:pandas.equals

你可以这样使用它:

df1.equals(df2)

与== 的一些区别是:

  • 您没有收到问题中描述的错误
  • 它返回一个简单的布尔值。
  • 同一位置的 NaN 值被视为相等
  • 2 DataFrames 需要具有相同的dtype 才能被视为相等,请参阅this stackoverflow question

编辑:
正如@paperskilltrees answer 中指出的那样,索引对齐很重要。除了提供的解决方案之外,另一个选项是在比较 DataFrame 之前sort the index of the DataFrames。对于df1,那就是df1.sort_index(inplace=True)。

【讨论】:

  • 一个非常有帮助但错误的答案。我在my answer 中解释过
【解决方案4】:

比较两个DataFrame时,必须确保第一个DataFrame中的记录数与第二个DataFrame中的记录数匹配。在我们的示例中,两个 DataFrame 中的每一个都有 4 条记录,包括 4 种产品和 4 种价格。

例如,如果其中一个 DataFrame 有 5 个产品,而另一个 DataFrame 有 4 个产品,并且您尝试运行比较,则会收到以下错误:

ValueError:只能比较标签相同的系列对象

这应该可以工作

import pandas as pd
import numpy as np

firstProductSet = {'Product1': ['Computer','Phone','Printer','Desk'],
                   'Price1': [1200,800,200,350]
                   }
df1 = pd.DataFrame(firstProductSet,columns= ['Product1', 'Price1'])


secondProductSet = {'Product2': ['Computer','Phone','Printer','Desk'],
                    'Price2': [900,800,300,350]
                    }
df2 = pd.DataFrame(secondProductSet,columns= ['Product2', 'Price2'])


df1['Price2'] = df2['Price2'] #add the Price2 column from df2 to df1

df1['pricesMatch?'] = np.where(df1['Price1'] == df2['Price2'], 'True', 'False')  #create new column in df1 to check if prices match
df1['priceDiff?'] = np.where(df1['Price1'] == df2['Price2'], 0, df1['Price1'] - df2['Price2']) #create new column in df1 for price diff 
print (df1)

来自https://datatofish.com/compare-values-dataframes/的示例

【讨论】:

    【解决方案5】:

    Flyingdutchman's answer 很好但错误:它使用DataFrame.equals,在您的情况下将返回False。 相反,您想使用DataFrame.eq,它将返回True。

    似乎DataFrame.equals 忽略了数据帧的索引,而DataFrame.eq 使用数据帧的索引进行对齐,然后比较对齐的值。这是quote Pandas 的核心问题的机会:

    这是一个需要牢记的基本原则:数据对齐是内在的。除非您明确这样做,否则标签和数据之间的链接不会断开。

    正如我们在以下示例中所见,除非明确要求,否则数据对齐既不会中断,也不会强制执行。所以我们有三种不同的情况。

    1. 没有给出关于对齐的明确说明:== aka DataFrame.__eq__,
    
       In [1]: import pandas as pd
       In [2]: df1 = pd.DataFrame(index=[0, 1, 2], data={'col1':list('abc')})
       In [3]: df2 = pd.DataFrame(index=[2, 0, 1], data={'col1':list('cab')})
       In [4]: df1 == df2
       ---------------------------------------------------------------------------
       ...
       ValueError: Can only compare identically-labeled DataFrame objects
    
    
    1. 对齐被明确破坏:DataFrame.equals,DataFrame.values,DataFrame.reset_index(),
        In [5]: df1.equals(df2)
        Out[5]: False
    
        In [9]: df1.values == df2.values
        Out[9]: 
        array([[False],
               [False],
               [False]])
    
        In [10]: (df1.values == df2.values).all().all()
        Out[10]: False
    
    
    1. 明确强制执行对齐:DataFrame.eq、DataFrame.sort_index()、
    
        In [6]: df1.eq(df2)
        Out[6]: 
           col1
        0  True
        1  True
        2  True
    
        In [8]: df1.eq(df2).all().all()
        Out[8]: True
        
    

    我的答案是熊猫版1.0.3。

    【讨论】:

      【解决方案6】:

      在这里,我将展示如何处理此错误的完整示例。我添加了带零的行。您可以从 csv 或任何其他来源获取数据框。

      import pandas as pd
      import numpy as np
      
      
      # df1 with 9 rows
      df1 = pd.DataFrame({'Name':['John','Mike','Smith','Wale','Marry','Tom','Menda','Bolt','Yuswa',],
          'Age':[23,45,12,34,27,44,28,39,40]})
      
      # df2 with 8 rows
      df2 = pd.DataFrame({'Name':['John','Mike','Wale','Marry','Tom','Menda','Bolt','Yuswa',],
          'Age':[25,45,14,34,26,44,29,42]})
      
      
      # get lengths of df1 and df2
      df1_len = len(df1)
      df2_len = len(df2)
      
      
      diff = df1_len - df2_len
      
      rows_to_be_added1 = rows_to_be_added2 = 0
      # rows_to_be_added1 = np.zeros(diff)
      
      if diff < 0:
          rows_to_be_added1 = abs(diff)
      else:
          rows_to_be_added2 = diff
          
      # add empty rows to df1
      if rows_to_be_added1 > 0:
          df1 = df1.append(pd.DataFrame(np.zeros((rows_to_be_added1,len(df1.columns))),columns=df1.columns))
      
      # add empty rows to df2
      if rows_to_be_added2 > 0:
          df2 = df2.append(pd.DataFrame(np.zeros((rows_to_be_added2,len(df2.columns))),columns=df2.columns))
      
      # at this point we have two dataframes with the same number of rows, and maybe different indexes
      # drop the indexes of both, so we can compare the dataframes and other operations like update etc.
      df2.reset_index(drop=True, inplace=True)
      df1.reset_index(drop=True, inplace=True)
      
      # add a new column to df1
      df1['New_age'] = None
      
      # compare the Age column of df1 and df2, and update the New_age column of df1 with the Age column of df2 if they match, else None
      df1['New_age'] = np.where(df1['Age'] == df2['Age'], df2['Age'], None)
      
      # drop rows where Name is 0.0
      df2 = df2.drop(df2[df2['Name'] == 0.0].index)
      
      # now we don't get the error ValueError: Can only compare identically-labeled Series objects
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-08
        • 2018-01-25
        相关资源
        最近更新 更多