使用 apply 函数可以工作,但是使用 .assign() 相同的函数却不能?

dim*_*ies 8 python dataframe pandas

我有点卡住了,我有一个可以使用的工作函数.apply(),但是,我似乎无法让它与 一起使用.assign()。我希望它能够与分配一起使用,这样我就可以将多个转换链接在一起。

有人能指出我解决问题的正确方向吗?

这有效

data = {'heading': ['some men', 'some men', 'some women']}

dataframe = pd.DataFrame(data=data)

def add_gender(x):
    if re.search("(womens?)", x.heading, re.IGNORECASE):
        return 'women'
    elif re.search("(mens?)", x.heading, re.IGNORECASE):
        return 'men'
    else:
        return 'unisex'

dataframe['g'] = dataframe.apply(lambda ref: add_gender(ref), axis=1)
Run Code Online (Sandbox Code Playgroud)

这不起作用

dataframe = dataframe.assign(gender = lambda ref: add_gender(ref))
Run Code Online (Sandbox Code Playgroud)

类型错误:预期的字符串或类似字节的对象

这是因为.assign()没有提供轴参数吗?那么也许该函数没有在寻找正确的东西?

阅读文档后,.assign您可以生成一个新列,因此我假设输出与.apply(axis=1)

Rod*_*alm 7

来自以下文档DataFrame.assign

\n
\n

DataFrame.分配(**kwargs)

\n

(...)

\n

参数 **kwargs :{str:可调用或系列}的字典

\n

列名是关键字。如果这些值是可调用的,则会在 DataFrame 上计算它们并分配给新列。可调用对象不得更改输入 DataFrame(尽管 pandas 不会检查它\xe2\x80\x99)。如果值不可调用(例如系列、标量或数组),则仅对它们进行赋值。

\n
\n

这意味着在

\n
\n
dataframe = dataframe.assign(gender=lambda ref: add_gender(ref))\n
Run Code Online (Sandbox Code Playgroud)\n
\n

ref代表调用 DataFrame,即dataframe,因此您将整个传递dataframe给函数add_gender。但是,根据它的定义方式,add_gender期望将单行(Series对象)作为参数传递x,而不是整个 DataFrame。

\n
\n
if re.search("(womens?)", x.heading, re.IGNORECASE):\n
Run Code Online (Sandbox Code Playgroud)\n
\n

在 的情况下assign,代表( )的x.heading整列,它是一个对象。但是,仅适用于或类似的对象,因此会引发错误。而在 的情况下,对应于的每一行的字段,它们是值。headingdataframexSeriesre.searchstringbytesapplyx.headingheadingxdataframestring

\n

要解决这个问题,只需使用assignwith apply。请注意, in 中的 lambdalambda ref: add_gender(ref)是多余的,它相当于只是传递add_gender

\n
dataframe = dataframe.assign(gender=lambda df: df.apply(add_gender, axis=1))\n
Run Code Online (Sandbox Code Playgroud)\n
\n

作为建议,这里有一种更简洁的定义add_gender、使用Series.str.extract和 的方法Series.fillna

\n
def add_gender(df):\n    pat = r\'\\b(men|women)s?\\b\'\n    return df[\'heading\'].str.extract(pat, flags=re.IGNORECASE).fillna(\'unisex\')\n
Run Code Online (Sandbox Code Playgroud)\n

关于正则表达式模式\'\\b(men|women)s?\\b\'

\n
    \n
  • \\b匹配单词边界
  • \n
  • (men|women)匹配menwomen字面意义并捕获该组
  • \n
  • s?火柴s零次或一次
  • \n
\n

Series.str.extract提取列的每个字符串值的捕获组heading。不匹配项设置为 NaN。然后,Series.fillna将 NaN 替换为“unisex”。

\n

在这种情况下,add_gender期望传递整个 DataFrame。有了这个定义,你可以简单地做

\n
dataframe = dataframe.assign(gender=add_gender)\n
Run Code Online (Sandbox Code Playgroud)\n

设置:

\n
import pandas as pd\nimport re\n\ndata = {\'heading\': [\'some men\', \'some men\', \'some women\', \'x mens\', \'y womens\',  \'other\', \'blahmenblah\', \'blahwomenblah\']}\ndataframe = pd.DataFrame(data=data)\n\ndef add_gender(df):\n    pat = r\'\\b(men|women)s?\\b\'\n    return df[\'heading\'].str.extract(pat, flags=re.IGNORECASE).fillna(\'unisex\')\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
>>> dataframe \n\n         heading\n0       some men\n1       some men\n2     some women\n3         x mens\n4       y womens\n5          other\n6    blahmenblah\n7  blahwomenblah\n\n>>> dataframe = dataframe.assign(gender = add_gender)\n>>> dataframe \n\n         heading  gender\n0       some men     men\n1       some men     men\n2     some women   women\n3         x mens     men\n4       y womens   women\n5          other  unisex\n6    blahmenblah  unisex\n7  blahwomenblah  unisex\n
Run Code Online (Sandbox Code Playgroud)\n