对列进行聚类

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

我有一个想要聚类的列:

df = pl.DataFrame({"values": [0.1, 0.5, 0.7, -0.2, 0.4, -0.7, 0.05]})
shape: (7, 1)
┌────────┐
│ values │
│ ---    │
│ f64    │
╞════════╡
│ 0.1    │
│ 0.5    │
│ 0.7    │
│ -0.2   │
│ 0.4    │
│ -0.7   │
│ 0.05   │
└────────┘

如果某个值小于 -0.5,则为 -1;如果小于零,则为 0;否则为 1。

df = df.with_columns(
    pl.when(pl.col("values") <= -0.5)
    .then(-1)
    .otherwise(
        pl.when(pl.col("values") <= 0)
        .then(0.0)
        .otherwise(1)
    )
)
shape: (7, 2)
┌────────┬─────────┐
│ values ┆ literal │
│ ---    ┆ ---     │
│ f64    ┆ f64     │
╞════════╪═════════╡
│ 0.1    ┆ 1.0     │
│ 0.5    ┆ 1.0     │
│ 0.7    ┆ 1.0     │
│ -0.2   ┆ 0.0     │
│ 0.4    ┆ 1.0     │
│ -0.7   ┆ -1.0    │
│ 0.05   ┆ 1.0     │
└────────┴─────────┘

当然,如果我有更多的垃圾箱,代码就会变得一团糟。 对于一般情况有什么建议吗?

python-polars
1个回答
1
投票

当有大量垃圾箱时,实现此目的的一个好方法是使用

join_asof

首先,我将修改您的输入数据(这样我们就可以看到如何处理断点为

<=
与严格
<
时的情况)。

df = pl.DataFrame({"values": pl.int_range(0, 10, eager=True) / 4 - 1.0})
df
shape: (10, 1)
┌────────┐
│ values │
│ ---    │
│ f64    │
╞════════╡
│ -1.0   │
│ -0.75  │
│ -0.5   │
│ -0.25  │
│ 0.0    │
│ 0.25   │
│ 0.5    │
│ 0.75   │
│ 1.0    │
│ 1.25   │
└────────┘

包含上限值 (
<=
)

现在我们将创建一个 DataFrame,其中包含我们的上限断点和我们想要的聚类值。 例如:

cluster_vals = (
    pl.DataFrame({
        'bin_value': [-0.5, 0.0, float('Inf')],
        'clustered_value': [-1.0, 0.0, 1.0],
    })
)
cluster_vals
>>> cluster_vals
shape: (3, 2)
┌───────────┬─────────────────┐
│ bin_value ┆ clustered_value │
│ ---       ┆ ---             │
│ f64       ┆ f64             │
╞═══════════╪═════════════════╡
│ -0.5      ┆ -1.0            │
│ 0.0       ┆ 0.0             │
│ inf       ┆ 1.0             │
└───────────┴─────────────────┘

然后我们执行我们的

join_asof
。 带有
join_asof
strategy=forward
将包括垃圾箱中的上部断点。

请注意,

join_asof
中的两个 DataFrame 必须按 asof 列进行预排序。 (我已经在这里明确地对两者进行了排序,即使我们的
clustered_vals
DataFrame 已经排序 - 只是作为提醒)。

(
    df
    .sort('values')
    .join_asof(
        other=cluster_vals
              .sort('bin_value'),
        left_on='values',
        right_on='bin_value',
        strategy='forward',
    )
)
shape: (10, 3)
┌────────┬───────────┬─────────────────┐
│ values ┆ bin_value ┆ clustered_value │
│ ---    ┆ ---       ┆ ---             │
│ f64    ┆ f64       ┆ f64             │
╞════════╪═══════════╪═════════════════╡
│ -1.0   ┆ -0.5      ┆ -1.0            │
│ -0.75  ┆ -0.5      ┆ -1.0            │
│ -0.5   ┆ -0.5      ┆ -1.0            │
│ -0.25  ┆ 0.0       ┆ 0.0             │
│ 0.0    ┆ 0.0       ┆ 0.0             │
│ 0.25   ┆ inf       ┆ 1.0             │
│ 0.5    ┆ inf       ┆ 1.0             │
│ 0.75   ┆ inf       ┆ 1.0             │
│ 1.0    ┆ inf       ┆ 1.0             │
│ 1.25   ┆ inf       ┆ 1.0             │
└────────┴───────────┴─────────────────┘

注意每个 bin 的上限断点(-0.5 和 0.0)如何包含在 bin 中。

不包括上限值(严格意义上
<

如果我们不想将上限值包含在 bin 中,我们可以切换到

strategy=backward
并将 bin 更改为 bin 的 lower 端点。

我们修改后的聚类值 DataFrame 将是:

cluster_vals = (
    pl.DataFrame({
        'bin_value': [float('-Inf'), -0.5, 0.0],
        'clustered_value': [-1.0, 0.0, 1.0],
    })
)
cluster_vals
shape: (3, 2)
┌───────────┬─────────────────┐
│ bin_value ┆ clustered_value │
│ ---       ┆ ---             │
│ f64       ┆ f64             │
╞═══════════╪═════════════════╡
│ -inf      ┆ -1.0            │
│ -0.5      ┆ 0.0             │
│ 0.0       ┆ 1.0             │
└───────────┴─────────────────┘

我们的

join_asof
将变成:

(
    df
    .sort('values')
    .join_asof(
        other=cluster_vals
              .sort('bin_value'),
        left_on='values',
        right_on='bin_value',
        strategy='backward',
    )
)
shape: (10, 3)
┌────────┬───────────┬─────────────────┐
│ values ┆ bin_value ┆ clustered_value │
│ ---    ┆ ---       ┆ ---             │
│ f64    ┆ f64       ┆ f64             │
╞════════╪═══════════╪═════════════════╡
│ -1.0   ┆ null      ┆ null            │
│ -0.75  ┆ null      ┆ null            │
│ -0.5   ┆ -0.5      ┆ -1.0            │
│ -0.25  ┆ -0.5      ┆ -1.0            │
│ 0.0    ┆ 0.0       ┆ 0.0             │
│ 0.25   ┆ 0.0       ┆ 0.0             │
│ 0.5    ┆ 0.0       ┆ 0.0             │
│ 0.75   ┆ 0.0       ┆ 0.0             │
│ 1.0    ┆ 0.0       ┆ 0.0             │
│ 1.25   ┆ 0.0       ┆ 0.0             │
└────────┴───────────┴─────────────────┘

请注意每个 bin 的上断点如何不再包含在 bin 中。

注意
when/then/otherwise

简单说明一下:when/then 语句可以链接起来,这样就只需要一个:

df.with_columns(
    pl.when(pl.col("values") <= -0.5)
    .then(-1)
    .when(pl.col("values") <= 0)
    .then(0.0)
    .otherwise(1)
    .alias('result')
)
© www.soinside.com 2019 - 2024. All rights reserved.