根据python中的百分位数替换列值

时间:2017-11-08 18:44:33

标签: python pandas grouping percentile

我已经对一个数据框进行了分组,我希望每个组可以替换某些列中的值,如果它们小于某个百分位数。 因此,一组中大于0.95百分位数的所有值应替换为0.95百分位数,所有小于0.05百分位数的值应替换为0.05百分位数。
数据框可能如下所示(示例来自another question): 两组:'一'和'两'

    A           B           C
0   0.719391    0.091693    one
1   0.951499    0.83716     one
2   0.975212    0.224855    one
3   0.80762     0.031284    one
4   0.63319     0.342889    one
5   0.075102    0.899291    one
6   0.502843    0.773424    one
7   0.032285    0.242476    one
8   0.794938    0.607745    one
9   0.620387    0.574222    one
10  0.446639    0.549749    two
11  0.664324    0.134041    two
12  0.622217    0.505057    two
13  0.670338    0.99087     two
14  0.281431    0.016245    two
15  0.675756    0.185967    two
16  0.145147    0.045686    two
17  0.404413    0.191482    two
18  0.94913     0.943509    two
19  0.164642    0.157013    two

此数据框的结果应为:

A               B           C
0   0.719391    0.091693    one
1   0.951499    0.83716     one
2   0.96454115  0.224855    one
3   0.80762     0.05846805  one
4   0.63319     0.342889    one
5   0.075102    0.87133205  one
6   0.502843    0.773424    one
7   0.05155265  0.242476    one
8   0.794938    0.607745    one
9   0.620387    0.574222    one
10  0.446639    0.549749    two
11  0.664324    0.134041    two
12  0.622217    0.505057    two
13  0.670338    0.96955755  two
14  0.281431    0.02949345  two
15  0.675756    0.185967    two
16  0.15391975  0.045686    two
17  0.404413    0.191482    two
18  0.8261117   0.943509    two
19  0.164642    0.157013    two

请注意,对于A列,已替换第2,7,16和18行;对于B列,已经更换了行3,5,13和14。

有没有人知道如何以有效的方式为大型数据帧执行此操作?

由于

3 个答案:

答案 0 :(得分:3)

您可以使用groupby + quantile + clip

g = df.groupby('C').transform(lambda x: x.clip(*x.quantile([0.05, 0.95])))
g['C'] = df['C']

           A         B    C
0   0.719391  0.091693  one
1   0.951499  0.837160  one
2   0.964541  0.224855  one
3   0.807620  0.058468  one
4   0.633190  0.342889  one
5   0.075102  0.871332  one
6   0.502843  0.773424  one
7   0.051553  0.242476  one
8   0.794938  0.607745  one
9   0.620387  0.574222  one
10  0.446639  0.549749  two
11  0.664324  0.134041  two
12  0.622217  0.505057  two
13  0.670338  0.969558  two
14  0.281431  0.029493  two
15  0.675756  0.185967  two
16  0.153920  0.045686  two
17  0.404413  0.191482  two
18  0.826112  0.943509  two
19  0.164642  0.157013  two

完整性检查

np.allclose(e[['A', 'B']].values, g[['A', 'B']].values)
True

此处,e是您问题中的输出。

答案 1 :(得分:2)

df.groupby('C')['A','B'].transform(lambda x : np.clip(x,x.quantile(0.05),x.quantile(0.95)))
Out[1599]: 
           A         B
0   0.719391  0.091693
1   0.951499  0.837160
2   0.964541  0.224855
3   0.807620  0.058468
4   0.633190  0.342889
5   0.075102  0.871332
6   0.502843  0.773424
7   0.051553  0.242476
8   0.794938  0.607745
9   0.620387  0.574222
10  0.446639  0.549749
11  0.664324  0.134041
12  0.622217  0.505057
13  0.670338  0.969558
14  0.281431  0.029493
15  0.675756  0.185967
16  0.153920  0.045686
17  0.404413  0.191482
18  0.826112  0.943509
19  0.164642  0.157013

答案 2 :(得分:0)

要使其更快,您可以通过此方法来完成,尽管如果您有很多列,这将涉及很多编码行。这是我的数据集中包含200万行的非常快速的方法(<1s)。和您一样,.groupby非常慢!

A_05 = df['A'].quantile(0.05)
A_95 = df['A'].quantile(0.95)
df['A'].clip(A_05, A_95, inplace=True)