我很难使用df.apply将变量传递给参数。我有一个函数,它拆分一个字符串,然后计算有多少子字符串匹配列表中的项目。我将其应用到pandas数据框,使用apply传递要分割的字符串并查找要匹配的列表。如果直接应用虽然可以成功,但如果我尝试在for循环中传递此信息失败,则该方法似乎有效矮人不接受该变量。
这是示例函数
def classification_counter(original, class_lists):
...: count=0
...: for y in original.split():
...: if y in class_lists:
...: count= count+1
...: return count
例如,这是我的列表,其中包含稍后将要查找的关键字:
bikes = ['raleigh', 'trek', 'cannondale']
cars = ['ford', 'bmw', 'vw']
我将遍历的列表:
class_set = ['cars', 'bikes']
这是我的数据框:
In [116]: df
Out[116]:
bikes cars texts
0 0 0 I like to drive my bmw
1 0 0 I like to ride my cannondale
2 0 0 I keep my trek on a rack on my vw
0 0 0 my wifes car is a vw mine is a bmw
如果我将Apply应用于一列,它将按预期工作:
In [119]: df['cars']=df['texts'].apply(classification_counter, class_lists=cars)
In [121]: df['bikes']=df['texts'].apply(classification_counter, class_lists=bikes)
In [122]: df
Out[122]:
bikes cars texts
0 0 1 I like to drive my bmw
1 1 0 I like to ride my cannondale
2 1 1 I keep my trek on a rack on my vw
0 0 2 my wifes car is a vw mine is a bmw
但是,如果我尝试遍历列表,则会中断:
In [117]: for x in class_set:
...: df[x]=df['texts'].apply(classification_counter, class_lists=x)
...:
In [118]: df
Out[118]:
bikes cars texts
0 0 0 I like to drive my bmw
1 0 0 I like to ride my cannondale
2 0 1 I keep my trek on a rack on my vw
0 0 3 my wifes car is a vw mine is a bmw
我是否缺少有关将变量传递给关键字参数的正确方法的某些信息?
答案 0 :(得分:3)
您不需要为此编写自己的“复杂”函数。为此,请使用熊猫Series.str.count
:
for col in class_set:
df[col] = df.texts.str.count('|'.join(eval(col)))
print(df)
bikes cars texts
0 0 1 I like to drive my bmw
1 1 0 I like to ride my cannondale
2 1 1 I keep my trek on a rack on my vw
3 0 2 my wifes car is a vw mine is a bmw
要使自己的代码正常工作,请使用以下命令:
for x in class_set:
df[x]=df['texts'].apply(classification_counter, class_lists=eval(x))
但是在熊猫中,您总是想使用向量化解决方案,因为与自己定义的函数和for循环相比,它可以大大提高代码的速度。
编辑以获取解释
我们使用'|'.join
来创建列表的字符串表示形式:
bikes = ['raleigh', 'trek', 'cannondale']
print('|'.join(bikes))
raleigh|trek|cannondale
我们使用eval
,因为您不能将变量作为字符串调用,因此我们必须使用eval,因为您的class_set
列出了字符串后缀。但是我们要调用列表bikes
和car
而不是字符串。
text = 'hello'
x = 'text'
print(eval(x))
hello
答案 1 :(得分:1)
如果这是您需要的,则无需构建自己的函数,请查看get_dummies
bikesdict=dict.fromkeys(bikes,'bikes')
carsdict=dict.fromkeys(cars,'cars')
d={}
d.update(bikesdict)
d.update(carsdict)
df.texts.str.get_dummies(' ').groupby(by=d,axis=1).sum()
Out[344]:
bikes cars
0 0 1
1 1 0
2 1 1
3 0 2
答案 2 :(得分:1)
我认为您的问题是您的for循环中的x
是一个字符串。当您确实分别申请每列时,您将列表cars
和bikes
作为关键字class_lists
进行了传递。但是,在for循环中,您将字符串'cars'
和'bikes'
作为关键字class_lists
传递。
如果您制作了一个类的字典,它将起作用。也就是说,
class_dict = {'cars':['ford', 'bmw', 'vw'],
'bikes':['raleigh', 'trek', 'cannondale']}
,并将for循环更改为:
>>> for k, v in class_dict.items():
... df[k]=df['texts'].apply(classification_counter, class_lists=v)
>>> df
bikes cars texts
0 0 1 I like to drive my bmw
1 1 0 I like to ride my cannondale
2 1 1 I keep my trek on a rack on my vw
3 0 2 my wifes car is a vw mine is a bmw