Python 比较两个数据帧的差异

Python 比较两个数据帧的差异,python,python-2.7,pandas,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=

我有一个脚本更新了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)

有什么想法吗?

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

要检查它们是否相等,您可以:

您可以使用以下内容将其包装到函数中:

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

讨论了一种更好的方法…

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

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]))

然后可以使用此索引信息返回表之间不匹配的值。因为它是零索引的,所以它指的是第二个位置的第二个数组,这是正确的。

不确定问题发布时是否存在这种情况,但熊猫现在有一个内置函数来测试两个数据帧之间的相等性:。

使用:dfu 1.equals(dfu 2)返回True或False,详情如下


更准确的比较应该单独检查索引名,因为
DataFrame.equals
不测试索引名。所有其他属性(索引值(单/多索引)、值、列、数据类型)都由它正确检查

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

注意:使用
index.names
而不是
index.name
使它也适用于多索引数据帧。

不确定这是否有用,但我快速组合了这个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)

在我的例子中,我有一个奇怪的错误,即使索引、列名 值相同,
数据帧
不匹配。我一直追查到 数据类型,而且似乎
熊猫
有时可以使用不同的数据类型, 导致这样的问题

例如:

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

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

如果您检查
param1.dtypes
param2.dtypes
,您会发现'a'是 为
param1
键入
object
,为
param2
键入
int64
。现在,如果你这样做了 某些操作使用
param1
param2
的组合,其他 数据帧的参数将偏离默认值

因此,在生成最终数据帧之后,即使 如果打印出来的是相同的,
final\u df1.equals(final\u df2)
,则可能是 不相等,因为那些samll参数,如轴1,
ObjectBlock
IntBlock
可能不同

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

final\u df1==final\u df2

但是,这将进行逐个元素的比较,因此如果 正在使用它断言语句,例如在
pytest

TL;博士 有效的方法是

all(final\u df1==final\u df2)

这将进行元素对元素的比较,同时忽略参数 比较起来很重要

TL;DR2
如果值和索引相同,但
final\u df1.equals(final\u df2)
显示
False
,则可以使用
final\u df1.\u data
final\u df2.\u data
检查数据帧的其余元素。

提取对称差异:

df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)
例如:

df1 = pd.DataFrame({
    'num': [1, 4, 3],
    'name': ['a', 'b', 'c'],
})
df2 = pd.DataFrame({
    'num': [1, 2, 3],
    'name': ['a', 'b', 'd'],
})
将产生:

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

df_diff = pd.concat([df1,df2], sort=False).drop_duplicates(keep=False)

不是熊猫方面的专家,但正常的平等性比较不应该起作用吗?我已经看过平等性,但我不确定如何使用该功能,我也无法在搜索中找到任何东西:(出于某种原因,我得到了一个异常:
exception:只能比较相同标签的DataFrame对象
,这就给出了答案,对吗?这意味着标签(行和列名/值)在Andy的包装中添加另一行:
Exception:return False
@Hyflex是的,正如Tom指出的,只需删除AssertionError(在它仅停止AssertionError并引发其他事件之前)…好的,我修复了标签(我没有意识到我必须对csvdat_old的标签顺序进行重新排序,我尝试将其纳入我的实际数据中,但即使数据在输出时是相同的,它也会更新,是否有办法找到/查看到底是什么“不同”?如何在这些帧中获得不同的值?这里的主要好处是您可以确定np返回的索引位置。在哪里确定表不匹配的确切位置,并提醒用户该位置。不,这是不存在的,它同样有效。(更好,因为这是一个单行vs 5行显示,它在浮点上工作吗?我希望有一个精度参数。必须有比这更好的参数。仅仅一个false不是一个令人满意的答案不确定这是否是大多数人想要的。
DataFrame.equals进行了非常深入的比较。例如..我有两个数据帧值是相等的。但是,
DataFrames
也有一些参数称为
Axis 1
IntBlock
ObjectBlock
。这些参数是在
pd.\u data
下定义的。如果这两个对象之间的参数不同,则会导致False@Nickpick
DataFrame.eq
可能很适合f或者定位不相等的元素?有一个问题:
索引。名称不进行比较。有关详细信息,请参阅我的答案:是否有人
df1 = pd.DataFrame({
    'num': [1, 4, 3],
    'name': ['a', 'b', 'c'],
})
df2 = pd.DataFrame({
    'num': [1, 2, 3],
    'name': ['a', 'b', 'd'],
})
df_diff = pd.concat([df1,df2], sort=False).drop_duplicates(keep=False)