J'ai un script qui met à jour 5-10 colonnes de données, mais parfois le csv de départ sera identique au csv de fin, alors au lieu d'écrire un fichier csv identique, je ne veux rien faire ...
Comment comparer deux images pour vérifier si elles sont identiques ou non?
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)
Des idées?
Vous devez également faire attention à créer une copie du DataFrame, sinon csvdata_old sera mis à jour avec csvdata (car il pointe sur le même objet):
csvdata_old = csvdata.copy()
Pour vérifier si elles sont égales, vous pouvez utiliser assert_frame_equal comme dans cette réponse :
from pandas.util.testing import assert_frame_equal
assert_frame_equal(csvdata, csvdata_old)
Vous pouvez envelopper ceci dans une fonction avec quelque chose comme:
try:
assert_frame_equal(csvdata, csvdata_old)
return True
except: # appeantly AssertionError doesn't catch all
return False
Il y avait une discussion sur une meilleure façon ...
Je ne sais pas si cela existait au moment où la question a été posée, mais les pandas ont maintenant une fonction intégrée pour tester l'égalité entre deux cadres de données: http://pandas.pydata.org/pandas-docs/stable/generated/pandas .DataFrame.equals.html .
Vérifiez en utilisant: df_1.equals (df_2) # Retourne Vrai ou Faux, détails ci-dessous
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
Ceci compare les values de deux cadres de données, notez que le nombre de lignes/colonnes doit être identique entre les tables
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]))
Vous pouvez ensuite utiliser ces informations d'index pour renvoyer la valeur qui ne correspond pas entre les tables. Comme il est indexé à zéro, il fait référence au second tableau en 2e position, ce qui est correct.
Je ne suis pas sûr que cela soit utile ou non, mais j'ai regroupé cette méthode rapide en python pour ne renvoyer que les différences entre deux images contenant les mêmes colonnes et la même forme.
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)
Une comparaison plus précise devrait vérifier les noms d'index séparément, car DataFrame.equals
ne le teste pas. Toutes les autres propriétés (valeurs d'index (single/multi-index), valeurs, colonnes, dtypes) sont vérifiées correctement.
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
Remarque: l'utilisation de index.names
au lieu de index.name
le fait également fonctionner pour les images multi-indexées.
Dans mon cas, j’ai eu une erreur étrange, alors que même si les indices, les noms de colonnes .__ et les valeurs étaient identiques, la variable DataFrames
ne correspondait pas. Je l'ai retrouvé jusqu'aux types de données , Et il semble que pandas
puisse parfois utiliser différents types de données, , Ce qui entraîne de tels problèmes
Par exemple:
param2 = pd.DataFrame({'a': [1]})
param1 = pd.DataFrame({'a': [1], 'b': [2], 'c': [2], 'step': ['alpha']})
si vous cochez param1.dtypes
et param2.dtypes
, vous constaterez que 'a' est de type type object
pour param1
et de type int64
pour param2
. Maintenant, si vous manipulez une manipulation en utilisant param1
et param2
, les autres paramètres Du cadre de données différeront de ceux par défaut.
Ainsi, après la génération de la structure de données finale, même si les valeurs réelles imprimées Sont identiques, final_df1.equals(final_df2)
, peut s'avérer être Pas égal, car ces paramètres identiques à Axis 1
, ObjectBlock
, IntBlock
peut ne pas être la même chose.
Un moyen facile de contourner ce problème et de comparer les valeurs consiste à utiliser
final_df1==final_df2
.
Cependant, cela fera une comparaison élément par élément, donc cela ne fonctionnera pas si vous l'utilisez pour affirmer une déclaration, par exemple dans pytest
.
Ce qui fonctionne bien c'est
all(final_df1 == final_df2)
.
Ceci fait une comparaison élément par élément, tout en négligeant les paramètres non importants pour la comparaison.
Si vos valeurs et vos index sont identiques, mais que final_df1.equals(final_df2)
affiche False
, vous pouvez utiliser final_df1._data
et final_df2._data
pour vérifier le reste des éléments des images.