比较两个pandas数据帧的差异

Ryf*_*lex 39 python python-2.7 pandas

我有一个脚本更新5-10列的数据,但有时启动csv将与结束csv相同,所以不要写相同的csv文件,我希望它什么也不做......

如何比较两个数据帧以检查它们是否相同?

csvdata = pandas.read_csv('csvfile.csv')
csvdata_old = csvdata

# ... do stuff with csvdata dataframe

if csvdata_old != csvdata:
    csvdata.to_csv('csvfile.csv', index=False)
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

And*_*den 54

您还需要小心创建DataFrame的副本,否则csvdata_old将使用csvdata更新(因为它指向同一个对象):

csvdata_old = csvdata.copy()
Run Code Online (Sandbox Code Playgroud)

要检查它们是否相等,可以在此答案中使用assert_frame_equal:

from pandas.util.testing import assert_frame_equal
assert_frame_equal(csvdata, csvdata_old)
Run Code Online (Sandbox Code Playgroud)

你可以将它包装在一个函数中,例如:

try:
    assert_frame_equal(csvdata, csvdata_old)
    return True
except:  # appeantly AssertionError doesn't catch all
    return False
Run Code Online (Sandbox Code Playgroud)

讨论了更好的方法......

  • 这给了你答案,对吧?据说标签(行和列名称/值)不相同,因此 DataFrame 不能相同。向 Andy 的包装器添加另一个 `except` 行:`except Exception: return False` (3认同)
  • pandas.util.testing 不再工作,你现在应该使用 pandas.testing (2认同)

小智 12

不确定问题发布时是否存在,但是pandas现在有一个内置函数来测试两个数据帧之间的相等性:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame .equals.html.

  • 它如何在浮子上工作?我希望有一个精度参数. (3认同)
  • 必须有比这更好的东西.只是假的不是一个令人满意的答案 (2认同)
  • 不确定这是否是大多数人想要的。`DataFrame.equals` 做了一个非常深入的比较。例如.. 我有 2 个值相等的数据帧.. 但事实证明,`DataFrames` 也有一些名为 `Axis 1`、`IntBlock` 和 `ObjectBlock` 的参数。这些在`pd._data`下定义。如果这些在 2 个对象之间不相同.. 将导致 False (2认同)

Sur*_*rya 7

检查使用:df_1.equals(df_2) #返回True或False,详情请见下文

In [45]: import numpy as np

In [46]: import pandas as pd

In [47]: np.random.seed(5)

In [48]: df_1= pd.DataFrame(np.random.randn(3,3))

In [49]: df_1
Out[49]: 
          0         1         2
0  0.441227 -0.330870  2.430771
1 -0.252092  0.109610  1.582481
2 -0.909232 -0.591637  0.187603

In [50]: np.random.seed(5)

In [51]: df_2= pd.DataFrame(np.random.randn(3,3))

In [52]: df_2
Out[52]: 
          0         1         2
0  0.441227 -0.330870  2.430771
1 -0.252092  0.109610  1.582481
2 -0.909232 -0.591637  0.187603

In [53]: df_1.equals(df_2)
Out[53]: True


In [54]: df_3= pd.DataFrame(np.random.randn(3,3))

In [55]: df_3
Out[55]: 
          0         1         2
0 -0.329870 -1.192765 -0.204877
1 -0.358829  0.603472 -1.664789
2 -0.700179  1.151391  1.857331

In [56]: df_1.equals(df_3)
Out[56]: False
Run Code Online (Sandbox Code Playgroud)


Tom*_*pin 7

不确定这是否有帮助,但我鞭打了这个快速的python方法,仅返回两个具有相同列和形状的数据框之间的差异。

def get_different_rows(source_df, new_df):
    """Returns just the rows from the new dataframe that differ from the source dataframe"""
    merged_df = source_df.merge(new_df, indicator=True, how='outer')
    changed_rows_df = merged_df[merged_df['_merge'] == 'right_only']
    return changed_rows_df.drop('_merge', axis=1)
Run Code Online (Sandbox Code Playgroud)

  • 这就是我实际上正在寻找的答案。非常感谢 (3认同)

Tri*_*ard 6

这比较了两个数据帧的,注意表之间的行/列数需要相同

comparison_array = table.values == expected_table.values
print (comparison_array)

>>>[[True, True, True]
    [True, False, True]]

if False in comparison_array:
    print ("Not the same")

#Return the position of the False values
np.where(comparison_array==False)

>>>(array([1]), array([1]))
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用此索引信息返回表之间不匹配的值.由于它是零索引,它指的是第二个位置的第二个数组是正确的.


Den*_*zov 6

比较准确的比较应该单独检查索引名称,因为DataFrame.equals不会对此进行测试。所有其他属性(索引值(单/多索引),值,列,dtypes)均由其正确检查。

df1 = pd.DataFrame([[1, 'a'], [2, 'b'], [3, 'c']], columns=['num', 'name'])
df1 = df1.set_index('name')
df2 = pd.DataFrame([[1, 'a'], [2, 'b'], [3, 'c']], columns=['num', 'another_name'])
df2 = df2.set_index('another_name')

df1.equals(df2)
True

df1.index.names == df2.index.names
False
Run Code Online (Sandbox Code Playgroud)

注意:使用index.names代替index.name使其也适用于多索引数据框。


alp*_*989 6

就我而言,我有一个奇怪的错误,即使索引、列名和值相同,也不DataFrames匹配。我追踪到数据类型,似乎pandas有时可以使用不同的数据类型,导致这样的问题

例如:

param2 = pd.DataFrame({'a': [1]}) param1 = pd.DataFrame({'a': [1], 'b': [2], 'c': [2], 'step': ['alpha']})

如果您检查param1.dtypesand param2.dtypes,您会发现 'a' 的类型是objectforparam1并且是int64for的类型param2。现在,如果你使用的组合一些操作param1param2,数据帧的其他参数会偏离默认的。

从而产生最终的数据帧之后,即使被打印出的实际值是相同的,final_df1.equals(final_df2)可以变成是不等于,因为那些samll参数喜欢Axis 1ObjectBlockIntBlockmaynot是相同的。

解决此问题并比较值的一种简单方法是使用

final_df1==final_df2.

但是,这将进行逐个元素的比较,因此如果您使用它来断言声明,例如 in pytest.

TL; 博士

什么效果好是

all(final_df1 == final_df2).

这是一个逐个元素的比较,同时忽略了对比较不重要的参数。

TL;DR2

如果您的值和索引相同,但final_df1.equals(final_df2)显示False,则可以使用final_df1._datafinal_df2._data检查数据框的其余元素。


lee*_*sej 6

拉出对称差异:

df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)
Run Code Online (Sandbox Code Playgroud)

例如:

df1 = pd.DataFrame({
    'num': [1, 4, 3],
    'name': ['a', 'b', 'c'],
})
df2 = pd.DataFrame({
    'num': [1, 2, 3],
    'name': ['a', 'b', 'd'],
})
Run Code Online (Sandbox Code Playgroud)

将产生:

在此处输入图片说明

注意:在pandas 的下一个版本发布之前,为了避免关于未来如何设置sort 参数的警告,只需添加该sort=False参数即可。如下:

df_diff = pd.concat([df1,df2], sort=False).drop_duplicates(keep=False)
Run Code Online (Sandbox Code Playgroud)