У меня есть файл 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
для проверки этих изменений.
Обновление. Мне не нужно сравнивать и говорить "да, равно" и "нет, это не равно". Мне нужно получить значения, которые меняют ячейку по ячейке.
Наконец, я нашел что-то подходящее для сравнения: 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)
==
или!=
. Лучшим решением было бы определить абсолютный или относительный эпсилон (выберите тот, который подходит для вашей проблемы) и сделатьabs(a - b) < epsilon
для сравнения. Смотрите это, например, stackoverflow.com/questions/5595425/…epsilon
, я читаю об этом