10分钟掌握Nushell中Polars表达式逻辑运算的增强实现
【免费下载链接】nushell A new type of shell 项目地址: https://gitcode.com/GitHub_Trending/nu/nushell
作为数据处理工程师,你是否经常面临复杂条件判断的困扰?当你需要在Nushell中处理布尔逻辑时,是否觉得现有工具不够直观?本文将带你深入了解Nushell中Polars表达式逻辑运算的增强实现,让你轻松应对各种复杂的条件判断场景。
1. 背景介绍
Nushell(简称Nu)是一种新型的Shell,它将现代编程语言的特性与传统Shell的交互性相结合,提供了强大的数据处理能力。Polars是一个快速的DataFrame库,它允许你使用类似SQL的语法来操作数据。在Nushell中,通过Polars插件,我们可以利用Polars的强大功能来处理数据。
1.1 Polars插件架构
Polars插件的核心是PolarsPlugin结构体,它实现了Nushell的插件接口。该结构体包含缓存、运行时等重要组件,为逻辑运算提供了基础支持。
pub struct PolarsPlugin {
pub(crate) cache: Cache,
/// For testing purposes only
pub(crate) disable_cache_drop: bool,
pub(crate) runtime: Runtime,
}
1.2 布尔命令模块
Polars插件的布尔命令模块位于crates/nu_plugin_polars/src/dataframe/command/boolean/mod.rs,它定义了一系列布尔运算相关的命令:
pub(crate) fn boolean_commands() -> Vec<Box<dyn PluginCommand<Plugin = PolarsPlugin>>> {
vec![
Box::new(AllFalse),
Box::new(all_true::AllTrue),
Box::new(ArgTrue),
Box::new(ExprIsIn),
Box::new(ExprOtherwise),
Box::new(ExprWhen),
Box::new(expr_not::ExprNot),
Box::new(IsDuplicated),
Box::new(IsNotNull),
Box::new(IsNull),
Box::new(IsUnique),
Box::new(NotSeries),
Box::new(SetSeries),
]
}
2. 核心逻辑运算实现
2.1 非运算(NOT)
非运算是最基本的逻辑运算之一,在Polars插件中有两种实现方式:针对Series的NotSeries和针对表达式的ExprNot。
2.1.1 Series非运算
NotSeries命令用于对布尔类型的Series进行非运算,其实现位于crates/nu_plugin_polars/src/dataframe/command/boolean/not.rs:
fn command(
plugin: &PolarsPlugin,
engine: &EngineInterface,
call: &EvaluatedCall,
df: NuDataFrame,
) -> Result<PipelineData, ShellError> {
let series = df.as_series(call.head)?;
let bool = series.bool().map_err(|e| ShellError::GenericError {
error: "Error inverting mask".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = bool.not();
let df = NuDataFrame::try_from_series_vec(vec![res.into_series()], call.head)?;
df.to_pipeline_data(plugin, engine, call.head)
}
使用示例:
[true false true] | polars into-df | polars not
该命令会将输入的布尔DataFrame取反,结果为[false true false]。
2.1.2 表达式非运算
ExprNot命令用于对表达式进行非运算,其实现位于crates/nu_plugin_polars/src/dataframe/command/boolean/expr_not.rs:
fn command_expr(
plugin: &PolarsPlugin,
engine: &EngineInterface,
call: &EvaluatedCall,
expr: NuExpression,
) -> Result<PipelineData, ShellError> {
NuExpression::from(expr.into_polars().not()).to_pipeline_data(plugin, engine, call.head)
}
使用示例:
[[a]; [1] [2] [3] [4] [5]] | polars into-df
| polars with-column [(((polars col a) > 2)
| polars expr-not
| polars as a_expr_not)]
| polars collect
| polars sort-by a
该示例会添加一列a_expr_not,其值为a > 2的非运算结果。
2.2 条件表达式(WHEN/OTHERWISE)
Polars插件还提供了类似SQL中的CASE WHEN语法的条件表达式,通过ExprWhen和ExprOtherwise命令实现,位于crates/nu_plugin_polars/src/dataframe/command/boolean/when.rs和crates/nu_plugin_polars/src/dataframe/command/boolean/otherwise.rs。
使用示例:
[[a]; [1] [2] [3] [4] [5]] | polars into-df
| polars with-column [
(polars when ((polars col a) > 3)
| polars then (polars lit "large")
| polars otherwise (polars lit "small")
| polars as size)
]
| polars collect
该示例会根据a的值是否大于3,添加一列size,值为"large"或"small"。
3. 高级应用场景
3.1 复杂条件过滤
结合Polars的逻辑运算和过滤功能,可以实现复杂的条件过滤:
[[name age score];
["Alice" 25 85]
["Bob" 30 75]
["Charlie" 35 90]
["David" 28 60]] | polars into-df
| polars filter ((polars col age) > 28) and ((polars col score) > 70)
| polars select name
该命令会筛选出年龄大于28且分数大于70的人的姓名。
3.2 条件列赋值
使用逻辑运算和with-column命令,可以实现基于条件的列赋值:
[[a b]; [1 10] [2 20] [3 30] [4 40]] | polars into-df
| polars with-column [
(polars when ((polars col a) % 2 == 0)
| polars then ((polars col b) * 2)
| polars otherwise ((polars col b) / 2)
| polars as c)
]
| polars collect
该示例会根据a是否为偶数,将b的值乘以2或除以2,结果存入新列c。
4. 性能优化与缓存机制
Polars插件还实现了缓存机制,用于优化重复计算的性能。PolarsPlugin结构体中的cache字段用于存储中间结果:
pub struct PolarsPlugin {
pub(crate) cache: Cache,
/// For testing purposes only
pub(crate) disable_cache_drop: bool,
pub(crate) runtime: Runtime,
}
在测试中,我们可以看到缓存的使用:
pub fn test_polars_plugin_command_with_decls(
command: &impl PluginCommand,
decls: Vec<Box<dyn Command>>,
) -> Result<(), ShellError> {
let plugin = PolarsPlugin::new_test_mode()?;
let examples = command.examples();
// we need to cache values in the examples
for example in &examples {
if let Some(ref result) = example.result {
// if it's a polars plugin object, try to cache it
if let Ok(obj) = PolarsPluginObject::try_from_value(&plugin, result) {
let id = obj.id();
plugin
.cache
.insert(TestEngineWrapper {}, id, obj, Span::test_data())
.unwrap();
}
}
}
// ...
}
5. 总结与展望
Nushell中的Polars插件通过PolarsPlugin结构体和一系列布尔命令,提供了强大的逻辑运算能力。我们可以通过polars not等命令对数据进行逻辑操作,也可以使用polars when和polars otherwise构建复杂的条件表达式。
未来,Polars插件可能会进一步增强逻辑运算功能,例如添加对AND、OR等组合逻辑运算的直接支持,以及更复杂的模式匹配功能。
通过掌握这些增强的逻辑运算功能,你可以在Nushell中更高效地处理复杂的数据筛选和转换任务,提升数据处理的效率和可读性。
6. 参考资料
- Polars插件核心实现:crates/nu_plugin_polars/src/lib.rs
- 布尔命令模块:crates/nu_plugin_polars/src/dataframe/command/boolean/mod.rs
- 非运算实现:crates/nu_plugin_polars/src/dataframe/command/boolean/not.rs
- 表达式非运算实现:crates/nu_plugin_polars/src/dataframe/command/boolean/expr_not.rs
【免费下载链接】nushell A new type of shell 项目地址: https://gitcode.com/GitHub_Trending/nu/nushell
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



