tutorial index from espaƱol empty create column python pandas equality nan

python - index - pandas dataframe tutorial



Pandas DataFrames con comparaciĆ³n de igualdad NaNs (5)

En el contexto de la prueba unitaria de algunas funciones, estoy tratando de establecer la igualdad de 2 DataFrames usando pandas python:

ipdb> expect 1 2 2012-01-01 00:00:00+00:00 NaN 3 2013-05-14 12:00:00+00:00 3 NaN ipdb> df identifier 1 2 timestamp 2012-01-01 00:00:00+00:00 NaN 3 2013-05-14 12:00:00+00:00 3 NaN ipdb> df[1][0] nan ipdb> df[1][0], expect[1][0] (nan, nan) ipdb> df[1][0] == expect[1][0] False ipdb> df[1][1] == expect[1][1] True ipdb> type(df[1][0]) <type ''numpy.float64''> ipdb> type(expect[1][0]) <type ''numpy.float64''> ipdb> (list(df[1]), list(expect[1])) ([nan, 3.0], [nan, 3.0]) ipdb> df1, df2 = (list(df[1]), list(expect[1])) ;; df1 == df2 False

Dado que estoy tratando de probar todo lo expect contra todo df , incluidas las posiciones de NaN , ¿qué estoy haciendo mal?

¿Cuál es la forma más sencilla de comparar la igualdad de Series / DataFrames incluyendo NaN s?


Cualquier comparación de igualdad utilizando == con np.NaN es False, incluso np.NaN == np.NaN es False.

Simplemente, df1.fillna(''NULL'') == df2.fillna(''NULL'') , si ''NULL'' no es un valor en los datos originales.

Para estar seguro, haga lo siguiente:

Ejemplo a) Compara dos marcos de datos con valores de NaN

bools = (df1 == df2) bools[pd.isnull(df1) & pd.isnull(df2)] = True assert bools.all().all()

Ejemplo b) Filtrar filas en df1 que no coinciden con df2

bools = (df1 != df2) bools[pd.isnull(df1) & pd.isnull(df2)] = False df_outlier = df1[bools.all(axis=1)]

(Nota: esto es incorrecto - bools [pd.isnull (df1) == pd.isnull (df2)] = False)


Me gusta la respuesta de @PhillipCloud, pero está más escrita

In [26]: df1 = DataFrame([[np.nan,1],[2,np.nan]]) In [27]: df2 = df1.copy()

Realmente son equivalentes.

In [28]: result = df1 == df2 In [29]: result[pd.isnull(df1) == pd.isnull(df2)] = True In [30]: result Out[30]: 0 1 0 True True 1 True True

Un nan en df2 que no existe en df1

In [31]: df2 = DataFrame([[np.nan,1],[np.nan,np.nan]]) In [32]: result = df1 == df2 In [33]: result[pd.isnull(df1) == pd.isnull(df2)] = True In [34]: result Out[34]: 0 1 0 True True 1 False True

También puede rellenar con un valor que sepa que no está en el marco

In [38]: df1.fillna(-999) == df1.fillna(-999) Out[38]: 0 1 0 True True 1 True True


Puede usar assert_frame_equals con check_names = False (para no verificar los nombres de los índices / columnas), que aparecerán si no son iguales:

In [11]: from pandas.util.testing import assert_frame_equal In [12]: assert_frame_equal(df, expected, check_names=False)

Puedes envolver esto en una función con algo como:

try: assert_frame_equal(df, expected, check_names=False) return True except AssertionError: return False

En pandas más recientes, esta funcionalidad se ha agregado como .equals :

df.equals(expected)


Una de las propiedades de NaN es que NaN != NaN es True .

Echa un vistazo a esta respuesta para una buena manera de hacerlo usando numexpr .

(a == b) | ((a != a) & (b != b))

Dice esto (en pseudocódigo):

a == b or (isnan(a) and isnan(b))

Entonces, o a es igual a b , o ambos a y b son NaN .

Si tiene marcos pequeños, entonces assert_frame_equal estará bien. Sin embargo, para cuadros grandes (10M filas) assert_frame_equal es bastante inútil. Tuve que interrumpirlo, estaba tardando tanto.

In [1]: df = DataFrame(rand(1e7, 15)) In [2]: df = df[df > 0.5] In [3]: df2 = df.copy() In [4]: df Out[4]: <class ''pandas.core.frame.DataFrame''> Int64Index: 10000000 entries, 0 to 9999999 Columns: 15 entries, 0 to 14 dtypes: float64(15) In [5]: timeit (df == df2) | ((df != df) & (df2 != df2)) 1 loops, best of 3: 598 ms per loop

timeit del bool único (probablemente) deseado que indica si los dos DataFrame s son iguales:

In [9]: timeit ((df == df2) | ((df != df) & (df2 != df2))).values.all() 1 loops, best of 3: 687 ms per loop


df.fillna(0) == df2.fillna(0)

Puedes usar fillna() . Documenación aquí .

from pandas import DataFrame # create a dataframe with NaNs df = DataFrame([{''a'': 1, ''b'': 2}, {''a'': 5, ''b'': 10, ''c'': 20}]) df2 = df # comparison fails! print df == df2 # all is well print df.fillna(0) == df2.fillna(0)