У меня есть датафрейм
df = pd.DataFrame(data=np.arange(10),columns=['v']).astype(float)
Как сделать так, чтобы числа в v были целыми числами?
Меня очень беспокоят ошибки округления / усечения / представления с плавающей запятой
эти значения берутся из целых чисел. Однако во время обработки они часто приводятся к типу float64.
Единственные ошибки, которые могут возникнуть при обработке целых чисел с плавающей запятой, - это ошибки округления и переполнения при преобразовании из одного формата в другой. При преобразовании целого числа в число с плавающей запятой, если точность не достаточна для точного представления значения, оно будет округлено. Однако значение, до которого оно будет округлено, будет другим целым числом из-за природы чисел с плавающей запятой. Следовательно, проверка того, являются ли все значения в массиве целыми числами, не предоставит информации о том, произошли ли какие-либо ошибки округления.
Если задача состоит в том, чтобы гарантировать, что значения, преобразованные из целых чисел в числа с плавающей запятой, не вызывают ошибок округления, то достаточно, если ни одно целое число не превышает точность мантиссы формата с плавающей запятой. Например, базовый 64-битный двоичный код IEEE 754 имеет 53-битное значение, поэтому преобразование любых целых чисел до 2 ^ 53 по величине не приведет к ошибке округления.






astype(int)Предварительно преобразуйте вашу колонку в int и протестируйте с np.array_equal:
np.array_equal(df.v, df.v.astype(int))
True
float.is_integerВы можете использовать эту функцию Python вместе с apply:
df.v.apply(float.is_integer).all()
True
Или, используя Python all в понимании генератора, для экономии места:
all(x.is_integer() for x in df.v)
True
Каков допуск allclose по сравнению с is_integer? Являются ли они вызовом одной и той же функции?
@ErroriSalvo Нет, механизмы немного другие. Для allclose допуск очень мал, чтобы учесть неточности с плавающей запятой. В is_integer функция фактически проверяет целые числа. Механизм немного отличается, но конечный результат тот же.
allclose не может определить, является ли число целым числом, если допуск не установлен на 0, после чего он становится проверкой на равенство. Кроме того, как указано в моем комментарии к вопросу, тестирование целочисленных значений не достигает фактической цели OP.
@EricPostpischil, хорошо, я изменил это на array_equal. Кстати, это может быть проблема XY, но все же полезно знать, как это сделать с помощью numpy / pandas, поэтому я все равно ответил. Я ценю критику (и отрицательные голоса).
df.v.apply: не уверен, работает ли это, после df.v это numpy ndarray, у которого нет метода apply. Вы имеете в виду apply_along_axis?
Если вы хотите проверить несколько столбцов с плавающей запятой в вашем фрейме данных, вы можете сделать следующее:
col_should_be_int = df.select_dtypes(include=['float']).applymap(float.is_integer).all()
float_to_int_cols = col_should_be_int[col_should_be_int].index
df.loc[:, float_to_int_cols] = df.loc[:, float_to_int_cols].astype(int)
Имейте в виду, что столбец с плавающей запятой, содержащий все целые числа, не будет выбран, если он имеет значения np.NaN. Чтобы преобразовать столбцы с плавающей запятой с отсутствующими значениями в целые числа, вам необходимо заполнить / удалить отсутствующие значения, например, с помощью медианного вменения:
float_cols = df.select_dtypes(include=['float'])
float_cols = float_cols.fillna(float_cols.median().round()) # median imputation
col_should_be_int = float_cols.applymap(float.is_integer).all()
float_to_int_cols = col_should_be_int[col_should_be_int].index
df.loc[:, float_to_int_cols] = float_cols[float_to_int_cols].astype(int)
Вот более простой и, возможно, более быстрый подход:
(df[col] % 1 == 0).all()
Чтобы игнорировать нули:
(df[col].fillna(-9999) % 1 == 0).all()
Для полноты, Панды v1.0 + предлагает Утилита convert_dtypes(), который (среди 3 других преобразований) выполняет запрошенную операцию для всех столбцов (или серий) фрейма данных, содержащих только целые числа.
Если вы хотите ограничить преобразование только одним столбцом, вы можете сделать следующее:
>>> df.dtypes # inspect previous dtypes
v float64
>>> df["v"] = df["v"].convert_dtype()
>>> df.dtypes # inspect converted dtypes
v Int64
Как тестирование целых чисел снимет опасения по поводу ошибок с плавающей запятой? Значения берутся из целых чисел, и вы обеспокоены тем, что они изменились? Или это результаты вычислений, математические свойства которых таковы, что точными результатами будут целые числа?