使用自定义函数按组汇总熊猫数据帧会导致错误的输出



>我有一个熊猫数据帧,我想使用解析为布尔值的自定义函数按组进行汇总。

请考虑以下数据。df描述了4个人,每个人喜欢的水果。

import numpy as np
import pandas as pd
df = pd.DataFrame({
"name": ["danny", "danny", "danny", "monica", "monica", "monica", "fred", "fred", "sam", "sam"],
"fruit": ["apricot", "apple", "orange", "apricot", "banana", "watermelon", "apple", "apricot", "apricot", "peach"]
})
print(df)
##      name       fruit
## 0   danny     apricot
## 1   danny       apple
## 2   danny      orange
## 3  monica     apricot
## 4  monica      banana
## 5  monica  watermelon
## 6    fred       apple
## 7    fred    apricot
## 8     sam    apricot
## 9     sam       peach

我想总结一下这张表,找到既喜欢apricot喜欢apple的人。换句话说,我想要的输出是下表

# desired output
##      name     fruit
## 0   danny     True
## 1  monica     False
## 2    fred     True
## 3     sam     False

我的尝试

我首先定义了一个在目标列表中搜索字符串存在的函数:

def is_needle_in_haystack(needle, haystack):
return all(x in haystack for x in needle)

is_needle_in_haystack()工作的示例:

is_needle_in_haystack(["zebra", "lion"], ["whale", "lion", "dog"])
# False
is_needle_in_haystack(["rabbit", "cat"], ["hamster", "cat", "monkey", "rabbit"])
# True

现在我在按namedf进行分组时使用了is_needle_in_haystack()

target_fruits = ["apricot", "apple"]
df.groupby(df["name"]).agg({"fruit": lambda x: is_needle_in_haystack(target_fruits, x)})

那为什么我得到以下输出,这显然不符合预期?

##    fruit
## name         
## danny   False
## fred    False
## monica  False
## sam     False

我在代码中做错了什么?

问题是haystack是一个系列,当在.agg中调用时,更改为:

def is_needle_in_haystack(needle, haystack):
return all(x in set(haystack) for x in needle)

target_fruits = ["apricot", "apple"]
res = df.groupby(df["name"]).agg({"fruit": lambda x: is_needle_in_haystack(target_fruits, x)})
print(res)

输出

fruit
name
danny    True
fred     True
monica  False
sam     False

序列的in运算符返回False,例如:

"hamster" in pd.Series(["hamster", "cat", "monkey", "rabbit"])
# False

我们可以使用一些集合逻辑来完成相同的任务:

target_fruits = {"apricot", "apple"}
res = (df.groupby('name', as_index=False)#['fruit'] # Add if you have more columns.
.agg(lambda x: target_fruits.issubset(x)))
# target_fruits.issubset(x) = Are all values from target_fruits present in the Series?

输出:

name  fruit
0   danny   True
1    fred   True
2  monica  False
3     sam  False

您也可以将target_fruits设为Series并使用Series.isin()

target_fruits = pd.Series(["apricot", "apple"])
dfr = df.groupby('name').apply(lambda x: target_fruits.isin(x['fruit']).all()) 
.reset_index().rename(columns={0:'fruit'})
print(dfr)

结果

name  fruit
0   danny   True
1    fred   True
2  monica  False
3     sam  False

最新更新