根据条件将过滤器应用于数据框

时间:2020-10-28 18:26:09

标签: pandas

我有这个df:

df = pd.DataFrame({
  'Team': [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z'
  ],
  'Ranking': [
    2, 6, 6, 1, 8, 9, 16, 6, 16, 8, 6, 3, 1, 16, 9, 1, 2, 1, 16, 16, 16, 9, 9, 8, 8
  ],
  'Points': [
    1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
  ]
})

我需要使用以下逻辑对其应用过滤器:

  • 如果团队排名1-4,则最多保留4个项目。
  • 如果团队排名5-12,则最多保留3个项目
  • 如果团队排名12-16,则最多保留2个项目
  • 如果17至20,最多保留1件
  • 在下线时,巫婆的物品超过了配额,则丢弃得分较少的物品。

如何将上述逻辑应用于数据框?

所需结果:

Teams /
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
Y
Z

2 个答案:

答案 0 :(得分:1)

让我们使用pd.cut将排名映射到要提取的行数,然后使用groupby().cumcount()将它们与相对行数进行比较:

thresh = pd.cut(df['Ranking'], bins=[0,4,12,16,20], 
                labels=[4,3,2,1]).astype(int)

df.loc[df.sort_values(['Points'])
         .groupby('Ranking').cumcount().lt( thresh), 'Team']

输出:

0     A
1     B
2     C
3     D
4     E
5     F
7     H
11    L
12    M
15    P
16    Q
17    R
19    T
20    U
21    V
22    X
23    Y
24    Z
Name: Team, dtype: object

答案 1 :(得分:0)

我已经尝试了一种解决方案,但是答案可能与您写的答案有很大出入,可能是因为有误。无论如何,这是您想要做的一种方式。

为了提高可读性,我创建了一个函数,用于根据项目的排名返回要保留的项目数。

def items2keep(ranking):
    return 4 if ranking < 5 else 3 if ranking < 13 else 2 if ranking < 17 else 1

result = []
for rank in df['Ranking'].unique():
    _df = df[df['Ranking'] == rank].nlargest(
        n=items2keep(rank),
        columns=['Points']
    )
    result.append(_df)

final_df = pd.concat(result)

如果我们打印final_df,则会得到:

print(final_df.sort_values(['Ranking', 'Points'], ascending=[True, False]))

   Team  Ranking  Points
15    P        1       3
3     D        1       1
12    M        1       1
17    R        1       1
0     A        2       1
16    Q        2       1
11    L        3       1
1     B        6       1
2     C        6       1
7     H        6       1
9     J        8       2
4     E        8       1
23    Y        8       1
14    O        9       3
5     F        9       2
21    V        9       1
6     G       16       1
8     I       16       1