【问题标题】:Error: float object has no attribute notnull错误:浮动对象没有属性 notnull
【发布时间】:2017-12-06 06:08:09
【问题描述】:

我有一个数据框:

  a     b     c
0 nan   Y     nan
1  23   N      3
2 nan   N      2
3  44   Y     nan

我希望有这个输出:

  a     b     c      d
0 nan   Y     nan   nan
1  23   N      3     96
2 nan   N      2    nan
3  44   Y     nan    44

我希望有一个条件 当 a 列为空时,d 将为空,否则如果 b 列为 N 且 c 列不为空,则 d 列等于 a 列 * c 列 else 列d 等于 a 列

我已经完成了这段代码,但我得到了错误:

def f4(row):
    if row['a']==np.nan:
       return np.nan
    elif row['b']=="N" & row(row['c'].notnull()):
       return row['a']*row['c']
    else:
       return row['a']

 DF['P1']=DF.apply(f4,axis=1)

谁能帮我指出我的错误在哪里?我已经参考了这个并尝试了这个,但也得到了错误Creating a new column based on if-elif-else condition

【问题讨论】:

  • row['c'] 给你一个
  • 所以有什么办法可以克服这个问题,因为我的 c 行应该包含 nan(null value)

标签: python pandas


【解决方案1】:

你不需要apply,使用np.where

df['d'] = np.where(df.a.isnull(),
         np.nan,
         np.where((df.b == "N")&(~df.c.isnull()),
                  df.a*df.c,
                  df.a))

输出:

      a  b    c     d
0   NaN  Y  NaN   NaN
1  23.0  N  3.0  69.0
2   NaN  N  2.0   NaN
3  44.0  Y  NaN  44.0

【讨论】:

    【解决方案2】:

    你可以试试

    df['d'] = np.where((df.b == 'N') & (pd.notnull(df.c)), df.a*df.c, np.where(pd.notnull(df.a), df.a, np.nan))
    
    
        a       b   c      d
    0   NaN     Y   NaN    NaN
    1   23.0    N   3.0    69.0
    2   NaN     N   2.0    NaN
    3   44.0    Y   NaN    44.0
    

    查看documentation for pandas notnull,在您当前的代码中,您只需将 series.notnull 更改为 pd.notnull(series) 即可使其正常工作。虽然 np.where 应该更高效

    def f4(row):
        if row['a']==np.nan:
            return np.nan
        elif (row['b']=="N") & (pd.notnull(row.c)):
            return row['a']*row['c']
        else:
            return row['a']
    df['d']=df.apply(f4,axis=1)
    

    【讨论】:

      【解决方案3】:

      由于您只想传播 Nans,因此将列相乘会为您解决这个问题:

      >>> df = pd.read_clipboard()
      >>> df
            a  b    c
      0   NaN  Y  NaN
      1  23.0  N  3.0
      2   NaN  N  2.0
      3  44.0  Y  NaN
      >>> df.a * df.c
      0     NaN
      1    69.0
      2     NaN
      3     NaN
      dtype: float64
      >>>
      

      如果你想在一个条件下这样做,你可以在这里使用np.where而不是.apply。您只需要以下内容:

      >>> df
            a  b    c
      0   NaN  Y  NaN
      1  23.0  N  3.0
      2   NaN  N  2.0
      3  44.0  Y  NaN
      >>> np.where(df.b == 'N', df.a*df.c, df.a)
      array([ nan,  69.,  nan,  44.])
      

      这是涉及Nan 的大多数操作的默认行为。因此,您可以简单地分配上述结果:

      >>> df['d'] = np.where(df.b == 'N', df.a*df.c, df.a)
      >>> df
            a  b    c     d
      0   NaN  Y  NaN   NaN
      1  23.0  N  3.0  69.0
      2   NaN  N  2.0   NaN
      3  44.0  Y  NaN  44.0
      >>>
      

      只是详细说明一下:

      np.where(df.b == 'N', df.a*df.c, df.a)
      

      在做,你可以把它想象成“其中df.b == 'N',给我df.a * df.c的结果,否则,给我df.a

      >>> np.where(df.b == 'N', df.a*df.c, df.a)
      array([ nan,  69.,  nan,  44.])
      

      另请注意,如果您的数据框有点不同:

      >>> df
            a  b    c
      0   NaN  Y  NaN
      1  23.0  Y  3.0
      2   NaN  N  2.0
      3  44.0  Y  NaN
      >>> df.loc[0,'a'] = 99
      >>> df.loc[0, 'b']= 'N'
      >>> df
            a  b    c
      0  99.0  N  NaN
      1  23.0  N  3.0
      2   NaN  N  2.0
      3  44.0  Y  NaN
      

      那么下面的就不等价了:

      >>> np.where(df.b == 'N', df.a*df.c, df.a)
      array([ nan,  69.,  nan,  44.])
      >>> np.where((df.b == 'N') & (~df.c.isnull()), df.a*df.c, df.a)
      array([ 99.,  69.,  nan,  44.])
      

      所以你可能想使用稍微详细一点的:

      >>> df['d'] = np.where((df.b == 'N') & (~df.c.isnull()), df.a*df.c, df.a)
      >>> df
            a  b    c     d
      0  99.0  N  NaN  99.0
      1  23.0  N  3.0  69.0
      2   NaN  N  2.0   NaN
      3  44.0  Y  NaN  44.0
      >>>
      

      【讨论】:

      • 这样简单多了:) +1
      【解决方案4】:

      使用

      pd.isnull(df['Description'][i])
      

      pd.isna(df['Description'][i])
      

      【讨论】:

      • 虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
      • 谢谢,这太短了,这是一个补充:对于Series和DataFrame,返回与布尔值的ndarray相同的类型,包含布尔值。所以 pd.notnull(df) 和 pd.notna(df) 结果是一样的。
      • 很好的解决方案,当我想在 for 循环中跳过带有 NaN 的行时工作正常:for i, row in df.iterrows()if pd.notnull(df['Column'][i]):
      【解决方案5】:

      使用pd.isnull() 代替== np.nan

      例子:

      >>> x1 = np.nan
      >>> x1 == np.nan
      False
      >>> pd.isnull(x1)
      True
      >>> pd.isna(x1)
      True
      

      看这个:

      The difference between comparison to np.nan and isnull()

      【讨论】:

        猜你喜欢
        • 2015-12-27
        • 1970-01-01
        • 1970-01-01
        • 2019-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-21
        相关资源
        最近更新 更多