python-polars - 计算 Polars 列中某个值的分位数,又称为 Polars CDF

标签 python-polars quantile cdf ecdf

我想计算 Polars 列中每一行的分位数。 Polars 有一个分位数函数,用于计算对应于输入分位数的值(逆 CDF),但它似乎没有任何类型的经验 CDF 函数。

Polars 目前具备此功能吗?

最佳答案

原始答案,滚动到末尾以获得更简洁的解决方案

您可以通过按相关值排序然后获取 cum_count/count 来导出 ecdf

例如,让我们将其与plotly 的 ecdf 进行比较

import polars as pl
import numpy as np
import plotly.express as px
import plotly.graph_objects as go

df=pl.DataFrame({'a':np.random.normal(10,5,1000)})
df_ecdf = df.sort('a').with_columns(
         ecdf=((pl.first().cum_count()+1)/(pl.count()))
)
myecdf=px.line(df_ecdf,
        x='a', y='ecdf')
myecdf.update_traces(line_color='red')
pxecdf=px.ecdf(df,
        x='a')
fig=go.Figure()
fig.add_trace(list(myecdf.select_traces())[0])
fig.add_trace(list(pxecdf.select_traces())[0])
fig.show()

enter image description here

Plotly 的 ecdf 似乎有更多的阶梯,我无法解释,如果我们放大到任意部分,它可以更容易看到......

enter image description here

也就是说,与 px.ecdf 相比,px.line 可能被过度平滑。

如果我们从 pxecdf 中提取数据,那么我们就可以进行数值比较。

compare=pl.DataFrame({'plotly_ecdf': pxecdf._data[0]['y'],
                      'plotly_x':pxecdf._data[0]['x']})

compare=df_ecdf.join(compare, left_on='a', right_on='plotly_x')
compare.select(diff=(pl.col('ecdf')-pl.col('plotly_ecdf')).abs().sum())
### returns 0

因此 px.ecdf 中的可见阶梯必须由 px.line 中的某些默认平滑驱动,该平滑不会应用于 px.ecdf,因为它们在数值上是相同的。

对评论的回应以及更简洁的做法

这里有一种方法,您可以仅通过表达式并行生成任意数量的列的 ecdf。

df=pl.DataFrame({'a':np.random.normal(10,5,1000),
                 'b':np.random.normal(10,5,1000),
                 'c':np.random.normal(10,5,1000)})
(
    df
    .with_columns(**{
        f"{x}_ecdf":pl.int_range(1,pl.count()+1).sort_by(pl.arg_sort_by(x))/pl.count()
        for x in df.columns # change df.columns to list of columns for subset only
        })
)
┌───────────┬───────────┬───────────┬────────┬────────┬────────┐
│ a         ┆ b         ┆ c         ┆ a_ecdf ┆ b_ecdf ┆ c_ecdf │
│ ---       ┆ ---       ┆ ---       ┆ ---    ┆ ---    ┆ ---    │
│ f64       ┆ f64       ┆ f64       ┆ f64    ┆ f64    ┆ f64    │
╞═══════════╪═══════════╪═══════════╪════════╪════════╪════════╡
│ 3.115462  ┆ 15.602951 ┆ 1.041053  ┆ 0.085  ┆ 0.873  ┆ 0.033  │
│ 4.481795  ┆ 1.868424  ┆ 9.563978  ┆ 0.121  ┆ 0.044  ┆ 0.477  │
│ 12.686753 ┆ 11.747184 ┆ 9.464207  ┆ 0.673  ┆ 0.644  ┆ 0.462  │
│ 11.416048 ┆ 13.163161 ┆ -0.304657 ┆ 0.598  ┆ 0.739  ┆ 0.02   │
│ 18.453647 ┆ 11.83464  ┆ 8.279558  ┆ 0.956  ┆ 0.649  ┆ 0.359  │
└───────────┴───────────┴───────────┴────────┴────────┴────────┘

理论上,您实际上应该在惰性模式下执行此操作(或在另一个上下文中预先生成 int_range),否则它将为每个列生成 int_range 系列,而不是一次性生成并使用对于每一列。实际上,这可能并不重要,因为这是一个微不足道的操作。

关于python-polars - 计算 Polars 列中某个值的分位数,又称为 Polars CDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77687322/

相关文章:

r - 考虑到数据的子集,如何获得每个数据帧行的百分位值?

r - 如何在 gnuplot 生成的 cdf 上绘制引导线?

r - 如何在 R 中(最好是在 ggplot 中)绘制互补累积分布函数 (CCDF)?

python-polars - 组中唯一项目的数量

python - 极坐标 DataFrame 行之间的分割值

Python Pandas - 手动分位数计算

r - 如何计算分位数中观察值的数量?

python - scipy.stats 中 cdf 的精度

python-polars 两个现有列的字符串连接

python-polars - Python - Polars - 字符串列上的值计数