我正在处理看起来像
所描述的DataFrame的数据df = pd.DataFrame({'AAA': [1,1,1,2,2,2,3,3], 'BBB': [2,1,3,4,6,1,2,3]})
如果价值超过第90个百分点,我想做的是将值设置为综合(90%)。所以它就像把最大值限制在第90个百分位。
这对我来说变得越来越棘手,因为每列都会有不同的百分位值。
我可以使用以下方法获得第90个百分位值:
df.describe(percentiles=[.9])
因此对于BBB列,6大于4.60(第90百分位数),因此需要将其更改为5(综合4.60)。
在我的实际问题中,我正在为一个大矩阵做这个,所以我想知道是否有任何简单的解决方案,而不是首先创建一个90%的列数组,然后检查列中的元素并将这些数据设置为90%。
答案 0 :(得分:2)
一种矢量化方法是合并np.minimum
和df.quantile
:
>>> np.minimum(df, df.quantile(0.9))
AAA BBB
0 1 2.0
1 1 1.0
2 1 3.0
3 2 4.0
4 2 4.6
5 2 1.0
6 3 2.0
7 3 3.0
为了更大的速度提升使用:
np.minimum(df, np.percentile(df, 90, axis=0))
df.quantile
似乎比np.percentile
慢(可能是因为它返回的是Series而不是普通的NumPy数组)。
答案 1 :(得分:1)
执行此操作的一种方法是对每列使用clip_upper()
90%百分位值np.percentile(x, 90)
In [242]: df.apply(lambda x: x.clip_upper(np.percentile(x, 90)))
Out[242]:
AAA BBB
0 1 2.0
1 1 1.0
2 1 3.0
3 2 4.0
4 2 4.6
5 2 1.0
6 3 2.0
7 3 3.0
我想象@ajcr优雅的解决方案会比apply
更快。的但是,强>
低于len(df) ~ 130K
In [245]: %timeit df.apply(lambda x: x.clip_upper(np.percentile(x, 90)))
100 loops, best of 3: 7.49 ms per loop
In [246]: %timeit np.minimum(df, df.quantile(0.9))
100 loops, best of 3: 11.1 ms per loop
适用于len(df) ~ 1M
In [248]: %timeit df.apply(lambda x: x.clip_upper(np.percentile(x, 90)))
10 loops, best of 3: 54.5 ms per loop
In [249]: %timeit np.minimum(df, df.quantile(0.9))
10 loops, best of 3: 73.9 ms per loop