如何重写 Lambda 函数(通过 pandas .apply() 方法)以击败著名的"ValueError: The truth value of a Series is ambiguous."?



编辑:此笔记本中发布的解决方案。特别感谢Étienne Célèry和ifly6


我正试图找出如何战胜令人恐惧的错误:

ValueError:序列的真值不明确。使用a.empty、a.bool((、a.item((、.any((或.all((。

d = {
'nickname': ['bobg89', 'coolkid34','livelaughlove38'], 
'state': ['NY', 'CA','TN'],
'score': [100, 200,300]
}
df = pd.DataFrame(data=d)
df_2 = df.copy() #for use in the second non-lambda part
print(df)

这个输出:

nickname state  score
0           bobg89    NY    100
1        coolkid34    CA    200
2  livelaughlove38    TN    300

如果他们来自纽约,那么我们的目标是将比分加50。

def add_some_love(state_value,score_value,name):
if state_value == name:
return score_value + 50
else:
return score_value

然后我们可以将该函数与lambda函数一起应用。

df['love_added'] = df.apply(lambda x: add_some_love(x.state, x.score, 'NY'), axis=1)
print(df)

这让我们:

nickname state  score  love_added
0           bobg89    NY    100         150
1        coolkid34    CA    200         200
2  livelaughlove38    TN    300         300

这是我尝试在没有lambda的情况下编写它的地方,这就是我得到错误的地方。

@MSeifert在这里的回答似乎解释了为什么会发生这种情况(函数查看的是整列,而不是列中的一行,但我也认为将axis = 1传递到.apply()方法中会按行应用函数,并解决问题(。

所以我这样做:

df2['love_added'] = df2.apply(add_some_love(df2.state, df2.score, 'NY'), axis=1)
print(df2)

然后你会得到错误:

ValueError:序列的真值不明确。使用a.empty、a.bool((、a.item((、.any((或.all((。

所以我尝试了这些解决方案,但我似乎不知道如何重写add_some_love()函数,以便在没有lambda函数的情况下正常运行。

有人有什么建议吗?

非常感谢您的时间和考虑。

您可以使用np.where:

df['score'] = np.where(df['state'] == 'NY', df['score'] + 50, df['score'])

这将产生与您应用的函数相同的结果,同时也更具性能。


不使用lambda函数的问题是,实际上并没有将行传递给函数。你实际传递的是整个列df['score'],因为这就是你告诉计算机要做的

你的功能中发生了什么,计算机在问:

# if state_value == name ...
if df['score'] == 'NY':
...

这自然会引起错误,因为df['score'] == 'NY'是一系列布尔变量,而不是if语句所需的单个布尔变量。

add_some_love函数需要一个字符串输入才能执行比较if state_value == name。在DataFrame上应用lambda函数时,可以将每个单元格传递给该函数,而不是整个Series。

如果没有lambda函数,就无法使用精确的add_some_love函数。

如果您仍然想使用apply(),请尝试以下功能:

def add_some_love(row, name):
if row.state == name:
row.score = row.score + 50
return row
df_2 = df_2.apply(add_some_love, axis=1, args=('NY',))

然而,这应该是最快、最有效的:

FILTER = df_2['state'] == 'NY'
df_2.loc[FILTER, 'score'] = df_2.loc[FILTER, 'score'] + 50

相关内容

最新更新