Pandas DataFrames с сравнением равенства NaNs

В контексте модульного тестирования некоторых функций я пытаюсь установить равенство 2 DataFrames с использованием python pandas:

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 

Учитывая, что я пытаюсь проверить весь expect против всего df , включая позиции NaN , что я делаю неправильно?

Каков самый простой способ сравнить равенство рядов / DataFrames, включая NaN s?

5 Solutions collect form web for “Pandas DataFrames с сравнением равенства NaNs”

Вы можете использовать assert_frame_equals с check_names = False (чтобы не проверять имена индексов / столбцов), которые будут повышаться, если они не равны:

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

Вы можете обернуть это в функцию с чем-то вроде:

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

В более поздних пандах эта функциональность была добавлена ​​как .equals :

 df.equals(expected) 

Одним из свойств NaN является то, что NaN != NaN является True .

Отметьте этот ответ для хорошего способа сделать это, используя numexpr .

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

говорит это (в псевдокоде):

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

Таким образом, либо a равно b , либо оба a и b являются NaN .

Если у вас маленькие кадры, тогда assert_frame_equal будет в порядке. Однако для больших кадров (10M строк) assert_frame_equal практически бесполезен. Я должен был прервать его, это было так долго.

 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 (предположительно) желаемого единственного bool указывающего, равны ли два DataFrame s:

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

Как @PhillipCloud ответ, но больше выписано

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

Они действительно эквивалентны

 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 

Нан в df2, который не существует в 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 

Вы также можете заполнить значением, которое, как вы знаете, не должно быть в кадре

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

Вы можете использовать fillna() . Представление здесь .

 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) 

Любое сравнение равенства с использованием n с np.NaN является False, даже np.NaN == np.NaN является False.

Просто df1.fillna('NULL') == df2.fillna('NULL') , если «NULL» не является значением в исходных данных.

Чтобы быть в безопасности, выполните следующие действия:

Пример a) Сравните два кадра данных с значениями NaN

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

Пример b) Фильтровать строки в df1, которые не совпадают с df2

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

(Примечание: это неверно – bools [pd.isnull (df1) == pd.isnull (df2)] = False)

  • Pandas Statsmodels ols прогнозирование регрессии с использованием предсказателя DF?
  • Элементы процесса с одинаковым идентификатором
  • Ускорение за последние 60 дней в пандах
  • Слияние данных в ближайшем времени datetime / timestamp
  • Pandas HDF5 как база данных
  • Добавить дополнительный столбец как совокупную временную разницу
  • Планирование кадров данных Pandas
  • Python & Pandas: как запросить, если столбец типа списка содержит что-то?
  •  
    Interesting Posts for Van-Lav

    Виртуальные скобки в Python

    Каков наилучший способ преобразования объекта Zope DateTime в объект datetime Python?

    Пространства имен в C # vs import в Java и Python

    Проверка уникального вывода в Python

    Импорт дополнительного модуля

    Создание данных из уникальных пар значений путем фильтрации по нескольким столбцам

    Как анализировать позиционные аргументы с помощью знака минус (отрицательные числа) с помощью argparse

    Почему это соединение сокета разрешает только 1 отправку и получение?

    Можно ли загружать файлы с помощью Python SimpleHTTPServer или cgi?

    Умножение и добавление внутри слишком большого массива

    Python: последовательность Фибоначчи

    Определить переменные с теми же данными списка, но разными объектами, использующими python

    Как читать файлы .ARC от искателя Heritrix с помощью Python?

    Глобальная переменная и класс Python

    RSA шифрует / дешифрует сбой в моей собственной реализации в python

    Python - лучший язык программирования в мире.