How to Re-Write Lambda Function (via Pandas .apply() method) to Beat Famous "ValueError: The truth value of a Series is ambiguous."?
How to Re-Write Lambda Function (via Pandas .apply() method) to Beat Famous "ValueError: The truth value of a Series is ambiguous."?
编辑:this notebook 中发布的解决方案。特别感谢 Étienne Célèry 和 ifly6!
我正在想办法克服可怕的错误:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.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: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
所以我尝试了这些解决方案,但我似乎无法弄清楚如何重写 add_some_love()
函数,以便在没有 lambda 函数的情况下它可以 运行 正确。
有人有什么建议吗?
非常感谢您的时间和考虑。
您可以改为使用 np.where
:
df['score'] = np.where(df['state'] == 'NY', df['score'] + 50, df['score'])
这将产生与您应用的函数相同的结果,同时性能更高。
lambda 函数的 non-use 存在的问题是您实际上并未将行传递给您的函数。您实际传递的是整个列 df['score']
,因为这是您告诉计算机要做的。
你的函数中发生的事情是计算机询问:
# if state_value == name ...
if df['score'] == 'NY':
...
这自然会引发您的错误,因为 df['score'] == 'NY'
是一系列布尔变量,而不是 单个 布尔变量,这是 if
所需要的声明。
您的 add_some_love
函数需要字符串输入才能执行比较 if state_value == name
。当您在 DataFrame 上应用 lambda
函数时,您可以将 每个单元格 传递给该函数,而不是整个系列。
如果没有 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
编辑:this notebook 中发布的解决方案。特别感谢 Étienne Célèry 和 ifly6!
我正在想办法克服可怕的错误:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.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: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
所以我尝试了这些解决方案,但我似乎无法弄清楚如何重写 add_some_love()
函数,以便在没有 lambda 函数的情况下它可以 运行 正确。
有人有什么建议吗?
非常感谢您的时间和考虑。
您可以改为使用 np.where
:
df['score'] = np.where(df['state'] == 'NY', df['score'] + 50, df['score'])
这将产生与您应用的函数相同的结果,同时性能更高。
lambda 函数的 non-use 存在的问题是您实际上并未将行传递给您的函数。您实际传递的是整个列 df['score']
,因为这是您告诉计算机要做的。
你的函数中发生的事情是计算机询问:
# if state_value == name ...
if df['score'] == 'NY':
...
这自然会引发您的错误,因为 df['score'] == 'NY'
是一系列布尔变量,而不是 单个 布尔变量,这是 if
所需要的声明。
您的 add_some_love
函数需要字符串输入才能执行比较 if state_value == name
。当您在 DataFrame 上应用 lambda
函数时,您可以将 每个单元格 传递给该函数,而不是整个系列。
如果没有 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