我可以得到一个直方图,其中每个值都是总和而不是桶中值的计数吗?

问题描述 投票:0回答:1

我有一个包含某些事件经过时间的数据集,我想知道使用极坐标在每个时间范围内花费的总时间。

hist
函数给出每个括号内的事件计数,如下所示:

>>> df = pl.DataFrame(
...     {
...         "nam": ["a", "a", "a", "b", "b", "b", "b"],
...         "ela": [1, 1, 20, 3, 4, 10, 20],
...     }
... )
>>> df.group_by("nam").agg(
...     pl.col("ela").hist([ 1, 10,])
... )
shape: (2, 2)
┌─────┬───────────┐
│ nam ┆ ela       │
│ --- ┆ ---       │
│ str ┆ list[u32] │
╞═════╪═══════════╡
│ a   ┆ [2, 0, 1] │
│ b   ┆ [0, 3, 1] │
└─────┴───────────┘


我希望看到的是这样的

shape: (2, 2)
┌─────┬─────────────┐
│ nam ┆ ela         │
│ --- ┆ ---         │
│ str ┆ list[u32]   │
╞═════╪═════════════╡
│ a   ┆ [2, 0, 20]  │
│ b   ┆ [0, 17, 20] │
└─────┴─────────────┘

我尝试过使用

cut
implode

>>> (df.with_columns(pl.col("ela").cut([ 1, 10,]).alias("bucket"))
...     .group_by("nam", "bucket")
...     .agg(ela=pl.sum("ela"))
...     .group_by("nam")
...     .agg(pl.sum("ela").alias("ela_sum"), pl.implode("bucket", "ela"))
... )
shape: (2, 4)
┌─────┬─────────┬──────────────────────────────┬─────────────────┐
│ nam ┆ ela_sum ┆ bucket                       ┆ ela             │
│ --- ┆ ---     ┆ ---                          ┆ ---             │
│ str ┆ i64     ┆ list[list[cat]]              ┆ list[list[i64]] │
╞═════╪═════════╪══════════════════════════════╪═════════════════╡
│ b   ┆ 37      ┆ [["(1, 10]", "(10, inf]"]]   ┆ [[17, 20]]      │
│ a   ┆ 22      ┆ [["(-inf, 1]", "(10, inf]"]] ┆ [[2, 20]]       │
└─────┴─────────┴──────────────────────────────┴─────────────────┘

但我不知道如何获得历史上的紧凑包容格式。它缺少零个存储桶,并且由于某种原因它显示为列表中的列表。

python python-polars
1个回答
0
投票

解决方案

这是一种丑陋的方法,我当然希望有更好的方法:

import polars as pl
import polars.selectors as cs

df = pl.DataFrame(
    {
        "nam": ["a", "a", "a", "b", "b", "b", "b"],
        "ela": [1, 1, 20, 3, 4, 10, 20],
    }
)


(
    df.with_columns(pl.col("ela").cut([1, 10,]).alias("bucket"))
    .group_by("nam", "bucket")
    .agg(
        b=pl.col("ela").hist([1, 10,]),
        c=pl.col("ela").sum()
    )
    .select(
        (
            pl.col("b").list.eval(
                pl.element() > 0
            ) * pl.col("c")
        ).list.to_struct(),
        pl.col("nam")
    )
    .unnest("b")
    .group_by("nam")
    .agg(pl.col("*").sum())
    .select(
        "nam",
        pl.concat_list(cs.numeric())
    )
)

说明

稍微分解一下,将您的两次尝试合并为我们可以使用的一个:

df.with_columns(pl.col("ela").cut([1, 10,]).alias("bucket"))
    .group_by("nam", "bucket")
    .agg(
        b=pl.col("ela").hist([1, 10,]),
        c=pl.col("ela").sum()
)
┌─────┬───────────┬───────────┬─────┐
│ nam ┆ bucket    ┆ b         ┆ c   │
│ --- ┆ ---       ┆ ---       ┆ --- │
│ str ┆ cat       ┆ list[u32] ┆ i64 │
╞═════╪═══════════╪═══════════╪═════╡
│ b   ┆ (10, inf] ┆ [0, 0, 1] ┆ 20  │
│ a   ┆ (-inf, 1] ┆ [2, 0, 0] ┆ 2   │
│ a   ┆ (10, inf] ┆ [0, 0, 1] ┆ 20  │
│ b   ┆ (1, 10]   ┆ [0, 3, 0] ┆ 17  │
└─────┴───────────┴───────────┴─────┘

剩下的就是用一种丑陋的方式将其转化为最终结果

  1. 计算列表中非零出现的次数
  2. 转换为结构体并进一步取消嵌套为列(以获取列表的按元素求和)
  3. 计算分组总和并使用
    concat_list
    和数字选择器聚合列表。
© www.soinside.com 2019 - 2024. All rights reserved.