Skip to content

Arithmetic

polars_ta.wq.arithmetic

除了使用概率极高的几个函数,其他函数不再对常量做lit

Functions:

Name Description
abs_

求绝对值

add

水平多列相加

arc_cos

反余弦

arc_sin

反正弦

arc_tan

反正切

arc_tan2

反正切二值函数

cbrt

立方根

ceiling

向上取整

cos

余弦

cosh

双曲余弦

cot

余切

cube

立方

degrees

弧度转角度

div

x除以y的整数部分

divide

除法

exp

自然指数函数

expm1

对数收益率 转 简单收益率

floor

向下取整

fraction

小数部分

inverse

倒数

log

以e为底的对数

log10

以10为底的对数

log1p

简单收益率 转 对数收益率

log2

以2为底的对数

max_

水平多列求最大值

mean

水平多列求均值

min_

水平多列求最小值

mod

求余

multiply

水平多列相乘

power

乘幂

radians

角度转弧度

reverse

求相反数

round_

四舍五入

round_down

小于输入的f的最大倍数

s_log_1p

sign(x) * log10(1 + abs(x))

sign

符号函数

signed_power

x的y次幂,符号保留

sin

正弦

sinh

双曲正弦

softsign

softsign激活函数

sqrt

平方根

square

平方

std

水平多列求标准差

subtract

减法

tan

正切

tanh

双曲正切

var

水平多列求方差

abs_(x: Expr) -> Expr

求绝对值

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
    'b': [None, -1, 0, 1, 2],
}).with_columns(
    out1=abs_(pl.col('a')),
    out2=abs_(-1),
)
shape: (5, 4)
┌──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out1 ┆ out2 │
│ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ i64  ┆ i32  │
╞══════╪══════╪══════╪══════╡
│ null ┆ null ┆ null ┆ 1    │
│ -1   ┆ -1   ┆ 1    ┆ 1    │
│ 0    ┆ 0    ┆ 0    ┆ 1    │
│ 1    ┆ 1    ┆ 1    ┆ 1    │
│ 2    ┆ 2    ┆ 2    ┆ 1    │
└──────┴──────┴──────┴──────┘

add(a: Expr, b: Expr, *args) -> Expr

水平多列相加

Examples:

df = pl.DataFrame({
    'a': [None, 2, 3, 4, None],
    'b': [5, None, 3, 2, None],
    'c': [1, 1, None, 1, None],
}).with_columns(
    out=add(pl.col('a'), pl.col('b'), pl.col('c'))
)
shape: (5, 4)
┌──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ c    ┆ out  │
│ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ i64  ┆ i64  │
╞══════╪══════╪══════╪══════╡
│ null ┆ 5    ┆ 1    ┆ 6    │
│ 2    ┆ null ┆ 1    ┆ 3    │
│ 3    ┆ 3    ┆ null ┆ 6    │
│ 4    ┆ 2    ┆ 1    ┆ 7    │
│ null ┆ null ┆ null ┆ null │
└──────┴──────┴──────┴──────┘

Notes

null时返回null

arc_cos(x: Expr) -> Expr

反余弦

arc_sin(x: Expr) -> Expr

反正弦

arc_tan(x: Expr) -> Expr

反正切

arc_tan2(y: Expr, x: Expr) -> Expr

反正切二值函数

cbrt(x: Expr) -> Expr

立方根

ceiling(x: Expr) -> Expr

向上取整

cos(x: Expr) -> Expr

余弦

cosh(x: Expr) -> Expr

双曲余弦

cot(x: Expr) -> Expr

余切

cube(x: Expr) -> Expr

立方

degrees(x: Expr) -> Expr

弧度转角度

div(x: Expr, y: Expr) -> Expr

x除以y的整数部分

Examples:

df = pl.DataFrame({
    'a': [None, -1.5, 0., 1.5, 2.5],
    'b': [None, -1, 0, 1, 2],
}).with_columns(
    out1=div(pl.col('a'), 0),
    out2=div(pl.col('a'), 1),
    out3=div(pl.col('a'), pl.col('b')),
)
shape: (5, 5)
┌──────┬──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out1 ┆ out2 ┆ out3 │
│ ---  ┆ ---  ┆ ---  ┆ ---  ┆ ---  │
│ f64  ┆ i64  ┆ i64  ┆ i64  ┆ i64  │
╞══════╪══════╪══════╪══════╪══════╡
│ null ┆ null ┆ null ┆ null ┆ null │
│ -1.5 ┆ -1   ┆ null ┆ -2   ┆ 1    │
│ 0.0  ┆ 0    ┆ null ┆ 0    ┆ null │
│ 1.5  ┆ 1    ┆ null ┆ 1    ┆ 1    │
│ 2.5  ┆ 2    ┆ null ┆ 2    ┆ 1    │
└──────┴──────┴──────┴──────┴──────┘

divide(x: Expr, y: Expr) -> Expr

除法

x/y

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
    'b': [None, -1, 0, 1, 2],
}).with_columns(
    out1=divide(pl.col('a'), 0),
    out2=divide(pl.col('a'), 1),
    out3=divide(pl.col('a'), pl.col('b')),
)
shape: (5, 5)
┌──────┬──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out1 ┆ out2 ┆ out3 │
│ ---  ┆ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ f64  ┆ f64  ┆ f64  │
╞══════╪══════╪══════╪══════╪══════╡
│ null ┆ null ┆ null ┆ null ┆ null │
│ -1   ┆ -1   ┆ -inf ┆ -1.0 ┆ 1.0  │
│ 0    ┆ 0    ┆ NaN  ┆ 0.0  ┆ NaN  │
│ 1    ┆ 1    ┆ inf  ┆ 1.0  ┆ 1.0  │
│ 2    ┆ 2    ┆ inf  ┆ 2.0  ┆ 1.0  │
└──────┴──────┴──────┴──────┴──────┘

exp(x: Expr) -> Expr

自然指数函数

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=expm1(pl.col('a')),
)
shape: (5, 2)
┌──────┬──────────┐
│ a    ┆ out1     │
│ ---  ┆ ---      │
│ i64  ┆ f64      │
╞══════╪══════════╡
│ null ┆ null     │
│ -1   ┆ 0.367879 │
│ 0    ┆ 1.0      │
│ 1    ┆ 2.718282 │
│ 2    ┆ 7.389056 │
└──────┴──────────┘

expm1(x: Expr) -> Expr

对数收益率 转 简单收益率

convert log return to simple return

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=expm1(pl.col('a')),
)
shape: (5, 2)
┌──────┬───────────┐
│ a    ┆ out1      │
│ ---  ┆ ---       │
│ i64  ┆ f64       │
╞══════╪═══════════╡
│ null ┆ null      │
│ -1   ┆ -0.632121 │
│ 0    ┆ 0.0       │
│ 1    ┆ 1.718282  │
│ 2    ┆ 6.389056  │
└──────┴───────────┘

floor(x: Expr) -> Expr

向下取整

fraction(x: Expr) -> Expr

小数部分

This operator removes the whole number part and returns the remaining fraction part with sign.

Examples:

df = pl.DataFrame({
    'a': [-2.5, -1.2, -1., None, 2., 3.2],
}).with_columns(
    out=fraction(pl.col('a'))
)

shape: (6, 2)
┌──────┬──────┐
│ a    ┆ out  │
│ ---  ┆ ---  │
│ f64  ┆ f64  │
╞══════╪══════╡
│ -2.5 ┆ -0.5 │
│ -1.2 ┆ -0.2 │
│ -1.0 ┆ -0.0 │
│ null ┆ null │
│ 2.0  ┆ 0.0  │
│ 3.2  ┆ 0.2  │
└──────┴──────┘
Notes

按小学时的定义,负数-1.2的整数部分是-2,小数部分是0.8,而这有所不同

References

https://platform.worldquantbrain.com/learn/operators/detailed-operator-descriptions#fractionx

inverse(x: Expr) -> Expr

倒数

1/x

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=inverse(pl.col('a')),
)
shape: (5, 2)
┌──────┬──────┐
│ a    ┆ out1 │
│ ---  ┆ ---  │
│ i64  ┆ f64  │
╞══════╪══════╡
│ null ┆ null │
│ -1   ┆ -1.0 │
│ 0    ┆ inf  │
│ 1    ┆ 1.0  │
│ 2    ┆ 0.5  │
└──────┴──────┘

log(x: Expr) -> Expr

以e为底的对数

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=log(pl.col('a')),
)
shape: (5, 2)
┌──────┬──────────┐
│ a    ┆ out1     │
│ ---  ┆ ---      │
│ i64  ┆ f64      │
╞══════╪══════════╡
│ null ┆ null     │
│ -1   ┆ NaN      │
│ 0    ┆ -inf     │
│ 1    ┆ 0.0      │
│ 2    ┆ 0.693147 │
└──────┴──────────┘

log10(x: Expr) -> Expr

以10为底的对数

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=log10(pl.col('a')),
)
shape: (5, 2)
┌──────┬─────────┐
│ a    ┆ out1    │
│ ---  ┆ ---     │
│ i64  ┆ f64     │
╞══════╪═════════╡
│ null ┆ null    │
│ -1   ┆ NaN     │
│ 0    ┆ -inf    │
│ 1    ┆ 0.0     │
│ 2    ┆ 0.30103 │
└──────┴─────────┘

log1p(x: Expr) -> Expr

简单收益率 转 对数收益率

convert simple return to log return

log(x+1)

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=log1p(pl.col('a')),
)
shape: (5, 2)
┌──────┬──────────┐
│ a    ┆ out1     │
│ ---  ┆ ---      │
│ i64  ┆ f64      │
╞══════╪══════════╡
│ null ┆ null     │
│ -1   ┆ -inf     │
│ 0    ┆ 0.0      │
│ 1    ┆ 0.693147 │
│ 2    ┆ 1.098612 │
└──────┴──────────┘

log2(x: Expr) -> Expr

以2为底的对数

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=log2(pl.col('a')),
)
shape: (5, 2)
┌──────┬──────┐
│ a    ┆ out1 │
│ ---  ┆ ---  │
│ i64  ┆ f64  │
╞══════╪══════╡
│ null ┆ null │
│ -1   ┆ NaN  │
│ 0    ┆ -inf │
│ 1    ┆ 0.0  │
│ 2    ┆ 1.0  │
└──────┴──────┘

max_(a: Expr, b: Expr, *args) -> Expr

水平多列求最大值

Maximum value of all inputs. At least 2 inputs are required.

mean(a: Expr, b: Expr, *args) -> Expr

水平多列求均值

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
    'b': [None, -1, 0, 0, 2],
}).with_columns(
    out2=mean(pl.col('a'), 2),
    out3=mean(pl.col('a'), pl.col('b')),
)
shape: (5, 4)
┌──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out2 ┆ out3 │
│ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ f64  ┆ f64  │
╞══════╪══════╪══════╪══════╡
│ null ┆ null ┆ 2.0  ┆ null │
│ -1   ┆ -1   ┆ 0.5  ┆ -1.0 │
│ 0    ┆ 0    ┆ 1.0  ┆ 0.0  │
│ 1    ┆ 0    ┆ 1.5  ┆ 0.5  │
│ 2    ┆ 2    ┆ 2.0  ┆ 2.0  │
└──────┴──────┴──────┴──────┘

min_(a: Expr, b: Expr, *args) -> Expr

水平多列求最小值

Maximum value of all inputs. At least 2 inputs are required.

mod(x: Expr, y: Expr) -> Expr

求余

x%y

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
    'b': [None, -1, 0, 0, 2],
}).with_columns(
    out2=mod(pl.col('a'), 2),
    out3=mod(pl.col('a'), pl.col('b')),
)
shape: (5, 4)
┌──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out2 ┆ out3 │
│ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ i64  ┆ i64  │
╞══════╪══════╪══════╪══════╡
│ null ┆ null ┆ null ┆ null │
│ -1   ┆ -1   ┆ 1    ┆ 0    │
│ 0    ┆ 0    ┆ 0    ┆ null │
│ 1    ┆ 0    ┆ 1    ┆ null │
│ 2    ┆ 2    ┆ 0    ┆ 0    │
└──────┴──────┴──────┴──────┘

multiply(a: Expr, b: Expr, *args) -> Expr

水平多列相乘

Multiply all inputs. At least 2 inputs are required.

Examples:

df = pl.DataFrame({
    'a': [None, 2, 3, 4, None],
    'b': [5, None, 3, 2, None],
    'c': [1, 1, None, 1, None],
}).with_columns(
    out=multiply(pl.col('a'), pl.col('b'), pl.col('c'))
)

shape: (5, 4)
┌──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ c    ┆ out  │
│ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ i64  ┆ i64  │
╞══════╪══════╪══════╪══════╡
│ null ┆ 5    ┆ 1    ┆ 5    │
│ 2    ┆ null ┆ 1    ┆ 2    │
│ 3    ┆ 3    ┆ null ┆ 9    │
│ 4    ┆ 2    ┆ 1    ┆ 8    │
│ null ┆ null ┆ null ┆ null │
└──────┴──────┴──────┴──────┘

Notes

null时返回null

power(x: Expr, y: Expr) -> Expr

乘幂

x ** y

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
    'b': [None, -1, 0, 1, 2],
}).with_columns(
    out2=power(pl.col('a'), 1),
    out3=power(pl.col('a'), pl.col('b')),
)
shape: (5, 4)
┌──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out2 ┆ out3 │
│ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ i64  ┆ f64  │
╞══════╪══════╪══════╪══════╡
│ null ┆ null ┆ null ┆ null │
│ -1   ┆ -1   ┆ -1   ┆ -1.0 │
│ 0    ┆ 0    ┆ 0    ┆ 1.0  │
│ 1    ┆ 1    ┆ 1    ┆ 1.0  │
│ 2    ┆ 2    ┆ 2    ┆ 4.0  │
└──────┴──────┴──────┴──────┘
Notes

负数的非整数幂在实数中未定义

radians(x: Expr) -> Expr

角度转弧度

reverse(x: Expr) -> Expr

求相反数

round_(x: Expr, decimals: int = 0) -> Expr

四舍五入

Round input to closest integer.

Parameters:

Name Type Description Default
x Expr
required
decimals int

Number of decimals to round to.

0

Examples:

df = pl.DataFrame({
    'a': [None, 3.5, 4.5, -3.5, -4.5],
}).with_columns(
    out1=round_(pl.col('a'), 0),
    out2=pl.col('a').map_elements(lambda x: round(x, 0), return_dtype=pl.Float64),
)
shape: (5, 3)
┌──────┬──────┬──────┐
│ a    ┆ out1 ┆ out2 │
│ ---  ┆ ---  ┆ ---  │
│ f64  ┆ f64  ┆ f64  │
╞══════╪══════╪══════╡
│ null ┆ null ┆ null │
│ 3.5  ┆ 4.0  ┆ 4.0  │
│ 4.5  ┆ 5.0  ┆ 4.0  │
│ -3.5 ┆ -4.0 ┆ -4.0 │
│ -4.5 ┆ -5.0 ┆ -4.0 │
└──────┴──────┴──────┘
Notes

四舍五入,不是四舍六入五取偶(银行家舍入)

round_down(x: Expr, f: int = 1) -> Expr

小于输入的f的最大倍数

Round input to greatest multiple of f less than input

Parameters:

Name Type Description Default
x Expr
required
f int
1

Examples:

df = pl.DataFrame({
    'a': [None, 3.5, 4.5, -3.5, -4.5],
}).with_columns(
    out=round_down(pl.col('a'), 2),
)
shape: (5, 2)
┌──────┬──────┐
│ a    ┆ out  │
│ ---  ┆ ---  │
│ f64  ┆ f64  │
╞══════╪══════╡
│ null ┆ null │
│ 3.5  ┆ 2.0  │
│ 4.5  ┆ 4.0  │
│ -3.5 ┆ -4.0 │
│ -4.5 ┆ -6.0 │
└──────┴──────┘

s_log_1p(x: Expr) -> Expr

sign(x) * log10(1 + abs(x))

一种结合符号函数和对数变换的复合函数,常用于‌保留数据符号的同时压缩数值范围‌

Examples:

df = pl.DataFrame({
    'a': [None, 9, -9, 99, -99],
}).with_columns(
    out1=s_log_1p(pl.col('a')),
)
shape: (5, 2)
┌──────┬──────┐
│ a    ┆ out1 │
│ ---  ┆ ---  │
│ i64  ┆ f64  │
╞══════╪══════╡
│ null ┆ null │
│ 9    ┆ 1.0  │
│ -9   ┆ -1.0 │
│ 99   ┆ 2.0  │
│ -99  ┆ -2.0 │
└──────┴──────┘

Notes

wq示例可以看出,log的底数是10,而不是e

References

https://platform.worldquantbrain.com/learn/operators/detailed-operator-descriptions#s_log_1px

sign(x: Expr) -> Expr

符号函数

signed_power(x: Expr, y: Expr) -> Expr

x的y次幂,符号保留

x raised to the power of y such that final result preserves sign of x.

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
    'b': [None, -1, 0, 1, 2],
}).with_columns(
    out1=signed_power(pl.col('a'), 0),
    out2=signed_power(pl.col('a'), 1),
    out3=signed_power(pl.col('a'), 2),
    out4=signed_power(pl.col('a'), pl.col('b')),
)

shape: (5, 6)
┌──────┬──────┬──────┬──────┬──────┬──────┐
│ a    ┆ b    ┆ out1 ┆ out2 ┆ out3 ┆ out4 │
│ ---  ┆ ---  ┆ ---  ┆ ---  ┆ ---  ┆ ---  │
│ i64  ┆ i64  ┆ i64  ┆ i64  ┆ i64  ┆ f64  │
╞══════╪══════╪══════╪══════╪══════╪══════╡
│ null ┆ null ┆ null ┆ null ┆ null ┆ null │
│ -1   ┆ -1   ┆ -1   ┆ -1   ┆ -1   ┆ -1.0 │
│ 0    ┆ 0    ┆ 0    ┆ 0    ┆ 0    ┆ 0.0  │
│ 1    ┆ 1    ┆ 1    ┆ 1    ┆ 1    ┆ 1.0  │
│ 2    ┆ 2    ┆ 1    ┆ 2    ┆ 4    ┆ 4.0  │
└──────┴──────┴──────┴──────┴──────┴──────┘
References

https://platform.worldquantbrain.com/learn/operators/detailed-operator-descriptions#signed_powerx-y

sin(x: Expr) -> Expr

正弦

sinh(x: Expr) -> Expr

双曲正弦

softsign(x: Expr) -> Expr

softsign激活函数

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=softsign(pl.col('a')),
)

shape: (5, 2)
┌──────┬──────────┐
│ a    ┆ out1     │
│ ---  ┆ ---      │
│ i64  ┆ f64      │
╞══════╪══════════╡
│ null ┆ null     │
│ -1   ┆ -0.5     │
│ 0    ┆ 0.0      │
│ 1    ┆ 0.5      │
│ 2    ┆ 0.666667 │
└──────┴──────────┘

sqrt(x: Expr) -> Expr

平方根

square(x: Expr) -> Expr

平方

std(a: Expr, b: Expr, *args) -> Expr

水平多列求标准差

Examples:

df = pl.DataFrame({
    'a': [None, -1, 1, 1, 2],
    'b': [None, -1, 0, 1, 2],
    'c': [None, -1, 0, 2, None],
}).with_columns(
    out2=std(pl.col('a'), pl.col('b'), pl.col('c')),
)

shape: (5, 4)
┌──────┬──────┬──────┬──────────┐
│ a    ┆ b    ┆ c    ┆ out2     │
│ ---  ┆ ---  ┆ ---  ┆ ---      │
│ i64  ┆ i64  ┆ i64  ┆ f64      │
╞══════╪══════╪══════╪══════════╡
│ null ┆ null ┆ null ┆ 0.0      │
│ -1   ┆ -1   ┆ -1   ┆ 0.0      │
│ 1    ┆ 0    ┆ 0    ┆ 0.816497 │
│ 1    ┆ 1    ┆ 2    ┆ 0.816497 │
│ 2    ┆ 2    ┆ null ┆ 0.0      │
└──────┴──────┴──────┴──────────┘

subtract(x: Expr, y: Expr) -> Expr

减法

x-y

tan(x: Expr) -> Expr

正切

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=tan(pl.col('a')),
)

shape: (5, 2)
┌──────┬───────────┐
│ a    ┆ out1      │
│ ---  ┆ ---       │
│ i64  ┆ f64       │
╞══════╪═══════════╡
│ null ┆ null      │
│ -1   ┆ -1.557408 │
│ 0    ┆ 0.0       │
│ 1    ┆ 1.557408  │
│ 2    ┆ -2.18504  │
└──────┴───────────┘

tanh(x: Expr) -> Expr

双曲正切

Examples:

df = pl.DataFrame({
    'a': [None, -1, 0, 1, 2],
}).with_columns(
    out1=tanh(pl.col('a')),
)

shape: (5, 2)
┌──────┬───────────┐
│ a    ┆ out1      │
│ ---  ┆ ---       │
│ i64  ┆ f64       │
╞══════╪═══════════╡
│ null ┆ null      │
│ -1   ┆ -0.761594 │
│ 0    ┆ 0.0       │
│ 1    ┆ 0.761594  │
│ 2    ┆ 0.964028  │
└──────┴───────────┘

var(a: Expr, b: Expr, *args) -> Expr

水平多列求方差

Examples:

df = pl.DataFrame({
    'a': [None, -1, 1, 1, 2],
    'b': [None, -1, 0, 1, 2],
    'c': [None, -1, 0, 2, None],
}).with_columns(
    out1=var(pl.col('a'), pl.col('b'), pl.col('c')),
)

shape: (5, 4)
┌──────┬──────┬──────┬──────────┐
│ a    ┆ b    ┆ c    ┆ out1     │
│ ---  ┆ ---  ┆ ---  ┆ ---      │
│ i64  ┆ i64  ┆ i64  ┆ f64      │
╞══════╪══════╪══════╪══════════╡
│ null ┆ null ┆ null ┆ 0.0      │
│ -1   ┆ -1   ┆ -1   ┆ 0.0      │
│ 1    ┆ 0    ┆ 0    ┆ 0.666667 │
│ 1    ┆ 1    ┆ 2    ┆ 0.666667 │
│ 2    ┆ 2    ┆ null ┆ 0.0      │
└──────┴──────┴──────┴──────────┘