【问题标题】:Comparing floats in a pandas column比较熊猫列中的浮点数
【发布时间】:2016-02-11 02:54:27
【问题描述】:

我有以下数据框:

       actual_credit    min_required_credit
   0   0.3              0.4
   1   0.5              0.2
   2   0.4              0.4
   3   0.2              0.3

我需要添加一列来指示实际信用 >= min_required_credit 的位置。结果是:

       actual_credit    min_required_credit   result
   0   0.3              0.4                   False
   1   0.5              0.2                   True
   2   0.4              0.4                   True
   3   0.1              0.3                   False

我正在做以下事情:

df['result'] = abs(df['actual_credit']) >= abs(df['min_required_credit'])

但是,第 3 行(0.4 和 0.4)不断导致 False。在各个地方研究了这个问题之后,包括:What is the best way to compare floats for almost-equality in Python?我仍然无法让它工作。每当两列具有相同的值时,结果为 False,这是不正确的。

我正在使用 python 3.3

【问题讨论】:

    标签: python pandas floating-point floating-point-comparison inexact-arithmetic


    【解决方案1】:

    由于浮点比较不精确,您可以 ornp.isclose 进行比较,isclose 采用相对和绝对容差参数,因此以下应该可以工作:

    df['result'] = df['actual_credit'].ge(df['min_required_credit']) | np.isclose(df['actual_credit'], df['min_required_credit'])
    

    【讨论】:

      【解决方案2】:

      @EdChum 的回答效果很好,但使用pandas.DataFrame.round 函数是另一个干净的选项,在不使用numpy 的情况下效果很好。

      df = pd.DataFrame(  # adding a small difference at the thousandths place to reproduce the issue
          data=[[0.3, 0.4], [0.5, 0.2], [0.400, 0.401], [0.2, 0.3]],
          columns=['actual_credit', 'min_required_credit'])
      
      df['result'] = df['actual_credit'].round(1) >= df['min_required_credit'].round(1)
      print(df)
      
         actual_credit  min_required_credit  result
      0            0.3                0.400   False
      1            0.5                0.200    True
      2            0.4                0.401    True
      3            0.2                0.300   False
      

      您可以考虑使用round() 来更永久地编辑您的数据框,具体取决于您是否需要该精度。在这个例子中,似乎 OP 暗示这可能只是噪音,只是造成混乱。

      df = pd.DataFrame(  # adding a small difference at the thousandths place to reproduce the issue
          data=[[0.3, 0.4], [0.5, 0.2], [0.400, 0.401], [0.2, 0.3]],
          columns=['actual_credit', 'min_required_credit'])
      df = df.round(1)
      df['result'] = df['actual_credit'] >= df['min_required_credit']
      print(df)
      
         actual_credit  min_required_credit  result
      0            0.3                  0.4   False
      1            0.5                  0.2    True
      2            0.4                  0.4    True
      3            0.2                  0.3   False
      

      【讨论】:

      • 是的,但是当您使用 .round(2) 并以 0.005001 和 0.0049999 为例时,应谨慎行事。之后你会得到更大的差异......
      【解决方案3】:

      一般numpy Comparison 函数与pd.Series 配合得很好,并允许逐元素比较: iscloseallclosegreatergreater_equallessless_equal

      在你的情况下,greater_equal 会这样做:

      df['result'] = np.greater_equal(df['actual_credit'], df['min_required_credit'])
      

      或者,按照建议,使用pandas.ge(或者legt等):

      df['result'] = df['actual_credit'].ge(df['min_required_credit'])
      

      oring 和 ge(如上所述)的风险是,例如比较 3.9999999999994.0 可能会返回 True,这不一定是您想要的。

      【讨论】:

        【解决方案4】:

        使用pandas.DataFrame.abs() 代替内置的abs()

        df['result'] = df['actual_credit'].abs() >= df['min_required_credit'].abs()
        

        【讨论】:

        • 感谢您的建议,不幸的是这对我不起作用。我认为我的数据在内存中的表示可能与我在屏幕上看到的不同,因此结果很奇怪。 EdChum 的建议有效。谢谢。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-10
        • 1970-01-01
        相关资源
        最近更新 更多