Skip to content

版本 1

重大变更

正确应用Series构造函数中的strict参数

Series构造函数的行为已更新。通常情况下,它将更加严格,除非用户传递strict=False

严格构造比非严格构造更高效,因此为了获得最佳性能,请确保将相同数据类型的值传递给构造函数。

示例

之前:

>>> s = pl.Series([1, 2, 3.5])
shape: (3,)
Series: '' [f64]
[
        1.0
        2.0
        3.5
]
>>> s = pl.Series([1, 2, 3.5], strict=False)
shape: (3,)
Series: '' [i64]
[
        1
        2
        null
]
>>> s = pl.Series([1, 2, 3.5], strict=False, dtype=pl.Int8)
Series: '' [i8]
[
        1
        2
        null
]

之后:

>>> s = pl.Series([1, 2, 3.5])
Traceback (most recent call last):
...
TypeError: unexpected value while building Series of type Int64; found value of type Float64: 3.5

Hint: Try setting `strict=False` to allow passing data with mixed types.
>>> s = pl.Series([1, 2, 3.5], strict=False)
shape: (3,)
Series: '' [f64]
[
        1.0
        2.0
        3.5
]
>>> s = pl.Series([1, 2, 3.5], strict=False, dtype=pl.Int8)
Series: '' [i8]
[
        1
        2
        3
]

更改数据方向推断逻辑以构建DataFrame

Polars 不再通过检查数据类型来推断传递给 DataFrame 构造函数的数据方向。数据方向是根据数据和模式维度推断的。

此外,每当推断出行方向时都会发出警告。由于一些令人困惑的边缘情况,用户应传递orient="row"以明确其输入是基于行的。

示例

之前:

>>> data = [[1, "a"], [2, "b"]]
>>> pl.DataFrame(data)
shape: (2, 2)
┌──────────┬──────────┐
│ column_0 ┆ column_1 │
│ ---      ┆ ---      │
│ i64      ┆ str      │
╞══════════╪══════════╡
│ 1        ┆ a        │
│ 2        ┆ b        │
└──────────┴──────────┘

之后:

>>> pl.DataFrame(data)
Traceback (most recent call last):
...
TypeError: unexpected value while building Series of type Int64; found value of type String: "a"

Hint: Try setting `strict=False` to allow passing data with mixed types.

请改用:

>>> pl.DataFrame(data, orient="row")
shape: (2, 2)
┌──────────┬──────────┐
│ column_0 ┆ column_1 │
│ ---      ┆ ---      │
│ i64      ┆ str      │
╞══════════╪══════════╡
│ 1        ┆ a        │
│ 2        ┆ b        │
└──────────┴──────────┘

在Series构造函数中一致地转换为给定时区

危险

此更改可能会默默地影响您的管道结果。 如果您处理时区,请确保考虑到此更改。

在Series和DataFrame构造函数中处理时区信息的方式不一致。 按行构造会转换为给定的时区,而按列构造会替换时区。通过始终转换为数据类型中指定的时区,这种不一致性已得到修复。

示例

之前:

>>> from datetime import datetime
>>> pl.Series([datetime(2020, 1, 1)], dtype=pl.Datetime('us', 'Europe/Amsterdam'))
shape: (1,)
Series: '' [datetime[μs, Europe/Amsterdam]]
[
        2020-01-01 00:00:00 CET
]

之后:

>>> from datetime import datetime
>>> pl.Series([datetime(2020, 1, 1)], dtype=pl.Datetime('us', 'Europe/Amsterdam'))
shape: (1,)
Series: '' [datetime[μs, Europe/Amsterdam]]
[
        2020-01-01 01:00:00 CET
]

更新一些错误类型为更合适的变体

我们更新了许多错误类型,以更准确地表示问题。最常见的是,ComputeError 类型被更改为 InvalidOperationErrorSchemaError

示例

之前:

>>> s = pl.Series("a", [100, 200, 300])
>>> s.cast(pl.UInt8)
Traceback (most recent call last):
...
polars.exceptions.ComputeError: conversion from `i64` to `u8` failed in column 'a' for 1 out of 3 values: [300]

之后:

>>> s.cast(pl.UInt8)
Traceback (most recent call last):
...
polars.exceptions.InvalidOperationError: conversion from `i64` to `u8` failed in column 'a' for 1 out of 3 values: [300]

更新 read/scan_parquet 以默认禁用文件输入的 Hive 分区

Parquet 读取函数现在也支持目录输入。对于目录,Hive 分区默认启用,但对于文件输入,现在默认禁用。文件输入包括单个文件、通配符和文件列表。显式传递 hive_partitioning=True 以恢复之前的行为。

示例

之前:

>>> pl.read_parquet("dataset/a=1/foo.parquet")
shape: (2, 2)
┌─────┬─────┐
│ a   ┆ x   │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞═════╪═════╡
│ 1   ┆ 1.0 │
│ 1   ┆ 2.0 │
└─────┴─────┘

之后:

>>> pl.read_parquet("dataset/a=1/foo.parquet")
shape: (2, 1)
┌─────┐
│ x   │
│ --- │
│ f64 │
╞═════╡
│ 1.0 │
│ 2.0 │
└─────┘
>>> pl.read_parquet("dataset/a=1/foo.parquet", hive_partitioning=True)
shape: (2, 2)
┌─────┬─────┐
│ a   ┆ x   │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞═════╪═════╡
│ 1   ┆ 1.0 │
│ 1   ┆ 2.0 │
└─────┴─────┘

更新 reshape 以返回数组类型而不是列表类型

reshape 现在返回一个 Array 类型而不是 List 类型。

用户可以通过在输出上调用.arr.to_list()来恢复旧功能。请注意,这并不比直接创建List类型更昂贵,因为重塑为数组基本上是免费的。

示例

之前:

>>> s = pl.Series([1, 2, 3, 4, 5, 6])
>>> s.reshape((2, 3))
shape: (2,)
Series: '' [list[i64]]
[
        [1, 2, 3]
        [4, 5, 6]
]

之后:

>>> s.reshape((2, 3))
shape: (2,)
Series: '' [array[i64, 3]]
[
        [1, 2, 3]
        [4, 5, 6]
]

将2D NumPy数组读取为Array类型而不是List

Series 构造函数现在将 2D NumPy 数组解析为 Array 类型,而不是 List 类型。

示例

之前:

>>> import numpy as np
>>> arr = np.array([[1, 2], [3, 4]])
>>> pl.Series(arr)
shape: (2,)
Series: '' [list[i64]]
[
        [1, 2]
        [3, 4]
]

之后:

>>> import numpy as np
>>> arr = np.array([[1, 2], [3, 4]])
>>> pl.Series(arr)
shape: (2,)
Series: '' [array[i64, 2]]
[
        [1, 2]
        [3, 4]
]

replace功能拆分为两个独立的方法

许多用户发现replace的API令人困惑,特别是关于default参数和结果数据类型的部分。

它已被拆分为两种方法:replacereplace_strictreplace 现在总是保留 现有的数据类型 (破坏性更改,请参见下面的示例),并且用于替换现有列中的一些值。 它的参数 defaultreturn_dtype 已被弃用。

新方法 replace_strict 用于创建一个新列,映射原始列的部分或全部值,并可以选择指定一个默认值。如果没有提供默认值,当任何非空值未被映射时,它会引发错误。

示例

之前:

>>> s = pl.Series([1, 2, 3])
>>> s.replace(1, "a")
shape: (3,)
Series: '' [str]
[
        "a"
        "2"
        "3"
]

之后:

>>> s.replace(1, "a")
Traceback (most recent call last):
...
polars.exceptions.InvalidOperationError: conversion from `str` to `i64` failed in column 'literal' for 1 out of 1 values: ["a"]
>>> s.replace_strict(1, "a", default=s)
shape: (3,)
Series: '' [str]
[
        "a"
        "2"
        "3"
]

ewm_meanewm_stdewm_var中保留空值

Polars 将不再在 ewm 方法中向前填充空值。用户可以在输出上调用 .forward_fill() 来达到相同的结果。

示例

之前:

>>> s = pl.Series([1, 4, None, 3])
>>> s.ewm_mean(alpha=.9, ignore_nulls=False)
shape: (4,)
Series: '' [f64]
[
        1.0
        3.727273
        3.727273
        3.007913
]

之后:

>>> s.ewm_mean(alpha=.9, ignore_nulls=False)
shape: (4,)
Series: '' [f64]
[
        1.0
        3.727273
        null
        3.007913
]

更新 clip 以不再在给定边界内传播空值

边界中的空值不再将值设置为空 - 相反,保留原始值。

之前

>>> df = pl.DataFrame({"a": [0, 1, 2], "min": [1, None, 1]})
>>> df.select(pl.col("a").clip("min"))
shape: (3, 1)
┌──────┐
│ a    │
│ ---  │
│ i64  │
╞══════╡
│ 1    │
│ null │
│ 2    │
└──────┘

之后

>>> df.select(pl.col("a").clip("min"))
shape: (3, 1)
┌──────┐
│ a    │
│ ---  │
│ i64  │
╞══════╡
│ 1    │
│ 1    │
│ 2    │
└──────┘

str.to_datetime 的默认精度更改为微秒,适用于格式说明符 "%f""%.f"

.str.to_datetime中,当指定%.f作为格式时,默认是将结果数据类型设置为纳秒精度。这已被更改为微秒精度。

示例

之前

>>> s = pl.Series(["2022-08-31 00:00:00.123456789"])
>>> s.str.to_datetime(format="%Y-%m-%d %H:%M:%S%.f")
shape: (1,)
Series: '' [datetime[ns]]
[
        2022-08-31 00:00:00.123456789
]

之后

>>> s.str.to_datetime(format="%Y-%m-%d %H:%M:%S%.f")
shape: (1,)
Series: '' [datetime[us]]
[
        2022-08-31 00:00:00.123456
]

pivot中更新结果列名,当通过多个值进行透视时

DataFrame.pivot中,当指定多个values列时,结果会冗余地包含列名中的column列。此问题已得到解决。

示例

之前:

>>> df = pl.DataFrame(
...     {
...         "name": ["Cady", "Cady", "Karen", "Karen"],
...         "subject": ["maths", "physics", "maths", "physics"],
...         "test_1": [98, 99, 61, 58],
...         "test_2": [100, 100, 60, 60],
...     }
... )
>>> df.pivot(index='name', columns='subject', values=['test_1', 'test_2'])
shape: (2, 5)
┌───────┬──────────────────────┬────────────────────────┬──────────────────────┬────────────────────────┐
 name   test_1_subject_maths  test_1_subject_physics  test_2_subject_maths  test_2_subject_physics 
 ---    ---                   ---                     ---                   ---                    
 str    i64                   i64                     i64                   i64                    
╞═══════╪══════════════════════╪════════════════════════╪══════════════════════╪════════════════════════╡
 Cady   98                    99                      100                   100                    
 Karen  61                    58                      60                    60                     
└───────┴──────────────────────┴────────────────────────┴──────────────────────┴────────────────────────┘

之后:

>>> df = pl.DataFrame(
...     {
...         "name": ["Cady", "Cady", "Karen", "Karen"],
...         "subject": ["maths", "physics", "maths", "physics"],
...         "test_1": [98, 99, 61, 58],
...         "test_2": [100, 100, 60, 60],
...     }
... )
>>> df.pivot('subject', index='name')
┌───────┬──────────────┬────────────────┬──────────────┬────────────────┐
 name   test_1_maths  test_1_physics  test_2_maths  test_2_physics 
 ---    ---           ---             ---           ---            
 str    i64           i64             i64           i64            
╞═══════╪══════════════╪════════════════╪══════════════╪════════════════╡
 Cady   98            99              100           100            
 Karen  61            58              60            60             
└───────┴──────────────┴────────────────┴──────────────┴────────────────┘

请注意,函数签名也已更改:

  • columns 已更名为 on,并且现在是第一个位置参数。
  • indexvalues 都是可选的。如果未指定 index,则将使用未在 onvalues 中指定的所有列。如果未指定 values,则将使用未在 onindex 中指定的所有列。

默认情况下从Arrow转换时支持Decimal类型

更新从Arrow转换时始终将Decimals转换为Polars Decimals,而不是转换为Float64。Config.activate_decimals已被移除。

示例

之前:

>>> from decimal import Decimal as D
>>> import pyarrow as pa
>>> arr = pa.array([D("1.01"), D("2.25")])
>>> pl.from_arrow(arr)
shape: (2,)
Series: '' [f64]
[
        1.01
        2.25
]

之后:

>>> pl.from_arrow(arr)
shape: (2,)
Series: '' [decimal[3,2]]
[
        1.01
        2.25
]

pl.read_jsonDataFrame.write_json 中移除序列化/反序列化功能

pl.read_json 不再支持读取由 DataFrame.serialize 生成的 JSON 文件。用户应改用 pl.DataFrame.deserialize

DataFrame.write_json 现在只写入面向行的 JSON。参数 row_orientedpretty 已被移除。用户应使用 DataFrame.serialize 来序列化 DataFrame。

示例 - write_json

之前:

>>> df = pl.DataFrame({"a": [1, 2], "b": [3.0, 4.0]})
>>> df.write_json()
'{"columns":[{"name":"a","datatype":"Int64","bit_settings":"","values":[1,2]},{"name":"b","datatype":"Float64","bit_settings":"","values":[3.0,4.0]}]}'

之后:

>>> df.write_json()  # Same behavior as previously `df.write_json(row_oriented=True)`
'[{"a":1,"b":3.0},{"a":2,"b":4.0}]'

示例 - read_json

之前:

>>> import io
>>> df_ser = '{"columns":[{"name":"a","datatype":"Int64","bit_settings":"","values":[1,2]},{"name":"b","datatype":"Float64","bit_settings":"","values":[3.0,4.0]}]}'
>>> pl.read_json(io.StringIO(df_ser))
shape: (2, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞═════╪═════╡
│ 1   ┆ 3.0 │
│ 2   ┆ 4.0 │
└─────┴─────┘

之后:

>>> pl.read_json(io.StringIO(df_ser))  # Format no longer supported: data is treated as a single row
shape: (1, 1)
┌─────────────────────────────────┐
│ columns                         │
│ ---                             │
│ list[struct[4]]                 │
╞═════════════════════════════════╡
│ [{"a","Int64","",[1.0, 2.0]}, … │
└─────────────────────────────────┘

请改用:

>>> pl.DataFrame.deserialize(io.StringIO(df_ser))
shape: (2, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞═════╪═════╡
│ 1   ┆ 3.0 │
│ 2   ┆ 4.0 │
└─────┴─────┘

Series.equals 默认不再检查名称

以前,如果Series的名称不匹配,Series.equals会返回False。现在该方法默认不再检查名称。可以通过设置check_names=True来保留以前的行为。

示例

之前:

>>> s1 = pl.Series("foo", [1, 2, 3])
>>> s2 = pl.Series("bar", [1, 2, 3])
>>> s1.equals(s2)
False

之后:

>>> s1.equals(s2)
True
>>> s1.equals(s2, check_names=True)
False

nth 表达式函数中移除 columns 参数

columns 参数已被移除,改为将位置输入视为附加索引。 使用 Expr.get 来获得相同的功能。

示例

之前:

>>> df = pl.DataFrame({"a": [1, 2], "b": [3, 4], "c": [5, 6]})
>>> df.select(pl.nth(1, "a"))
shape: (1, 1)
┌─────┐
│ a   │
│ --- │
│ i64 │
╞═════╡
│ 2   │
└─────┘

之后:

>>> df.select(pl.nth(1, "a"))
...
TypeError: argument 'indices': 'str' object cannot be interpreted as an integer

请改用:

>>> df.select(pl.col("a").get(1))
shape: (1, 1)
┌─────┐
│ a   │
│ --- │
│ i64 │
╞═════╡
│ 2   │
└─────┘

重命名rle输出的结构体字段

rle 方法的结构体字段已从 lengths/values 重命名为 len/value。此外,len 字段的数据类型也已更新以匹配索引类型(以前是 Int32,现在是 UInt32)。

之前

>>> s = pl.Series(["a", "a", "b", "c", "c", "c"])
>>> s.rle().struct.unnest()
shape: (3, 2)
┌─────────┬────────┐
│ lengths ┆ values │
│ ---     ┆ ---    │
│ i32     ┆ str    │
╞═════════╪════════╡
│ 2       ┆ a      │
│ 1       ┆ b      │
│ 3       ┆ c      │
└─────────┴────────┘

之后

>>> s.rle().struct.unnest()
shape: (3, 2)
┌─────┬───────┐
│ len ┆ value │
│ --- ┆ ---   │
│ u32 ┆ str   │
╞═════╪═══════╡
│ 2   ┆ a     │
│ 1   ┆ b     │
│ 3   ┆ c     │
└─────┴───────┘

更新 set_sorted 以仅接受单列

调用set_sorted表示某一列是单独排序的。传递多列表示这些列中的每一列也是单独排序的。然而,许多用户误以为这意味着这些列是作为一个组排序的,这导致了错误的结果。

为了帮助用户避免这个陷阱,我们移除了在set_sorted中指定多列的可能性。要设置多列为已排序,只需多次调用set_sorted

示例

之前:

>>> df = pl.DataFrame({"a": [1, 2, 3], "b": [4.0, 5.0, 6.0], "c": [9, 7, 8]})
>>> df.set_sorted("a", "b")

之后:

>>> df.set_sorted("a", "b")
Traceback (most recent call last):
...
TypeError: DataFrame.set_sorted() takes 2 positional arguments but 3 were given

请改用:

>>> df.set_sorted("a").set_sorted("b")

默认在所有get/gather操作中对越界索引引发异常

默认行为在getgather操作之间不一致。现在所有此类操作默认都会引发异常。传递null_on_oob=True以恢复之前的行为。

示例

之前:

>>> s = pl.Series([[0, 1, 2], [0]])
>>> s.list.get(1)
shape: (2,)
Series: '' [i64]
[
        1
        null
]

之后:

>>> s.list.get(1)
Traceback (most recent call last):
...
polars.exceptions.ComputeError: get index is out of bounds

请改用:

>>> s.list.get(1, null_on_oob=True)
shape: (2,)
Series: '' [i64]
[
        1
        null
]

read_excel的默认引擎更改为"calamine"

calamine引擎(通过fastexcel包提供)最近被添加到Polars中。它比其他引擎快得多,并且已经是xlsbxls文件的默认引擎。我们现在将其设为所有Excel文件的默认引擎。

此引擎与之前的默认引擎(xlsx2csv)之间可能存在细微差异。一个明显的区别是calamine引擎不支持engine_options参数。如果您无法通过calamine引擎获得所需的行为,请指定engine="xlsx2csv"以恢复之前的行为。

示例

之前:

>>> pl.read_excel("data.xlsx", engine_options={"skip_empty_lines": True})

之后:

>>> pl.read_excel("data.xlsx", engine_options={"skip_empty_lines": True})
Traceback (most recent call last):
...
TypeError: read_excel() got an unexpected keyword argument 'skip_empty_lines'

相反,明确指定xlsx2csv引擎或省略engine_options

>>> pl.read_excel("data.xlsx", engine="xlsx2csv", engine_options={"skip_empty_lines": True})

从某些数据类型中移除类变量

一些数据类型类具有类变量。例如,Datetime类具有time_unittime_zone作为类变量。这是不正确的:这些应该是实例变量。现在已经进行了修正。

示例

之前:

>>> dtype = pl.Datetime
>>> dtype.time_unit is None
True

之后:

>>> dtype.time_unit is None
Traceback (most recent call last):
...
AttributeError: type object 'Datetime' has no attribute 'time_unit'

请改用:

>>> getattr(dtype, "time_unit", None) is None
True

group_by_dynamic中的默认offset从“负every”更改为“零”

这会影响group_by_dynamic中第一个窗口的开始。新的行为应该更符合用户的期望。

示例

之前:

>>> from datetime import date
>>> df = pl.DataFrame({
...     "ts": [date(2020, 1, 1), date(2020, 1, 2), date(2020, 1, 3)],
...     "value": [1, 2, 3],
... })
>>> df.group_by_dynamic("ts", every="1d", period="2d").agg("value")
shape: (4, 2)
┌────────────┬───────────┐
│ ts         ┆ value     │
│ ---        ┆ ---       │
│ date       ┆ list[i64] │
╞════════════╪═══════════╡
│ 2019-12-31 ┆ [1]       │
│ 2020-01-01 ┆ [1, 2]    │
│ 2020-01-02 ┆ [2, 3]    │
│ 2020-01-03 ┆ [3]       │
└────────────┴───────────┘

之后:

>>> df.group_by_dynamic("ts", every="1d", period="2d").agg("value")
shape: (3, 2)
┌────────────┬───────────┐
│ ts         ┆ value     │
│ ---        ┆ ---       │
│ date       ┆ list[i64] │
╞════════════╪═══════════╡
│ 2020-01-01 ┆ [1, 2]    │
│ 2020-01-02 ┆ [2, 3]    │
│ 2020-01-03 ┆ [3]       │
└────────────┴───────────┘

更改LazyFrame/DataFrame/Expr的默认序列化格式

对于Polars对象上的serialize/deserialize方法,唯一可用的序列化格式是JSON。我们添加了一个更优化的二进制格式,并将其设为默认格式。通过传递format="json",仍然可以使用JSON序列化。

示例

之前:

>>> lf = pl.LazyFrame({"a": [1, 2, 3]}).sum()
>>> serialized = lf.serialize()
>>> serialized
'{"MapFunction":{"input":{"DataFrameScan":{"df":{"columns":[{"name":...'
>>> from io import StringIO
>>> pl.LazyFrame.deserialize(StringIO(serialized)).collect()
shape: (1, 1)
┌─────┐
│ a   │
│ --- │
│ i64 │
╞═════╡
│ 6   │
└─────┘

之后:

>>> lf = pl.LazyFrame({"a": [1, 2, 3]}).sum()
>>> serialized = lf.serialize()
>>> serialized
b'\xa1kMapFunction\xa2einput\xa1mDataFrameScan\xa4bdf...'
>>> from io import BytesIO  # Note: using BytesIO instead of StringIO
>>> pl.LazyFrame.deserialize(BytesIO(serialized)).collect()
shape: (1, 1)
┌─────┐
│ a   │
│ --- │
│ i64 │
╞═════╡
│ 6   │
└─────┘

限制从DataFrame.sql访问全局变量,优先使用pl.sql

DataFrameLazyFrame 上的 sql 方法不能再访问全局变量。这些方法应该用于对框架本身进行操作。对于全局访问,现在有顶层的 sql 函数。

示例

之前:

>>> df1 = pl.DataFrame({"id1": [1, 2]})
>>> df2 = pl.DataFrame({"id2": [3, 4]})
>>> df1.sql("SELECT * FROM df1 CROSS JOIN df2")
shape: (4, 2)
┌─────┬─────┐
│ id1 ┆ id2 │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 1   ┆ 3   │
│ 1   ┆ 4   │
│ 2   ┆ 3   │
│ 2   ┆ 4   │
└─────┴─────┘

之后:

>>> df1.sql("SELECT * FROM df1 CROSS JOIN df2")
Traceback (most recent call last):
...
polars.exceptions.SQLInterfaceError: relation 'df1' was not found

请改用:

>>> pl.sql("SELECT * FROM df1 CROSS JOIN df2", eager=True)
shape: (4, 2)
┌─────┬─────┐
│ id1 ┆ id2 │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 1   ┆ 3   │
│ 1   ┆ 4   │
│ 2   ┆ 3   │
│ 2   ┆ 4   │
└─────┴─────┘

移除类型别名的重新导出

我们在polars.type_aliases模块中定义了许多类型别名。其中一些在顶层和polars.datatypes模块中重新导出。这些重新导出已被移除。

我们计划在未来添加一个公共的polars.typing模块,其中包含一系列精选的类型别名。在此之前,请定义您自己的类型别名,或从我们的polars.type_aliases模块中导入。请注意,type_aliases模块在技术上并不是公开的,因此使用时需自行承担风险。

示例

之前:

def foo(dtype: pl.PolarsDataType) -> None: ...

之后:

PolarsDataType = pl.DataType | type[pl.DataType]

def foo(dtype: PolarsDataType) -> None: ...

pyproject.toml中简化可选依赖定义

我们重新审视了可选的依赖定义,并做了一些小的更改。如果您正在使用 附加项 fastexcel, gevent, matplotlib, 或 async,这是一个破坏性更改。请更新 您的 Polars 安装以使用新的附加项。

示例

之前:

pip install 'polars[fastexcel,gevent,matplotlib]'

之后:

pip install 'polars[calamine,async,graph]'

弃用

当使用 LazyFrame 属性 schema/dtypes/columns/width 时发出 PerformanceWarning

最近对惰性引擎中模式解析正确性的改进对解析模式的成本产生了显著的性能影响。它不再是“免费”的——事实上,在具有惰性文件读取的复杂管道中,解析模式可能相对昂贵。

因此,LazyFrame上与模式相关的属性不再是一个好的API设计。 属性代表已经可用的信息,只需要检索即可。然而, 对于LazyFrame的属性,访问这些属性可能会带来显著的性能成本。

为了解决这个问题,我们添加了LazyFrame.collect_schema方法,该方法检索模式并返回一个Schema对象。这些属性会引发PerformanceWarning并告诉用户使用collect_schema代替。我们选择暂时不弃用这些属性,以便于编写适用于DataFrames和LazyFrames的通用代码。