我有点卡住了,我有一个可以使用.apply()
的工作函数,但我似乎无法让它与.assign()
一起工作。我希望这与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)
不起作用
dataframe = dataframe.assign(gender = lambda ref: add_gender(ref))
TypeError:预期字符串或字节,如对象
这是因为.assign()
不提供轴参数吗?所以,也许函数没有寻找正确的东西?
在阅读了文档.assign
之后,您可以生成一个新列,所以我假设输出与.apply(axis=1)
相同
来自DataFrame.assign
:的文档
DataFrame.assign(**kwargs(
(…(
参数**kwargs:{str:callable或Series}的dict
列名是关键字如果这些值是可调用的,则在DataFrame上计算这些值并将其分配给新列。可调用程序不能更改输入DataFrame(尽管panda没有检查它(。如果值是不可调用的(例如,系列、标量或数组(,则只分配它们。
这意味着在中
dataframe = dataframe.assign(gender=lambda ref: add_gender(ref))
ref
代表调用DataFrame,即dataframe
,因此您将整个dataframe
传递给函数add_gender
。但是,根据定义方式,add_gender
希望传递一行(Series
对象(作为参数x
,而不是整个DataFrame。
if re.search("(womens?)", x.heading, re.IGNORECASE):
在assign
的情况下,x.heading
代表dataframe
(x
(的整列heading
,它是Series
对象。然而,re.search
仅适用于类似string
或bytes
的对象,因此会引发错误。而在apply
的情况下,x.heading
对应于dataframe
的每个单独行x
的字段heading
,其为string
值。
要解决此问题,只需将assign
与apply
结合使用即可。请注意,lambda ref: add_gender(ref)
中的lambda是多余的,它相当于只传递add_gender
。
dataframe = dataframe.assign(gender=lambda df: df.apply(add_gender, axis=1))
建议使用Series.str.extract
和Series.fillna
来定义add_gender
。
def add_gender(df):
pat = r'b(men|women)s?b'
return df['heading'].str.extract(pat, flags=re.IGNORECASE).fillna('unisex')
关于正则表达式模式'b(men|women)s?b'
:
b
匹配单词边界(men|women)
与men
或women
完全匹配并捕获组s?
与s
匹配零次或一次
Series.str.extract
提取列heading
的每个字符串值的捕获组。不匹配项设置为NaN。然后,Series.fillna
将NaN替换为"unisex"。
在这种情况下,add_gender
期望通过整个DataFrame。有了这个定义,你可以简单地进行
dataframe = dataframe.assign(gender=add_gender)
设置:
import pandas as pd
import re
data = {'heading': ['some men', 'some men', 'some women', 'x mens', 'y womens', 'other', 'blahmenblah', 'blahwomenblah']}
dataframe = pd.DataFrame(data=data)
def add_gender(df):
pat = r'b(men|women)s?b'
return df['heading'].str.extract(pat, flags=re.IGNORECASE).fillna('unisex')
输出:
>>> dataframe
heading
0 some men
1 some men
2 some women
3 x mens
4 y womens
5 other
6 blahmenblah
7 blahwomenblah
>>> dataframe = dataframe.assign(gender = add_gender)
>>> dataframe
heading gender
0 some men men
1 some men men
2 some women women
3 x mens men
4 y womens women
5 other unisex
6 blahmenblah unisex
7 blahwomenblah unisex