我有一个想要聚类的列:
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 │
└────────┴─────────┘
当然,如果我有更多的垃圾箱,代码就会变得一团糟。 对于一般情况有什么建议吗?
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')
)