将 DataFrame 中每一列的值设置为第 90 个百分位数
Set value to 90th percentile for each column in a DataFrame
我正在处理看起来像
描述的 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 个百分位数。
执行此操作的一种方法是 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
一种矢量化方法是结合 np.minimum
and 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
慢(可能是因为它 returns 是一个系列而不是普通的 NumPy 数组)。
我正在处理看起来像
描述的 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 个百分位数。
执行此操作的一种方法是 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
一种矢量化方法是结合 np.minimum
and 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
慢(可能是因为它 returns 是一个系列而不是普通的 NumPy 数组)。