Polars DataFrame在Python中使用mask替换,mask也是一个Polars DataFrame
如何用另一个布尔掩码来改变变量(或重新创建)数据框(DataFrame)?这里不是说单独的列向量(Series),而是两个数据框。
比如说,把所有金额大于270的地方都设置成1000,最后的值就会变成1000。
输入:
apples[0].amount apples[1].amount... apples[3].amount apples[4].amount
0 NaN 321.68012 ... NaN NaN
1 NaN NaN ... NaN 259.70487
2 NaN NaN ... NaN 259.70487
3 NaN NaN ... NaN 259.70487
4 NaN NaN ... NaN 259.70487
... ... ... ... ... ...
440582 79.57273 NaN ... NaN NaN
440583 NaN NaN ... NaN NaN
440584 NaN NaN ... NaN NaN
440585 NaN NaN ... NaN NaN
440586 NaN NaN ... 299.91544 NaN
[440587 rows x 5 columns]
期望的输出:
apples[0].amount apples[1].amount... apples[3].amount apples[4].amount
0 NaN 1000.00000 ... NaN NaN
1 NaN NaN ... NaN 259.70487
2 NaN NaN ... NaN 259.70487
3 NaN NaN ... NaN 259.70487
4 NaN NaN ... NaN 259.70487
... ... ... ... ... ...
440582 79.57273 NaN ... NaN NaN
440583 NaN NaN ... NaN NaN
440584 NaN NaN ... NaN NaN
440585 NaN NaN ... NaN NaN
440586 NaN NaN ... 1000.00000 NaN
[440587 rows x 5 columns]
另一个例子: cum_sum_volume_apples 的输入:
apples[0].amount apples[1].amount ... apples[3].amount apples[4].amount
0 321.66164 1322.18012 ... 1581.98712 1683.34388
1 321.66164 574.39164 ... 849.15207 1260.20487
2 321.66164 574.39164 ... 849.15207 1260.20487
3 321.66164 574.39164 ... 849.15207 1260.20487
4 321.66164 574.39164 ... 849.15207 1260.20487
... ... ... ... ... ...
440582 1080.07273 1089.38273 ... 3248.32543 3266.94847
440583 9.06278 26.69990 ... 1107.99783 1117.30783
440584 346.34516 363.98228 ... 1445.28021 1454.59021
440585 346.34516 363.98228 ... 882.09418 891.40418
440586 426.89556 773.24072 ... 1300.41544 1308.98974
[440587 rows x 5 columns]
at_or_above_threshold_mask ~1000
apples[0].amount apples[1].amount ... apples[3].amount apples[4].amount
0 False True ... False False
1 False False ... False True
2 False False ... False True
3 False False ... False True
4 False False ... False True
... ... ... ... ... ...
440582 True False ... False False
440583 False False ... False False
440584 False False ... False False
440585 False False ... False False
440586 False False ... True False
[440587 rows x 5 columns]
如何仅在另一个具有相同行列长度的数据框上,使用 at_threshold_mask 来过滤出真实值?(一个示例可以是对上面已有的 cum_sum_volume_apples 应用掩码)
cum_sum_all = pl.cum_sum_horizontal("*")
at_or_above_threshold_boolean_cum_sum = (
(cum_sum_volume_apples >= volume_threshold).select(cum_sum_all).unnest("cum_sum")
)
at_or_above_threshold_mask = at_or_above_threshold_boolean_cum_sum >= 1
at_threshold_mask = at_or_above_threshold_boolean_cum_sum == 1
2 个回答
2
在这个情况下,“掩码”是来自于数据框本身,这时你可以使用 pl.when().then()
。
我们可以使用 pl.all()
来一次性引用所有的列。
df.with_columns(
pl.when(pl.all() > 270)
.then(1000.0) # replace with 1000.0
.otherwise(pl.all()) # otherwise keep the existing value
.name.keep()
)
shape: (10, 4)
┌──────────┬────────┬────────┬───────────┐
│ A ┆ B ┆ C ┆ D │
│ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 │
╞══════════╪════════╪════════╪═══════════╡
│ null ┆ 1000.0 ┆ null ┆ null │
│ null ┆ null ┆ null ┆ 259.70487 │
│ null ┆ null ┆ null ┆ 259.70487 │
│ null ┆ null ┆ null ┆ 259.70487 │
│ null ┆ null ┆ null ┆ 259.70487 │
│ 79.57273 ┆ null ┆ null ┆ null │
│ null ┆ null ┆ null ┆ null │
│ null ┆ null ┆ null ┆ null │
│ null ┆ null ┆ null ┆ null │
│ null ┆ null ┆ 1000.0 ┆ null │
└──────────┴────────┴────────┴───────────┘
如果没有 name.keep()
,我们会得到:
ComputeError: the name: 'literal' passed to `LazyFrame.with_columns` is duplicate
这是因为为名为 1000.0
的多个列创建了一个叫 literal
的东西。
>>> pl.select(1000.0) # same as pl.select(pl.lit(1000.0))
shape: (1, 1)
┌─────────┐
│ literal │
│ --- │
│ f64 │
╞═════════╡
│ 1000.0 │
└─────────┘
.name.keep()
会保留原来的列名(在这个例子中是来自 pl.all()
的列名)。
2
除了@jquirous提供的答案,你还可以使用.clip
这个方法来替换掉那些超过或低于某个设定范围的值。
import polars as pl
from polars import col
df = pl.DataFrame({
'a': [1, 5, 10, 15, 20],
'b': [1, 2, 3, 20, 10],
'c': [3, 5, 3, 18, 20]
})
print(
df,
# shape: (5, 3)
# ┌─────┬─────┬─────┐
# │ a ┆ b ┆ c │
# │ --- ┆ --- ┆ --- │
# │ i64 ┆ i64 ┆ i64 │
# ╞═════╪═════╪═════╡
# │ 1 ┆ 1 ┆ 3 │
# │ 5 ┆ 2 ┆ 5 │
# │ 10 ┆ 3 ┆ 3 │
# │ 15 ┆ 20 ┆ 18 │
# │ 20 ┆ 10 ┆ 20 │
# └─────┴─────┴─────┘
df.select(pl.all().clip(upper_bound=15)),
# shape: (5, 3)
# ┌─────┬─────┬─────┐
# │ a ┆ b ┆ c │
# │ --- ┆ --- ┆ --- │
# │ i64 ┆ i64 ┆ i64 │
# ╞═════╪═════╪═════╡
# │ 1 ┆ 1 ┆ 3 │
# │ 5 ┆ 2 ┆ 5 │
# │ 10 ┆ 3 ┆ 3 │
# │ 15 ┆ 15 ┆ 15 │
# │ 15 ┆ 10 ┆ 15 │
# └─────┴─────┴─────┘
sep='\n\n'
)