10分钟掌握Nushell中Polars表达式逻辑运算的增强实现

10分钟掌握Nushell中Polars表达式逻辑运算的增强实现

【免费下载链接】nushell A new type of shell 【免费下载链接】nushell 项目地址: 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语法的条件表达式,通过ExprWhenExprOtherwise命令实现,位于crates/nu_plugin_polars/src/dataframe/command/boolean/when.rscrates/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 whenpolars otherwise构建复杂的条件表达式。

未来,Polars插件可能会进一步增强逻辑运算功能,例如添加对ANDOR等组合逻辑运算的直接支持,以及更复杂的模式匹配功能。

通过掌握这些增强的逻辑运算功能,你可以在Nushell中更高效地处理复杂的数据筛选和转换任务,提升数据处理的效率和可读性。

6. 参考资料

【免费下载链接】nushell A new type of shell 【免费下载链接】nushell 项目地址: https://gitcode.com/GitHub_Trending/nu/nushell

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值