【问题标题】:Why do I get an AttributeError when using pandas apply?为什么在使用 pandas apply 时会出现 AttributeError?
【发布时间】:2018-06-11 15:17:25
【问题描述】:

我应该如何根据条件将 NaN 值转换为分类值。尝试转换 Nan 值时出现错误。

category           gender     sub-category    title

health&beauty      NaN         makeup         lipbalm

health&beauty      women       makeup         lipstick

NaN                NaN         NaN            lipgloss

我的 DataFrame 看起来像这样。我将性别中的 NaN 值转换为分类值的函数看起来像

def impute_gender(cols):
    category=cols[0]
    sub_category=cols[2]
    gender=cols[1]
    title=cols[3]
    if title.str.contains('Lip') and gender.isnull==True:
        return 'women'
df[['category','gender','sub_category','title']].apply(impute_gender,axis=1)

如果我运行代码会出错

----> 7     if title.str.contains('Lip') and gender.isnull()==True:
      8         print(gender)
      9 

AttributeError: ("'str' object has no attribute 'str'", 'occurred at index category')

完整数据集-https://github.com/lakshmipriya04/py-sample

【问题讨论】:

  • 你认为title.str是什么?
  • isnull 不是一个接受数组的函数吗? The docs。我不确定gender.isnull==True 是否有意义,
  • 标题是熊猫系列。我正在该专栏中寻找 Lip
  • @LPR btw ,如果您喜欢其他答案,可以投票 :-)

标签: python pandas dataframe apply attributeerror


【解决方案1】:

这里有一些注意事项-

  1. 如果您只使用两列,那么在 4 列上调用 apply 是一种浪费
  2. 调用apply 既浪费又低效,因为它速度慢、占用大量内存,而且对您没有向量化的好处
  3. 在应用中,您正在处理标量,因此您不要像使用pd.Series 对象那样使用.str 访问器。 title.contains 就足够了。或者更 Python 的说法,"lip" in title
  4. gender.isnull 对解释器来说听起来完全错误,因为 gender 是一个标量,它没有 isnull 属性

选项 1
np.where

m = df.gender.isnull() & df.title.str.contains('lip')
df['gender'] = np.where(m, 'women', df.gender)

df
        category gender sub-category     title
0  health&beauty  women       makeup   lipbalm
1  health&beauty  women       makeup  lipstick
2            NaN  women          NaN  lipgloss

这不仅速度快,而且更简单。如果您担心区分大小写,可以让您的 contains 检查不区分大小写 -

m = df.gender.isnull() & df.title.str.contains('lip', flags=re.IGNORECASE)

选项 2
另一种选择是使用pd.Series.mask/pd.Series.where -

df['gender'] = df.gender.mask(m, 'women')

或者,

df['gender'] = df.gender.where(~m, 'women')

【解决方案2】:

或者简单地使用 loc 作为@COLDSPEED 答案的选项 3

cond = (df['gender'].isnull()) & (df['title'].str.contains('lip'))
df.loc[cond, 'gender'] = 'women'


    category        gender  sub-category    title
0   health&beauty   women   makeup          lipbalm
1   health&beauty   women   makeup          lipstick
2   NaN             women       NaN         lipgloss

【讨论】:

  • 谢谢您的回答。什么时候应该使用apply功能?以及为什么会出现属性错误
  • @LPR 你在和谁说话?我已经在回答中解决了您的问题。另外,至于什么时候用apply,答案是什么时候不能用。
【解决方案3】:

如果我们需要 NaN 值,fillna 可以是其中一种方法:-)

df.gender=df.gender.fillna(df.title.str.contains('lip').replace(True,'women'))
df
Out[63]: 
        category gender sub-category     title
0  health&beauty  women       makeup   lipbalm
1  health&beauty  women       makeup  lipstick
2            NaN  women          NaN  lipgloss

【讨论】:

  • 我看到你开箱即用地得到了这个。不错。
  • @cᴏʟᴅsᴘᴇᴇᴅ 啊哈,很难跳出框框思考:-)
  • @Wen,新年快乐。我回答并回去享受假期的最后一天,所以错过了消息:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 2019-12-02
  • 2012-01-31
  • 1970-01-01
相关资源
最近更新 更多