【问题标题】:How to check if float pandas column contains only integer numbers?如何检查 float pandas 列是否仅包含整数?
【发布时间】:2018-08-21 08:04:54
【问题描述】:

我有一个数据框

df = pd.DataFrame(data=np.arange(10),columns=['v']).astype(float)

如何确保v 中的数字是整数? 我非常关心舍入/截断/浮点表示错误

【问题讨论】:

  • 整数测试将如何减轻对浮点错误的担忧?这些值是否来自整数,您是否担心它们已经改变?或者它们是计算的结果,其数学特性使得精确的结果是整数?
  • 这些值来自整数。然而,在处理过程中,它们经常被转换为 float64
  • 在处理浮点整数时唯一可能发生的错误是从一种格式转换为另一种格式时的舍入和溢出错误。将整数转换为浮点时,如果精度不足以准确表示该值,则会对其进行四舍五入。但是,由于浮点的性质,它将被四舍五入的值将是另一个整数。因此,测试数组中的所有值是否都是整数将不会提供有关是否发生任何舍入错误的信息。
  • 如果任务是确保从整数转换为浮点的值不会产生任何舍入误差,那么只要没有整数超过浮点格式的有效数字的精度就足够了。例如,IEEE 754 基本 64 位二进制具有 53 位有效位,因此任何整数的转换幅度高达 2^53 都不会产生任何舍入误差。

标签: python pandas floating-point precision


【解决方案1】:

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

【讨论】:

  • 与 is_integer 相比,allclose 的容差是多少?它们是对同一个函数的调用吗?
  • @ErroriSalvo 不,机制略有不同。使用allclose,容差非常小,无法解决浮点不准确的问题。使用is_integer,该函数实际上检查整数。机制略有不同,但最终结果是相同的。
  • allclose 无法确定数字是否为整数,除非容差设置为 0,此时它成为相等性测试。此外,正如我在对该问题的评论中所述,测试整数值并不能实现 OP 的实际目标。
  • @EricPostpischil 好的,我已将其更改为 array_equal。顺便说一句,这可能是一个 XY 问题,但知道如何使用 numpy/pandas 执行此操作仍然很有用,所以我还是继续回答了。我感谢批评(和反对票)。
  • df.v.apply: 不确定这是否有效,在df.v 之后它是一个numpy ndarray,它没有方法apply。你的意思是apply_along_axis
【解决方案2】:

这是一种更简单,可能更快的方法:

(df[col] % 1  == 0).all()

忽略空值:

(df[col].fillna(-9999) % 1  == 0).all()

【讨论】:

    【解决方案3】:

    如果要检查数据框中的多个浮点列,可以执行以下操作:

    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)
    

    【讨论】:

      【解决方案4】:

      为了完整起见,Pandas v1.0+ 提供了convert_dtypes() utility,它(在其他 3 种转换中)对仅包含整数的所有数据帧列(或系列)执行请求的操作。

      如果您只想将转换限制为单列,您可以执行以下操作:

      >>> df.dtypes          # inspect previous dtypes
      v                      float64
      
      >>> df["v"] = df["v"].convert_dtype()
      >>> df.dtypes          # inspect converted dtypes
      v                      Int64
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-17
        • 2020-09-08
        • 1970-01-01
        • 2021-12-24
        • 2020-07-21
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        相关资源
        最近更新 更多