我有以下数据框
df = pd.DataFrame({'ItemType': ['Red', 'White', 'Red', 'Blue', 'White', 'White', 'White', 'Green'],
'ItemPrice': [10, 11, 12, 13, 14, 15, 16, 17],
'ItemID': ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D']})
我想获得ItemIDs的记录(行),其中只包含DataFrame形式的“White”ItemType
我试过以下解决方案:
types = ['Red','Blue','Green']
~df.groupby('ItemID')['ItemType'].any().apply(lambda u: u in(types))
但是这给了我一个不正确的结果(D应该是假的)并且是一个系列的形式。
A False
B False
C True
D True
谢谢!
你应该避免在这里使用apply
,因为它通常很慢。相反,在flag
之前指定一个groupby
列,然后使用all
断言没有任何组值在types
中:
df.assign(flag=~df.ItemType.isin(types)).groupby('ItemID').flag.all()
ItemID
A False
B False
C True
D False
Name: flag, dtype: bool
但是,为了演示操作的逻辑,并显示您的方法的错误,这里是使用apply
的工作版本:
~df.groupby('ItemID').ItemType.apply(lambda x: any(i in types for i in x))
你需要在lambda中使用any
,而不是在使用apply
之前使用系列。
要访问满足此条件的行,您可以使用transform
:
df[df.assign(flag=~df.ItemType.isin(types)).groupby('ItemID').flag.transform('all')]
ItemType ItemPrice ItemID
4 White 14 C
5 White 15 C
另一种方法是计算非白色ItemID
值的数组。然后过滤您的数据框:
non_whites = df.loc[df['ItemType'].ne('White'), 'ItemID'].unique()
res = df[~df['ItemID'].isin(non_whites)]
print(res)
ItemType ItemPrice ItemID
4 White 14 C
5 White 15 C
你也可以使用GroupBy
,但这不是绝对必要的。