python - column - Comparando dos dataframes de pandas para las diferencias
pandas python (7)
En mi caso, tuve un error extraño, por el cual, aunque los índices, nombres de columna y valores eran los mismos, los DataFrames
coincidían. Lo rastreé hasta los tipos de datos, y parece que los pandas
veces pueden usar diferentes tipos de datos, lo que da como resultado tales problemas
Por ejemplo:
param2 = pd.DataFrame({''a'': [1]}) param1 = pd.DataFrame({''a'': [1], ''b'': [2], ''c'': [2], ''step'': [''alpha'']})
si comprueba param1.dtypes
y param2.dtypes
, encontrará que ''a'' es de tipo object
para param1
y es de tipo int64
para param2
. Ahora, si realiza alguna manipulación usando una combinación de param1
y param2
, otros parámetros del marco de datos se desviarán de los predeterminados.
Así que después de que se genera el marco de datos final, aunque los valores reales que se imprimen son los mismos, final_df1.equals(final_df2)
puede resultar no igual, porque esos parámetros ObjectBlock
como el Axis 1
, ObjectBlock
, IntBlock
pueden no ser el mismo.
Una manera fácil de evitar esto y comparar los valores es usar
final_df1==final_df2
.
Sin embargo, esto hará un elemento por comparación de elementos, por lo que no funcionará si lo está utilizando para afirmar una declaración, por ejemplo, en pytest
.
TL; DR
Lo que funciona bien es
all(final_df1 == final_df2)
.
Esto hace una comparación de elemento por elemento, mientras que descuida los parámetros que no son importantes para la comparación.
TL; DR2
Si sus valores e índices son los mismos, pero final_df1.equals(final_df2)
muestra False
, puede usar final_df1._data
y final_df2._data
para verificar el resto de los elementos de los dataframes.
Tengo un script que actualiza datos de 5-10 columnas, pero a veces el csv de inicio será idéntico al csv final, así que en lugar de escribir un archivo csv idéntico, no quiero que haga nada ...
¿Cómo puedo comparar dos marcos de datos para verificar si son iguales o no?
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)
¿Algunas ideas?
Esto compara los valores de dos marcos de datos. Tenga en cuenta que el número de filas / columnas debe ser el mismo entre las tablas.
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]))
A continuación, puede utilizar esta información de índice para devolver el valor que no coincide entre las tablas. Como está indexado en cero, se refiere a la segunda matriz en la 2da posición, que es la correcta.
No estoy seguro de si esto existía en el momento en que se publicó la pregunta, pero ahora los pandas tienen una función integrada para probar la igualdad entre dos marcos de datos: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.equals.html .
No estoy seguro si esto es útil o no, pero armé este rápido método de pitón para devolver solo las diferencias entre dos marcos de datos que tienen las mismas columnas y forma.
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)
También debe tener cuidado de crear una copia del DataFrame; de lo contrario, csvdata_old se actualizará con csvdata (ya que apunta al mismo objeto):
csvdata_old = csvdata.copy()
Para comprobar si son iguales, puede usar assert_frame_equal como en esta respuesta :
from pandas.util.testing import assert_frame_equal
assert_frame_equal(csvdata, csvdata_old)
Puede envolver esto en una función con algo como:
try:
assert_frame_equal(csvdata, csvdata_old)
return True
except: # appeantly AssertionError doesn''t catch all
return False
Hubo una discusión sobre una mejor manera ...
Una comparación más precisa debería verificar los nombres de los índices por separado, porque DataFrame.equals
no prueba eso. Todas las otras propiedades (valores de índice (single / multiindex), valores, columnas, dtypes) se verifican correctamente.
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
Nota: el uso de index.names
lugar de index.name
hace funcionar para index.name
de index.name
multi-indexados.
Verifique usando: df_1.equals (df_2) # Devuelve verdadero o falso , detalles a continuación
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