每次出现空值时,如何通过对列的其余部分进行采样以获得唯一值,从而在DataFrame中实现fill_null

例如:假设我有这个DataFrame:

>>> daf=pl.DataFrame({"a":[1,2, None, None, 5, 6, None, None, None, 10], "b":[None, "two", "three", None, "five", "six", "seven", None, "nine", "ten"]})
>>> daf
shape: (10, 2)
┌──────┬───────┐
│ a    ┆ b     │
│ ---  ┆ ---   │
│ i64  ┆ str   │
╞══════╪═══════╡
│ 1    ┆ null  │
│ 2    ┆ two   │
│ null ┆ three │
│ null ┆ null  │
│ 5    ┆ five  │
│ 6    ┆ six   │
│ null ┆ seven │
│ null ┆ null  │
│ null ┆ nine  │
│ 10   ┆ ten   │
└──────┴───────┘

我想通过对列的其余部分进行采样来填充所有列中的空值.例如,"a"中的空值应该从[1,2,5,6,10]中获得随机值,而"b"中的空值应该从["2","3","5","6","7","9","10"中获得随机值.但a中不应该有str,b中也不应该有i64.并且用于填充空值的值对于列中的每个空值都不应该相同.

我可以通过使用标准的Pythonfor循环遍历列来做到这一点:

>>> for c in daf.columns:
...   repl=daf[c].drop_nulls().sample(daf[c].len(), with_replacement=True)
...   daf=daf.with_columns(pl.col(c).fill_null(repl))
...
>>> daf
shape: (10, 2)
┌─────┬───────┐
│ a   ┆ b     │
│ --- ┆ ---   │
│ i64 ┆ str   │
╞═════╪═══════╡
│ 1   ┆ two   │
│ 2   ┆ two   │
│ 1   ┆ three │
│ 2   ┆ six   │
│ 5   ┆ five  │
│ 6   ┆ six   │
│ 5   ┆ seven │
│ 10  ┆ two   │
│ 5   ┆ nine  │
│ 10  ┆ ten   │
└─────┴───────┘

但我试图弄清楚如何使用表达式来做这件事,但我无法做到.有没有一种更简洁的方式来实现这一点,使用Polars表达式语法?

推荐答案

这似乎奏效了.它基于您最初的 idea ,它只是纯粹使用表达式对每一列执行相同的操作.

daf.select(
    pl.col("*").fill_null(
        pl.col("*").drop_nulls().sample(pl.len(), with_replacement=True)
    )
)
┌─────┬───────┐
│ a   ┆ b     │
│ --- ┆ ---   │
│ i64 ┆ str   │
╞═════╪═══════╡
│ 1   ┆ two   │
│ 2   ┆ two   │
│ 6   ┆ three │
│ 10  ┆ six   │
│ 5   ┆ five  │
│ 6   ┆ six   │
│ 1   ┆ seven │
│ 2   ┆ two   │
│ 2   ┆ nine  │
│ 10  ┆ ten   │
└─────┴───────┘

解释

pl.col("*")(或pl.all())只需单独 Select 每一列,然后对其应用后续操作.后来,它保留了相同的 struct ,因为例如,它是这样工作的:

>>> df = pl.DataFrame({"a": [1, 2, 3], "b": [100, 200, 300]})
>>> df.select(pl.col("*").mul(pl.col("*").mean()))
shape: (3, 2)
┌─────┬─────────┐
│ a   ┆ b       │
│ --- ┆ ---     │
│ f64 ┆ f64     │
╞═════╪═════════╡
│ 2.0 ┆ 20000.0 │
│ 4.0 ┆ 40000.0 │
│ 6.0 ┆ 60000.0 │
└─────┴─────────┘

如果我使用LazyFrameexplain,它在引擎盖下面是这样做的:

>>> daf.select(pl.col("*").fill_null(pl.col("*").drop_nulls().sample(pl.len(), with_replacement=True))).explain()
 SELECT [col("a").fill_null([col("a").drop_nulls().sample([len()])]), col("b").fill_null([col("b").drop_nulls().sample([len()])])] FROM
  DF ["a", "b"]; PROJECT 2/2 COLUMNS; SELECTION: "None"

让我有点惊讶的是,fill_null部分确实起作用了.fill_nulldocumentation不是很清楚,您可以向它传递一个表达式,该表达式返回的不是单个值,它的工作方式是这样的.

此外,人们还会认为使用1100而不是pl.len()会产生相同的结果,但是对于每个空替换,1号返回相同的样本,而1pl.len()以外的任何值都会产生形状误差.

它似乎做了一个表大小的or操作,并将每个空值替换为来自另一边的对应点的值(仍然可以是空的),这有点有趣.

>>> daf.select(pl.col("*").fill_null(pl.col("*").reverse()))
shape: (10, 2)
┌──────┬───────┐
│ a    ┆ b     │
│ ---  ┆ ---   │
│ i64  ┆ str   │
╞══════╪═══════╡
│ 1    ┆ ten   │
│ 2    ┆ two   │
│ null ┆ three │
│ null ┆ seven │
│ 5    ┆ five  │
│ 6    ┆ six   │
│ null ┆ seven │
│ null ┆ three │
│ 2    ┆ nine  │
│ 10   ┆ ten   │
└──────┴───────┘

Python相关问答推荐

Pandas 填充条件是另一列

大Pandas 胚胎中产生组合

在Pandas DataFrame操作中用链接替换'方法的更有效方法

如何找到满足各组口罩条件的第一行?

按顺序合并2个词典列表

如何在turtle中不使用write()来绘制填充字母(例如OEG)

启用/禁用shiny 的自动重新加载

Python Tkinter为特定样式调整所有ttkbootstrap或ttk Button填充的大小,适用于所有主题

用SymPy在Python中求解指数函数

Gunicorn无法启动Flask应用,因为无法将应用解析为属性名或函数调用.'"'' "

计算空值

用两个字符串构建回文

使用python playwright从 Select 子菜单中 Select 值

Python—在嵌套列表中添加相同索引的元素,然后计算平均值

如何使用pytest在traceback中找到特定的异常

ModuleNotFoundError:Python中没有名为google的模块''

查找查找表中存在的列值组合

替换包含Python DataFrame中的值的<;

Stats.ttest_ind:提取df值

在不降低分辨率的情况下绘制一组数据点的最外轮廓