如何在 polars 中调用带有两个位置参数的 numpy ufunc?

How can I call a numpy ufunc with two positional arguments in polars?

我想调用一个在 polars 中有两个位置参数的 numpy 通用函数 (ufunc)。

df.with_column(
    numpy.left_shift(pl.col('col1'), 8)
)

以上尝试导致以下错误消息

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/local/lib/python3.8/dist-packages/polars/internals/expr.py", line 181, in __array_ufunc__
    out_type = ufunc(np.array([1])).dtype
TypeError: left_shift() takes from 2 to 3 positional arguments but 1 were given

还有其他方法可以执行此计算,例如,

df['col1'] = numpy.left_shift(df['col1'], 8)

...但我正在尝试将其与 polars.LazyFrame.

一起使用

我正在使用 polars 0.13.13 和 Python 3.8。

编辑:从 Polars 0.13.19 开始,apply 方法无需 Numpy item 方法即可将 Numpy 数据类型转换为 Polars 数据类型。

当您只需要将一列从 polars 传递到 ufunc 时(如您的示例所示),最简单的方法是在特定列上使用 apply 函数。

import numpy as np
import polars as pl

df = pl.DataFrame({"col1": [2, 4, 8, 16]}).lazy()

df.with_column(
    pl.col("col1").apply(lambda x: np.left_shift(x, 8).item()).alias("result")
).collect()
shape: (4, 2)
┌──────┬────────┐
│ col1 ┆ result │
│ ---  ┆ ---    │
│ i64  ┆ i64    │
╞══════╪════════╡
│ 2    ┆ 512    │
├╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 4    ┆ 1024   │
├╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 8    ┆ 2048   │
├╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 16   ┆ 4096   │
└──────┴────────┘

如果您需要将多列从 Polars 传递到 ufunc,请使用 struct 表达式和 apply

df = pl.DataFrame({"col1": [2, 4, 8, 16], "shift": [1, 1, 2, 2]}).lazy()

df.with_column(
    pl.struct(["col1", "shift"])
    .apply(lambda cols: np.left_shift(cols["col1"], cols["shift"]).item())
    .alias("result")
).collect()
shape: (4, 3)
┌──────┬───────┬────────┐
│ col1 ┆ shift ┆ result │
│ ---  ┆ ---   ┆ ---    │
│ i64  ┆ i64   ┆ i64    │
╞══════╪═══════╪════════╡
│ 2    ┆ 1     ┆ 4      │
├╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 4    ┆ 1     ┆ 8      │
├╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 8    ┆ 2     ┆ 32     │
├╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 16   ┆ 2     ┆ 64     │
└──────┴───────┴────────┘

一个注意事项:在未来的 Polars 版本中可能不再需要使用 numpy item 方法。 (目前,apply 方法并不总是自动在 numpy dtypes 和 Polars dtypes 之间转换。)

这有帮助吗?