使用
我有一个DataFrame,让我们假设如下:
df=pd.DataFrame({'person':['Sebastian','Sebastian','Sebastian', 'Maria', 'Maria', 'Maria', 'Achim','Achim','Achim'],'item':['house','garden','sink','sink','gold','house','stone','gold','wood']})
现在我想获得所有不拥有某种物品(例如黄金)的人的列表。我已经找到了实现它的方法,但我认为还有更好的方法。我就是这样做的:
allPersons=df['person'].unique()
personWithGold=df[df['item']=='gold']['person'].unique()
personWithoutGold=allPersons[~np.isin(allPersons,personWithGold)]
对如何改进代码有什么建议吗?我总觉得有一个很简单的单行解决方案。
按人员分组并进一步筛选:
no_gold = df.groupby('person').apply(lambda x: (x['item'].ne('gold')).all())
persons_no_gold = no_gold[no_gold].index.values
array(['Sebastian'], dtype=object)
使用pd.get_dummies
和索引
你也可以使用pd.get_dummies
和一些过滤来获得你需要的而不是使用pd.DataFrame.groupby
import pandas as pd
forbidden_item = 'gold'
pivot = pd.get_dummies(df.set_index('person')['item']).max(level=0)
result = pivot[pivot[forbidden_item]==0].index.tolist()
result
['Sebastian']
数据透视表是这样的,因此您可以使用它来处理更复杂的逻辑。
print(pivot)
garden gold house sink stone wood
person
Sebastian 1 0 1 1 0 0
Maria 0 1 1 1 0 0
Achim 0 1 0 0 1 1
可以在这里使用布尔索引+.drop_duplicates()
:
who_has_gold = df.loc[df.item.eq('gold'), 'person'].drop_duplicates()
persons_without_gold = df.loc[~df['person'].isin(who_has_gold), 'person'].drop_duplicates()
print(persons_without_gold)
打印:
0 Sebastian
Name: person, dtype: object