Как сравнить два CSV-файла, используя DataFrames, и получить разные ячейки? Почему я получаю так много десятичных знаков в ячейках с плавающей точкой? [Дубликат]

1

У меня есть файл CSV, такой как этот (example.csv).

STRING_COL,INT_1,INT_2,FLOAT,INT_3
Hello,9,65151651,3234.54848,7832
This is a string,2,5484651,34.234,-999
Another,2,62189548,51.51658,-999
Test,2,2131514,5.2156,-999
Ham,9,6546548,2.15,-999
String,9,3216546,2.15468,-999

Каждая ячейка имеет различное число десятичных знаков. Они могут быть целыми или целыми (Int64, Int8,...). Тогда у меня также есть аналогичный CSV, но с некоторыми значениями. Я хочу проверить различия между обоими файлами.

Поэтому я написал код, подобный этому, для сравнения значений cell по ячейке:

import pandas as pd

df = pd.read_csv(
    'example.csv', delimiter=',', comment='#', skip_blank_lines=True,
    verbose=False, engine='python', dtype=str
)
df = df.apply(lambda x: pd.to_numeric(x, errors='ignore', downcast='integer'))

df_2 = pd.read_csv(
    'example_2.csv', delimiter=',', comment='#', skip_blank_lines=True,  # file with small changes
    verbose=False, engine='python', dtype=str
)
df_2 = df_2.apply(lambda x: pd.to_numeric(x, errors='ignore', downcast='integer'))

for i in list(df.index):
    for column in list(df.columns):
        old = df.loc[i, column]
        new = df_2.loc[i, column]
        if old != new:
            print('DIFFERENT VALUE >> INDEX: {} | OLD: {} | NEW: {}'.format(i, old, new))

Если вы запустите этот пример с небольшим CSV файлом, я уверен, что он будет работать хорошо. Но с огромным CSV файлом происходят какие-то странные вещи. Я не понимаю, почему иногда многие значения усекаются по отношению к этим:

1.6440000000000001  >> original value 1.644
7.7189999999999985  >> original value 7.7189

Затем, если я их сравниваю, он обнаруживает, что они разные, и это не так, потому что значение одно и то же. Что происходит? Есть ли способ исправить это? Есть ли лучший способ сравнить значения с DataFrames?

ПРИМЕЧАНИЕ. Возможно, я делаю что-то неправильно в другой части моего исходного кода, но я думаю, что написал самые важные и актуальные.

ПРИМЕЧАНИЕ 2: Я принимаю во внимание, что оператор != Не работает с NaN значениями. Я использую np.isnan для проверки этих изменений.

Обновление. Мне не нужно сравнивать и говорить "да, равно" и "нет, это не равно". Мне нужно получить значения, которые меняют ячейку по ячейке.

  • 1
    Вы сталкиваетесь с проблемами с плавающей запятой. Никогда не стоит сравнивать значения с плавающей запятой с == или != . Лучшим решением было бы определить абсолютный или относительный эпсилон (выберите тот, который подходит для вашей проблемы) и сделать abs(a - b) < epsilon для сравнения. Смотрите это, например, stackoverflow.com/questions/5595425/…
  • 0
    Мне не нужно подтверждать равенство. Мне нужно получить значения, которые меняются ячейка за ячейкой. Я обновил вопрос, чтобы уточнить его. Спасибо @sobek, чтобы указать на значение epsilon , я читаю об этом
Показать ещё 1 комментарий
Теги:
pandas
dataframe
python-3.x
floating-accuracy

1 ответ

0
Лучший ответ

Наконец, я нашел что-то подходящее для сравнения: np.isclose(). Я прочитал дублированный вопрос, который я нашел, и некоторые другие вопросы о значении epsilon: numpy.finfo(), epsilon

Эпсилон: Числа, которые отличаются меньше, чем машинный эпсилон, численно одинаковы

    abs(a - b) < epsilon
    absolute(a - b) <= (atol + rtol * absolute(b))      # np.isclose() method

Поэтому мне нужно сделать что-то вроде этого. Я должен проверить, что произойдет, если я сравниваю float32 и float64 или float16

eps64 = np.finfo(np.float64).eps
for col in df.columns:
    np.isclose(
        df[col],
        df_2[col],
        equal_nan=False,
        atol=0.0,
        rtol=eps64
    )

Но теперь я столкнулся с проблемой, что, если я хочу скопировать значение в другую переменную, 1.6440000000000001 неточное значение 1.6440000000000001. Что я делаю сейчас, чтобы исправить это, нужно float(1.6440000000000001) значение float >> float(1.6440000000000001)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню