模式
Polars DataFrame 或 LazyFrame 的模式列出了列的名称及其数据类型。您可以使用 DataFrame 或 LazyFrame 上的 .collect_schema 方法来查看模式。
lf = pl.LazyFrame({"foo": ["a", "b", "c"], "bar": [0, 1, 2]})
print(lf.collect_schema())
Schema({'foo': String, 'bar': Int64})
模式在惰性API中扮演着重要角色。
惰性API中的类型检查
惰性API的一个优势是,Polars会在处理任何数据之前检查模式。 这个检查在你执行惰性查询时发生。
我们通过以下简单示例来了解其工作原理,其中我们在字符串列 foo 上调用了 .round 表达式。
lf = pl.LazyFrame({"foo": ["a", "b", "c"]}).with_columns(pl.col("foo").round(2))
.round 表达式仅对具有数值数据类型的列有效。在字符串列上调用 .round 意味着当我们使用 collect 评估查询时,操作将引发 InvalidOperationError。当我们调用 collect 时,此模式检查会在数据处理之前进行。
try:
print(lf.collect())
except Exception as e:
print(f"{type(e).__name__}: {e}")
InvalidOperationError: round can only be used on numeric types
如果我们在急切模式下执行此查询,错误只有在所有早期步骤中的数据被处理完毕后才会被发现。
当我们执行一个惰性查询时,Polars 在实际处理管道中的数据之前,会检查是否有任何潜在的 InvalidOperationError。
懒人API必须知道模式
在惰性API中,Polars查询优化器必须能够推断查询计划每一步的模式。这意味着无法预先知道模式的操作不能与惰性API一起使用。
一个典型的操作示例,其中模式无法提前知道的是.pivot操作。在.pivot中,新的列名来自其中一列的数据。由于这些列名无法提前知道,因此在惰性API中无法使用.pivot。
处理在惰性API中不可用的操作
如果你的管道包含一个在惰性API中不可用的操作,通常最好:
- 在惰性模式下运行管道直到该点
- 使用
.collect执行管道以具体化一个DataFrame - 对
DataFrame执行非惰性操作 - 将输出转换回
LazyFrame,使用.lazy并继续在惰性模式下操作
我们在这个示例中展示了如何处理非惰性操作,其中我们:
- 创建一个简单的
DataFrame - 使用
.lazy将其转换为LazyFrame - 使用
.with_columns进行转换 - 在执行透视之前使用
.collect来获取一个DataFrame - 在
DataFrame上执行.pivot - 在惰性模式下转换回来
- 执行一个
.filter - 通过使用
.collect执行查询来完成,以获取一个DataFrame
collect · lazy · pivot · filter
lazy_eager_query = (
pl.LazyFrame(
{
"id": ["a", "b", "c"],
"month": ["jan", "feb", "mar"],
"values": [0, 1, 2],
}
)
.with_columns((2 * pl.col("values")).alias("double_values"))
.collect()
.pivot(index="id", on="month", values="double_values", aggregate_function="first")
.lazy()
.filter(pl.col("mar").is_null())
.collect()
)
print(lazy_eager_query)
shape: (2, 4)
┌─────┬──────┬──────┬──────┐
│ id ┆ jan ┆ feb ┆ mar │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 ┆ i64 │
╞═════╪══════╪══════╪══════╡
│ a ┆ 0 ┆ null ┆ null │
│ b ┆ null ┆ 2 ┆ null │
└─────┴──────┴──────┴──────┘