Pandas“只能比较相同标签的DataFrame对象”错误

2025-02-28 08:22:00
admin
原创
93
摘要:问题描述:我正在使用 Pandas 比较加载到两个数据框(uat,prod)中的两个文件的输出:......uat = uat[['Customer Number','Product']] prod = prod[['Customer Number','Product']] print uat['Custom...

问题描述:

我正在使用 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 对象。如果前两次比较正常,那么第三次有什么问题?

谢谢


解决方案 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

一种解决方案是先对索引进行排序(注意:某些函数需要排序索引):

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

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

注意:对列的顺序==也敏感,因此您可能必须使用: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

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

解决方案 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))

解决方案 3:

当提出这个问题时,Pandas 中没有其他函数可以测试相等性,但是不久前已经添加了它:pandas.equals

你可以像这样使用它:

df1.equals(df2)

一些不同之处==是:

  • 您没有收到问题中描述的错误

  • 它返回一个简单的布尔值。

  • 同一位置的 NaN 值被视为相等

  • 2 DataFrames 需要具有相同的内容dtype才被视为相等,请参阅此 stackoverflow 问题

编辑:正如@paperskilltrees 回答

中指出的那样,索引对齐很重要。除了提供的解决方案之外,另一个选项是在比较 DataFrames 之前对 DataFrames 的索引进行排序。为此,将是。df1`df1.sort_index(inplace=True)`

解决方案 4:

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

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

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

这应该可行

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 的答案很棒错了:它使用DataFrame.equals,在你的情况下会返回False。相反,你想使用DataFrame.eq,它会返回True

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

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

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

  1. 没有给出关于对齐的明确指示:==又名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

PS当您将数据框与自身进行比较时,它会自动对齐,因此我们可能会忘记对齐。这是否意味着上述所有方法都会给您?仅适用于没有True缺失值的数据框。但是,如果数据框包含缺失值,则会产生,而所有其他方法都会产生。这是因为将两个视为相等,这是非常不寻常的(按照惯例,是)。equals()`TrueFalseequals()NaNnp.nan == np.nan`False

解决方案 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

解决方案 7:

我在尝试对数据框列表进行排序时遇到了这个问题。

我尝试根据索引对一些数据框进行排序并将其连接在一起。

例如,我有:

  • 2022 年数据的数据框,索引范围从 2022-01-01 到 2022-12-31

  • 2023 年数据的数据框,索引范围从 2023-01-01 到 2023-12-31

  • 数据框有一个索引,它是一个日期时间对象

在这种情况下,我需要做的是添加一个keylambda 函数,sorted如下所示:

df_list_sorted = sorted(df_list, key=lambda df: df.iloc[0].name)

这里的关键点是:提供某种方法来指定如何对数据框进行排序。这应该使用函数key的参数来完成sorted,您可以提供(例如)一个 lambda 函数来提取要排序的键。

这在此示例中有效,因为数据框包含有序且不重叠的索引。

您还可以通过以下方式获得相同的结果:

  • 连接数据框

  • 对索引进行就地排序

这对于更复杂的情况有效,其中数据框可能在其索引中重叠,或者索引可能未排序。

但是,它当然会更慢,因为在数据帧连接之后需要进行额外的就地排序。

解决方案 8:

我找到了我案例中错误的来源:

问题是列名列表意外地被包含在另一个列表中。

考虑以下例子:

column_names=['warrior','eat','ok','monkeys']

df_good = pd.DataFrame(np.ones(shape=(6,4)),columns=column_names)
df_good['ok'] < df_good['monkeys']

>>> 0    False
    1    False
    2    False
    3    False
    4    False
    5    False

df_bad = pd.DataFrame(np.ones(shape=(6,4)),columns=[column_names])
df_bad ['ok'] < df_bad ['monkeys']

>>> ValueError: Can only compare identically-labeled DataFrame objects

问题是你无法从视觉上区分坏的 DataFrame 和好的 DataFrame。

解决方案 9:

就我而言,我只是在创建数据框时直接写入参数,因为一个 sql 查询中的数据带有名称,而其他查询中没有

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2941  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1803  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   31  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   31  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   28  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用