>我有一个熊猫数据帧,我想使用解析为布尔值的自定义函数按组进行汇总。
请考虑以下数据。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
现在我在按name
对df
进行分组时使用了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