按三列组合筛选前 n 个值



我有一个包含 4 列的排序数据帧,如下所示。我正在尝试过滤我的数据帧,以便对于 (Var1、Var2、Var3( 的每个组合,我保留 Var4 的 2 个前 disctint 值。 例如,数据帧中 (Var1, Var2, Var3( 的第一个组合是 (A, B, C(。此组合的前两个不同值是 value_1 和 value_2。 (Var1, Var2, Var3( 的第二个组合是 (A, C, C(。对于这种组合,我只有一种类型的值,即value_14。 等。。。

输入:

Var1  Var2  Var3  Var4
1     A    B      C  value_1
2     A    B      C  value_1
3     A    B      C  value_1
4     A    B      C  value_1
5     A    B      C  value_2
6     A    B      C  value_2
7     A    B      C  value_3
8     A    B      C  value_3
9     A    B      C  value_3
10    A    B      C  value_4
11     A    C      C  value_14
12     A    C      C  value_14
13     A    C      C  value_14
14     A    C      C  value_14
15     B    B      C  value_21
16     B    B      C  value_21
17     B    B      C  value_32
18     B    B      C  value_32
19     B    B      C  value_33
20     B    B      C  value_43

输出:

Var1  Var2  Var3  Var4
1     A    B      C  value_1
2     A    B      C  value_1
3     A    B      C  value_1
4     A    B      C  value_1
5     A    B      C  value_2
6     A    B      C  value_2
11     A    C      C  value_14
12     A    C      C  value_14
13     A    C      C  value_14
14     A    C      C  value_14
15     B    B      C  value_21
16     B    B      C  value_21
17     B    B      C  value_32
18     B    B      C  value_32

请注意,我的数据帧有 500 万行。到目前为止,我已经找到了使用循环的解决方案,但需要将近一个小时。

我们可以使用

df[df.groupby(['Var1','Var2','Var3'])['Var4'].apply(lambda x : x.groupby(x).ngroup()<2)]
Out[106]: 
Var1 Var2 Var3      Var4
1     A    B    C   value_1
2     A    B    C   value_1
3     A    B    C   value_1
4     A    B    C   value_1
5     A    B    C   value_2
6     A    B    C   value_2
11    A    C    C  value_14
12    A    C    C  value_14
13    A    C    C  value_14
14    A    C    C  value_14
15    B    B    C  value_21
16    B    B    C  value_21
17    B    B    C  value_32
18    B    B    C  value_32

ngroup标记该组,然后我们通过减去最小值来确保每个组从 0 开始。然后是一个简单的面具。

s = df.groupby([*df], sort=False).ngroup()  #sort = False keeps ordering of Val4
s = s - s.groupby([df.Var1, df.Var2, df.Var3]).transform('min')
df[s.le(1)]

Var1 Var2 Var3      Var4
1     A    B    C   value_1
2     A    B    C   value_1
3     A    B    C   value_1
4     A    B    C   value_1
5     A    B    C   value_2
6     A    B    C   value_2
11    A    C    C  value_14
12    A    C    C  value_14
13    A    C    C  value_14
14    A    C    C  value_14
15    B    B    C  value_21
16    B    B    C  value_21
17    B    B    C  value_32
18    B    B    C  value_32

让我们使用此方法:

df.drop_duplicates(['Var1','Var2','Var3','Var4'])
.groupby(['Var1','Var2','Var3']).head(2)
.merge(df, on=['Var1','Var2','Var3','Var4'])

输出:

Var1 Var2 Var3      Var4
0     A    B    C   value_1
1     A    B    C   value_1
2     A    B    C   value_1
3     A    B    C   value_1
4     A    B    C   value_2
5     A    B    C   value_2
6     A    C    C  value_14
7     A    C    C  value_14
8     A    C    C  value_14
9     A    C    C  value_14
10    B    B    C  value_21
11    B    B    C  value_21
12    B    B    C  value_32
13    B    B    C  value_32

最新更新