根据Python中的分组列值执行条件筛选

根据Python中的分组列值执行条件筛选,python,pandas,Python,Pandas,我想对Sales列执行筛选,以便对于任何Make拍卖组,至少有一个Sales大于等于100。因此,对于Acura而言,Copart的销售额为101,因此预计Acura的两行产品都将出现在产量中。对于宝马来说,整个销售栏的销售额是100,但这不是我想要的。有没有关于如何执行此操作的建议?谢谢 过滤数据框中销售>=100的记录,然后获取汽车的唯一Make。最后,如果此筛选集中有任何make,请使用布尔索引 >>> df[df['Make'].isin(df[df['Sales']

我想对Sales列执行筛选,以便对于任何Make拍卖组,至少有一个Sales大于等于100。因此,对于Acura而言,Copart的销售额为101,因此预计Acura的两行产品都将出现在产量中。对于宝马来说,整个销售栏的销售额是100,但这不是我想要的。有没有关于如何执行此操作的建议?谢谢

过滤数据框中销售>=100的记录,然后获取汽车的唯一
Make
。最后,如果此筛选集中有任何make,请使用布尔索引

>>> df[df['Make'].isin(df[df['Sales'] >= 100]['Make'].unique())]
    Make Auction  Sales
0  Acura  Copart    101
1  Acura     IAA     88
4  Buick  Copart    130
5  Buick     IAA    140
使用:

另一种解决方案,使用和为
生成
值,这些值通过以下方式过滤:

第二种解决方案更快:

np.random.seed(123)
N = 1000000
L = list('abcdefghijklmno')
df = pd.DataFrame({'Make': np.random.choice(L, N),
                   'Sales':np.random.randint(110, size=N)})
print (df)

In [59]: %timeit df[df['Make'].isin(df.loc[df['Sales'] >= 100, 'Make'])]
10 loops, best of 3: 55.6 ms per loop

#Alexander answer
In [60]: %timeit df[df['Make'].isin(df[df['Sales'] >= 100]['Make'].unique())]
10 loops, best of 3: 65 ms per loop

In [61]: %timeit df.groupby('Make').filter(lambda x: x['Sales'].ge(100).any())
1 loop, best of 3: 217 ms per loop

#piRSquared solution 1
In [62]: %timeit df[df.Sales.ge(100).groupby([df.Make]).transform('any')]
1 loop, best of 3: 135 ms per loop

#piRSquared solution 2
In [63]: %%timeit
    ...: f, u = pd.factorize(df.Make.values)
    ...: w = df.Sales.values >= 100
    ...: df[(np.bincount(f, w) > 0)[f]]
    ...: 
10 loops, best of 3: 67.2 ms per loop

选项1
转换

使用
'any'
返回
True
如果组中有任何元素
True
,并在组中的所有索引中广播该元素

df[df.Sales.ge(100).groupby([df.Make]).transform('any')]

    Make Auction  Sales
0  Acura  Copart    101
1  Acura     IAA     88
4  Buick  Copart    130
5  Buick     IAA    140

选项2
+
我们使用
np.bincount
pd.factorize
增加仓位,其真值由
df.Sales.values>=100
确定。如果bin大于
0
,那么我们应该获取该bin定义的组中的每个元素。我们可以通过
f
再次切片得到合适的数组

这与选项1非常类似

f, u = pd.factorize(df.Make.values)
w = df.Sales.values >= 100
df[(np.bincount(f, w) > 0)[f]]

    Make Auction  Sales
0  Acura  Copart    101
1  Acura     IAA     88
4  Buick  Copart    130
5  Buick     IAA    140

有趣。你能详细说明一下变换中的任何吗?“更快”完全取决于
N
,不确定,为了更好地进行测试,必须知道
中唯一值的数量、组的长度、数据帧的长度。但是显然,
loc
有助于提高性能。使用
loc
似乎不会影响性能,但我认为改进是微不足道的。
print (df.loc[df['Sales'] >= 100, 'Make'])
0    Acura
4    Buick
5    Buick
Name: Make, dtype: object

print (df['Make'].isin(df.loc[df['Sales'] >= 100, 'Make']))
0     True
1     True
2    False
3    False
4     True
5     True
Name: Make, dtype: bool

df = df[df['Make'].isin(df.loc[df['Sales'] >= 100, 'Make'])]
print (df)
    Make Auction  Sales
0  Acura  Copart    101
1  Acura     IAA     88
4  Buick  Copart    130
5  Buick     IAA    140
np.random.seed(123)
N = 1000000
L = list('abcdefghijklmno')
df = pd.DataFrame({'Make': np.random.choice(L, N),
                   'Sales':np.random.randint(110, size=N)})
print (df)

In [59]: %timeit df[df['Make'].isin(df.loc[df['Sales'] >= 100, 'Make'])]
10 loops, best of 3: 55.6 ms per loop

#Alexander answer
In [60]: %timeit df[df['Make'].isin(df[df['Sales'] >= 100]['Make'].unique())]
10 loops, best of 3: 65 ms per loop

In [61]: %timeit df.groupby('Make').filter(lambda x: x['Sales'].ge(100).any())
1 loop, best of 3: 217 ms per loop

#piRSquared solution 1
In [62]: %timeit df[df.Sales.ge(100).groupby([df.Make]).transform('any')]
1 loop, best of 3: 135 ms per loop

#piRSquared solution 2
In [63]: %%timeit
    ...: f, u = pd.factorize(df.Make.values)
    ...: w = df.Sales.values >= 100
    ...: df[(np.bincount(f, w) > 0)[f]]
    ...: 
10 loops, best of 3: 67.2 ms per loop
df[df.Sales.ge(100).groupby([df.Make]).transform('any')]

    Make Auction  Sales
0  Acura  Copart    101
1  Acura     IAA     88
4  Buick  Copart    130
5  Buick     IAA    140
f, u = pd.factorize(df.Make.values)
w = df.Sales.values >= 100
df[(np.bincount(f, w) > 0)[f]]

    Make Auction  Sales
0  Acura  Copart    101
1  Acura     IAA     88
4  Buick  Copart    130
5  Buick     IAA    140