forked from extern/nushell
Lazy dataframes (#5687)
* change between lazy and eager * when expressions * examples for aggregations * more examples for agg * examples for dataframes * checked examples * cargo fmt
This commit is contained in:
parent
0769e9b750
commit
997d56a288
@ -29,11 +29,12 @@ impl Command for FilterWith {
|
|||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"boolean mask used to filter data",
|
"boolean mask used to filter data",
|
||||||
)
|
)
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![
|
||||||
|
Example {
|
||||||
description: "Filter dataframe using a bool mask",
|
description: "Filter dataframe using a bool mask",
|
||||||
example: r#"let mask = ([true false] | dfr to-df);
|
example: r#"let mask = ([true false] | dfr to-df);
|
||||||
[[a b]; [1 2] [3 4]] | dfr to-df | dfr filter-with $mask"#,
|
[[a b]; [1 2] [3 4]] | dfr to-df | dfr filter-with $mask"#,
|
||||||
@ -45,7 +46,20 @@ impl Command for FilterWith {
|
|||||||
.expect("simple df for test should not fail")
|
.expect("simple df for test should not fail")
|
||||||
.into_value(Span::test_data()),
|
.into_value(Span::test_data()),
|
||||||
),
|
),
|
||||||
}]
|
},
|
||||||
|
Example {
|
||||||
|
description: "Filter dataframe using an expression",
|
||||||
|
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr filter-with ((dfr col a) > 1)",
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_int(3)]),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_int(4)]),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -81,8 +95,18 @@ fn command_eager(
|
|||||||
df: NuDataFrame,
|
df: NuDataFrame,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let mask_value: Value = call.req(engine_state, stack, 0)?;
|
let mask_value: Value = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let mask_span = mask_value.span()?;
|
let mask_span = mask_value.span()?;
|
||||||
|
|
||||||
|
if NuExpression::can_downcast(&mask_value) {
|
||||||
|
let expression = NuExpression::try_from_value(mask_value)?;
|
||||||
|
let lazy = NuLazyFrame::new(true, df.lazy());
|
||||||
|
let lazy = lazy.apply_with_expr(expression, LazyFrame::filter);
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(
|
||||||
|
NuLazyFrame::into_value(lazy, call.head)?,
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?;
|
let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?;
|
||||||
let mask = mask.bool().map_err(|e| {
|
let mask = mask.bool().map_err(|e| {
|
||||||
ShellError::GenericError(
|
ShellError::GenericError(
|
||||||
@ -98,7 +122,7 @@ fn command_eager(
|
|||||||
.filter(mask)
|
.filter(mask)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
ShellError::GenericError(
|
ShellError::GenericError(
|
||||||
"Error calculating dummies".into(),
|
"Error filtering dataframe".into(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
Some(call.head),
|
Some(call.head),
|
||||||
Some("The only allowed column types for dummies are String or Int".into()),
|
Some("The only allowed column types for dummies are String or Int".into()),
|
||||||
@ -107,6 +131,7 @@ fn command_eager(
|
|||||||
})
|
})
|
||||||
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
|
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn command_lazy(
|
fn command_lazy(
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
@ -120,7 +145,7 @@ fn command_lazy(
|
|||||||
let lazy = lazy.apply_with_expr(expr, LazyFrame::filter);
|
let lazy = lazy.apply_with_expr(expr, LazyFrame::filter);
|
||||||
|
|
||||||
Ok(PipelineData::Value(
|
Ok(PipelineData::Value(
|
||||||
NuLazyFrame::into_value(lazy, call.head),
|
NuLazyFrame::into_value(lazy, call.head)?,
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -129,9 +154,10 @@ fn command_lazy(
|
|||||||
mod test {
|
mod test {
|
||||||
use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::ExprCol;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
test_dataframe(vec![Box::new(FilterWith {})])
|
test_dataframe(vec![Box::new(FilterWith {}), Box::new(ExprCol {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ impl Command for FirstDF {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.optional("rows", SyntaxShape::Int, "Number of rows for head")
|
.optional("rows", SyntaxShape::Int, "Number of rows for head")
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -22,7 +22,7 @@ impl Command for LastDF {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.optional("rows", SyntaxShape::Int, "Number of rows for tail")
|
.optional("rows", SyntaxShape::Int, "Number of rows for tail")
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -18,7 +18,6 @@ mod rename;
|
|||||||
mod sample;
|
mod sample;
|
||||||
mod shape;
|
mod shape;
|
||||||
mod slice;
|
mod slice;
|
||||||
mod sort;
|
|
||||||
mod take;
|
mod take;
|
||||||
mod to_csv;
|
mod to_csv;
|
||||||
mod to_df;
|
mod to_df;
|
||||||
@ -48,7 +47,6 @@ pub use rename::RenameDF;
|
|||||||
pub use sample::SampleDF;
|
pub use sample::SampleDF;
|
||||||
pub use shape::ShapeDF;
|
pub use shape::ShapeDF;
|
||||||
pub use slice::SliceDF;
|
pub use slice::SliceDF;
|
||||||
pub use sort::SortDF;
|
|
||||||
pub use take::TakeDF;
|
pub use take::TakeDF;
|
||||||
pub use to_csv::ToCSV;
|
pub use to_csv::ToCSV;
|
||||||
pub use to_df::ToDataFrame;
|
pub use to_df::ToDataFrame;
|
||||||
@ -88,7 +86,6 @@ pub fn add_eager_decls(working_set: &mut StateWorkingSet) {
|
|||||||
SampleDF,
|
SampleDF,
|
||||||
ShapeDF,
|
ShapeDF,
|
||||||
SliceDF,
|
SliceDF,
|
||||||
SortDF,
|
|
||||||
TakeDF,
|
TakeDF,
|
||||||
ToCSV,
|
ToCSV,
|
||||||
ToDataFrame,
|
ToDataFrame,
|
||||||
|
@ -14,7 +14,7 @@ pub struct RenameDF;
|
|||||||
|
|
||||||
impl Command for RenameDF {
|
impl Command for RenameDF {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"dfr rename-col"
|
"dfr rename"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -33,13 +33,31 @@ impl Command for RenameDF {
|
|||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"New names for the selected column(s). A string or list of strings",
|
"New names for the selected column(s). A string or list of strings",
|
||||||
)
|
)
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Renames a series",
|
||||||
|
example: "[5 6 7 8] | dfr to-df | dfr rename '0' new_name",
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![Column::new(
|
||||||
|
"new_name".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(5),
|
||||||
|
Value::test_int(6),
|
||||||
|
Value::test_int(7),
|
||||||
|
Value::test_int(8),
|
||||||
|
],
|
||||||
|
)])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
description: "Renames a dataframe column",
|
description: "Renames a dataframe column",
|
||||||
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr rename-col a a_new",
|
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr rename a a_new",
|
||||||
result: Some(
|
result: Some(
|
||||||
NuDataFrame::try_from_columns(vec![
|
NuDataFrame::try_from_columns(vec![
|
||||||
Column::new(
|
Column::new(
|
||||||
@ -54,7 +72,26 @@ impl Command for RenameDF {
|
|||||||
.expect("simple df for test should not fail")
|
.expect("simple df for test should not fail")
|
||||||
.into_value(Span::test_data()),
|
.into_value(Span::test_data()),
|
||||||
),
|
),
|
||||||
}]
|
},
|
||||||
|
Example {
|
||||||
|
description: "Renames two dataframe columns",
|
||||||
|
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr rename [a b] [a_new b_new]",
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a_new".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(3)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_new".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -133,7 +170,7 @@ fn command_lazy(
|
|||||||
let lazy = lazy.into_polars();
|
let lazy = lazy.into_polars();
|
||||||
let lazy: NuLazyFrame = lazy.rename(&columns, &new_names).into();
|
let lazy: NuLazyFrame = lazy.rename(&columns, &new_names).into();
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,148 +0,0 @@
|
|||||||
use nu_engine::CallExt;
|
|
||||||
use nu_protocol::{
|
|
||||||
ast::Call,
|
|
||||||
engine::{Command, EngineState, Stack},
|
|
||||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::dataframe::values::{utils::convert_columns_string, Column};
|
|
||||||
|
|
||||||
use super::super::values::NuDataFrame;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct SortDF;
|
|
||||||
|
|
||||||
impl Command for SortDF {
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
"dfr sort"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
|
||||||
"Creates new sorted dataframe or series"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
|
||||||
Signature::build(self.name())
|
|
||||||
.switch("reverse", "invert sort", Some('r'))
|
|
||||||
.rest("rest", SyntaxShape::Any, "column names to sort dataframe")
|
|
||||||
.category(Category::Custom("dataframe".into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
|
||||||
vec![
|
|
||||||
Example {
|
|
||||||
description: "Create new sorted dataframe",
|
|
||||||
example: "[[a b]; [3 4] [1 2]] | dfr to-df | dfr sort a",
|
|
||||||
result: Some(
|
|
||||||
NuDataFrame::try_from_columns(vec![
|
|
||||||
Column::new(
|
|
||||||
"a".to_string(),
|
|
||||||
vec![Value::test_int(1), Value::test_int(3)],
|
|
||||||
),
|
|
||||||
Column::new(
|
|
||||||
"b".to_string(),
|
|
||||||
vec![Value::test_int(2), Value::test_int(4)],
|
|
||||||
),
|
|
||||||
])
|
|
||||||
.expect("simple df for test should not fail")
|
|
||||||
.into_value(Span::test_data()),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
Example {
|
|
||||||
description: "Create new sorted series",
|
|
||||||
example: "[3 4 1 2] | dfr to-df | dfr sort",
|
|
||||||
result: Some(
|
|
||||||
NuDataFrame::try_from_columns(vec![Column::new(
|
|
||||||
"0".to_string(),
|
|
||||||
vec![
|
|
||||||
Value::test_int(1),
|
|
||||||
Value::test_int(2),
|
|
||||||
Value::test_int(3),
|
|
||||||
Value::test_int(4),
|
|
||||||
],
|
|
||||||
)])
|
|
||||||
.expect("simple df for test should not fail")
|
|
||||||
.into_value(Span::test_data()),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(
|
|
||||||
&self,
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
call: &Call,
|
|
||||||
input: PipelineData,
|
|
||||||
) -> Result<PipelineData, ShellError> {
|
|
||||||
command(engine_state, stack, call, input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command(
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
call: &Call,
|
|
||||||
input: PipelineData,
|
|
||||||
) -> Result<PipelineData, ShellError> {
|
|
||||||
let reverse = call.has_flag("reverse");
|
|
||||||
|
|
||||||
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
|
|
||||||
|
|
||||||
if df.is_series() {
|
|
||||||
let columns = df.as_ref().get_column_names();
|
|
||||||
|
|
||||||
df.as_ref()
|
|
||||||
.sort(columns, reverse)
|
|
||||||
.map_err(|e| {
|
|
||||||
ShellError::GenericError(
|
|
||||||
"Error sorting dataframe".into(),
|
|
||||||
e.to_string(),
|
|
||||||
Some(call.head),
|
|
||||||
None,
|
|
||||||
Vec::new(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
|
|
||||||
} else {
|
|
||||||
let columns: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
|
||||||
|
|
||||||
if !columns.is_empty() {
|
|
||||||
let (col_string, col_span) = convert_columns_string(columns, call.head)?;
|
|
||||||
|
|
||||||
df.as_ref()
|
|
||||||
.sort(&col_string, reverse)
|
|
||||||
.map_err(|e| {
|
|
||||||
ShellError::GenericError(
|
|
||||||
"Error sorting dataframe".into(),
|
|
||||||
e.to_string(),
|
|
||||||
Some(col_span),
|
|
||||||
None,
|
|
||||||
Vec::new(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.map(|df| {
|
|
||||||
PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(ShellError::GenericError(
|
|
||||||
"Missing columns".into(),
|
|
||||||
"missing column name to perform sort".into(),
|
|
||||||
Some(call.head),
|
|
||||||
None,
|
|
||||||
Vec::new(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::super::super::test_dataframe::test_dataframe;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_examples() {
|
|
||||||
test_dataframe(vec![Box::new(SortDF {})])
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,7 @@ impl Command for WithColumn {
|
|||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"series to be added or expressions used to define the new columns",
|
"series to be added or expressions used to define the new columns",
|
||||||
)
|
)
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -59,11 +59,34 @@ impl Command for WithColumn {
|
|||||||
Example {
|
Example {
|
||||||
description: "Adds a series to the dataframe",
|
description: "Adds a series to the dataframe",
|
||||||
example: r#"[[a b]; [1 2] [3 4]]
|
example: r#"[[a b]; [1 2] [3 4]]
|
||||||
| dfr to-df
|
|
||||||
| dfr to-lazy
|
| dfr to-lazy
|
||||||
| dfr with-column ((dfr col a) * 2 | dfr as "c")
|
| dfr with-column [
|
||||||
|
((dfr col a) * 2 | dfr as "c")
|
||||||
|
((dfr col a) * 3 | dfr as "d")
|
||||||
|
]
|
||||||
| dfr collect"#,
|
| dfr collect"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(3)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"c".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(6)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"d".to_string(),
|
||||||
|
vec![Value::test_int(3), Value::test_int(9)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -85,7 +108,7 @@ impl Command for WithColumn {
|
|||||||
command_eager(engine_state, stack, call, df)
|
command_eager(engine_state, stack, call, df)
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::CantConvert(
|
Err(ShellError::CantConvert(
|
||||||
"expression or query".into(),
|
"lazy or eager dataframe".into(),
|
||||||
value.get_type().to_string(),
|
value.get_type().to_string(),
|
||||||
value.span()?,
|
value.span()?,
|
||||||
None,
|
None,
|
||||||
@ -100,9 +123,23 @@ fn command_eager(
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
mut df: NuDataFrame,
|
mut df: NuDataFrame,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let other_value: Value = call.req(engine_state, stack, 0)?;
|
let new_column: Value = call.req(engine_state, stack, 0)?;
|
||||||
let other_span = other_value.span()?;
|
let column_span = new_column.span()?;
|
||||||
let mut other = NuDataFrame::try_from_value(other_value)?.as_series(other_span)?;
|
|
||||||
|
if NuExpression::can_downcast(&new_column) {
|
||||||
|
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
||||||
|
let value = Value::List {
|
||||||
|
vals,
|
||||||
|
span: call.head,
|
||||||
|
};
|
||||||
|
let expressions = NuExpression::extract_exprs(value)?;
|
||||||
|
let lazy = NuLazyFrame::new(true, df.lazy().with_columns(&expressions));
|
||||||
|
|
||||||
|
let df = lazy.collect(call.head)?;
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(df.into_value(call.head), None))
|
||||||
|
} else {
|
||||||
|
let mut other = NuDataFrame::try_from_value(new_column)?.as_series(column_span)?;
|
||||||
|
|
||||||
let name = match call.get_flag::<String>(engine_state, stack, "name")? {
|
let name = match call.get_flag::<String>(engine_state, stack, "name")? {
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
@ -117,7 +154,7 @@ fn command_eager(
|
|||||||
ShellError::GenericError(
|
ShellError::GenericError(
|
||||||
"Error adding column to dataframe".into(),
|
"Error adding column to dataframe".into(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
Some(other_span),
|
Some(column_span),
|
||||||
None,
|
None,
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
)
|
)
|
||||||
@ -129,6 +166,7 @@ fn command_eager(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn command_lazy(
|
fn command_lazy(
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
@ -146,7 +184,7 @@ fn command_lazy(
|
|||||||
let lazy: NuLazyFrame = lazy.into_polars().with_columns(&expressions).into();
|
let lazy: NuLazyFrame = lazy.into_polars().with_columns(&expressions).into();
|
||||||
|
|
||||||
Ok(PipelineData::Value(
|
Ok(PipelineData::Value(
|
||||||
NuLazyFrame::into_value(lazy, call.head),
|
NuLazyFrame::into_value(lazy, call.head)?,
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -155,9 +193,15 @@ fn command_lazy(
|
|||||||
mod test {
|
mod test {
|
||||||
use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::ExprAlias;
|
||||||
|
use crate::dataframe::expressions::ExprCol;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
test_dataframe(vec![Box::new(WithColumn {})])
|
test_dataframe(vec![
|
||||||
|
Box::new(WithColumn {}),
|
||||||
|
Box::new(ExprAlias {}),
|
||||||
|
Box::new(ExprCol {}),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use nu_engine::CallExt;
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -26,14 +26,34 @@ impl Command for ExprAlias {
|
|||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"Alias name for the expression",
|
"Alias name for the expression",
|
||||||
)
|
)
|
||||||
.category(Category::Custom("expressions".into()))
|
.category(Category::Custom("expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "Creates and alias expression",
|
description: "Creates and alias expression",
|
||||||
example: "(dfr col a | df as new_a)",
|
example: "dfr col a | dfr as new_a | dfr as-nu",
|
||||||
result: None,
|
result: {
|
||||||
|
let cols = vec!["expr".into(), "value".into()];
|
||||||
|
let expr = Value::test_string("column");
|
||||||
|
let value = Value::test_string("a");
|
||||||
|
let expr = Value::Record {
|
||||||
|
cols,
|
||||||
|
vals: vec![expr, value],
|
||||||
|
span: Span::test_data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let cols = vec!["expr".into(), "alias".into()];
|
||||||
|
let value = Value::test_string("new_a");
|
||||||
|
|
||||||
|
let record = Value::Record {
|
||||||
|
cols,
|
||||||
|
vals: vec![expr, value],
|
||||||
|
span: Span::test_data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(record)
|
||||||
|
},
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,3 +75,20 @@ impl Command for ExprAlias {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::ExprAsNu;
|
||||||
|
use crate::dataframe::expressions::ExprCol;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![
|
||||||
|
Box::new(ExprAlias {}),
|
||||||
|
Box::new(ExprCol {}),
|
||||||
|
Box::new(ExprAsNu {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,11 +7,11 @@ use nu_protocol::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ExprToNu;
|
pub struct ExprAsNu;
|
||||||
|
|
||||||
impl Command for ExprToNu {
|
impl Command for ExprAsNu {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"dfr to-nu"
|
"dfr as-nu"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -19,13 +19,13 @@ impl Command for ExprToNu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("expressions".into()))
|
Signature::build(self.name()).category(Category::Custom("expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "Convert a col expression into a nushell value",
|
description: "Convert a col expression into a nushell value",
|
||||||
example: "dfr col col_a | dfr to-nu",
|
example: "dfr col col_a | dfr as-nu",
|
||||||
result: Some(Value::Record {
|
result: Some(Value::Record {
|
||||||
cols: vec!["expr".into(), "value".into()],
|
cols: vec!["expr".into(), "value".into()],
|
||||||
vals: vec![
|
vals: vec![
|
||||||
@ -65,6 +65,6 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
test_dataframe(vec![Box::new(ExprToNu {}), Box::new(ExprCol {})])
|
test_dataframe(vec![Box::new(ExprAsNu {}), Box::new(ExprCol {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,13 +26,13 @@ impl Command for ExprCol {
|
|||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"Name of column to be used",
|
"Name of column to be used",
|
||||||
)
|
)
|
||||||
.category(Category::Custom("expressions".into()))
|
.category(Category::Custom("expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "Creates a named column expression and converts it to a nu object",
|
description: "Creates a named column expression and converts it to a nu object",
|
||||||
example: "dfr col col_a | dfr to-nu",
|
example: "dfr col col_a | dfr as-nu",
|
||||||
result: Some(Value::Record {
|
result: Some(Value::Record {
|
||||||
cols: vec!["expr".into(), "value".into()],
|
cols: vec!["expr".into(), "value".into()],
|
||||||
vals: vec![
|
vals: vec![
|
||||||
@ -66,12 +66,12 @@ impl Command for ExprCol {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
use super::super::super::ExprToNu;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::as_nu::ExprAsNu;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
test_dataframe(vec![Box::new(ExprCol {}), Box::new(ExprToNu {})])
|
test_dataframe(vec![Box::new(ExprCol {}), Box::new(ExprAsNu {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +0,0 @@
|
|||||||
mod col;
|
|
||||||
mod lit;
|
|
||||||
mod when;
|
|
||||||
|
|
||||||
pub(super) use crate::dataframe::expressions::dsl::col::ExprCol;
|
|
||||||
pub(super) use crate::dataframe::expressions::dsl::lit::ExprLit;
|
|
||||||
pub(super) use crate::dataframe::expressions::dsl::when::ExprWhen;
|
|
@ -1,96 +0,0 @@
|
|||||||
use crate::dataframe::values::NuExpression;
|
|
||||||
use nu_engine::CallExt;
|
|
||||||
use nu_protocol::{
|
|
||||||
ast::Call,
|
|
||||||
engine::{Command, EngineState, Stack},
|
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
|
||||||
};
|
|
||||||
use polars::prelude::when;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ExprWhen;
|
|
||||||
|
|
||||||
impl Command for ExprWhen {
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
"dfr when"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
|
||||||
"Creates a when expression"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
|
||||||
Signature::build(self.name())
|
|
||||||
.required(
|
|
||||||
"when predicate",
|
|
||||||
SyntaxShape::Any,
|
|
||||||
"Name of column to be used",
|
|
||||||
)
|
|
||||||
.required_named(
|
|
||||||
"then",
|
|
||||||
SyntaxShape::Any,
|
|
||||||
"Expression that will be applied when predicate is true",
|
|
||||||
Some('t'),
|
|
||||||
)
|
|
||||||
.required_named(
|
|
||||||
"otherwise",
|
|
||||||
SyntaxShape::Any,
|
|
||||||
"Expression that will be applied when predicate is false",
|
|
||||||
Some('o'),
|
|
||||||
)
|
|
||||||
.category(Category::Custom("expressions".into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
|
||||||
vec![Example {
|
|
||||||
description: "Create a new column for the dataframe",
|
|
||||||
example: r#"[[a b]; [1 2] [3 4]]
|
|
||||||
| dfr to-df
|
|
||||||
| dfr to-lazy
|
|
||||||
| dfr with-column (
|
|
||||||
dfr when ((dfr col a) > 2) --then 4 --otherwise 5 | dfr as "c"
|
|
||||||
)
|
|
||||||
| dfr collect"#,
|
|
||||||
result: None,
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(
|
|
||||||
&self,
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
call: &Call,
|
|
||||||
_input: PipelineData,
|
|
||||||
) -> Result<PipelineData, ShellError> {
|
|
||||||
let predicate: Value = call.req(engine_state, stack, 0)?;
|
|
||||||
let predicate = NuExpression::try_from_value(predicate)?;
|
|
||||||
|
|
||||||
let then: Value = call
|
|
||||||
.get_flag(engine_state, stack, "then")?
|
|
||||||
.expect("it is a required named value");
|
|
||||||
let then = NuExpression::try_from_value(then)?;
|
|
||||||
let otherwise: Value = call
|
|
||||||
.get_flag(engine_state, stack, "otherwise")?
|
|
||||||
.expect("it is a required named value");
|
|
||||||
let otherwise = NuExpression::try_from_value(otherwise)?;
|
|
||||||
|
|
||||||
let expr: NuExpression = when(predicate.into_polars())
|
|
||||||
.then(then.into_polars())
|
|
||||||
.otherwise(otherwise.into_polars())
|
|
||||||
.into();
|
|
||||||
|
|
||||||
Ok(PipelineData::Value(expr.into_value(call.head), None))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::super::super::super::test_dataframe::test_dataframe;
|
|
||||||
use super::super::super::ExprToNu;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_examples() {
|
|
||||||
test_dataframe(vec![Box::new(ExprWhen {}), Box::new(ExprToNu {})])
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,7 @@ macro_rules! expr_command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
|
Signature::build(self.name()).category(Category::Custom("expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -107,3 +107,17 @@ expr_command!(
|
|||||||
}],
|
}],
|
||||||
explode
|
explode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ExprCount command
|
||||||
|
// Expands to a command definition for a count expression
|
||||||
|
expr_command!(
|
||||||
|
ExprCount,
|
||||||
|
"dfr count",
|
||||||
|
"creates a count expression",
|
||||||
|
vec![Example {
|
||||||
|
description: "",
|
||||||
|
example: "",
|
||||||
|
result: None,
|
||||||
|
}],
|
||||||
|
count
|
||||||
|
);
|
||||||
|
@ -25,13 +25,13 @@ impl Command for ExprLit {
|
|||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"literal to construct the expression",
|
"literal to construct the expression",
|
||||||
)
|
)
|
||||||
.category(Category::Custom("expressions".into()))
|
.category(Category::Custom("expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "Created a literal expression and converts it to a nu object",
|
description: "Created a literal expression and converts it to a nu object",
|
||||||
example: "dfr lit 2 | dfr to-nu",
|
example: "dfr lit 2 | dfr as-nu",
|
||||||
result: Some(Value::Record {
|
result: Some(Value::Record {
|
||||||
cols: vec!["expr".into(), "value".into()],
|
cols: vec!["expr".into(), "value".into()],
|
||||||
vals: vec![
|
vals: vec![
|
||||||
@ -68,12 +68,12 @@ impl Command for ExprLit {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
use super::super::super::ExprToNu;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::as_nu::ExprAsNu;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
test_dataframe(vec![Box::new(ExprLit {}), Box::new(ExprToNu {})])
|
test_dataframe(vec![Box::new(ExprLit {}), Box::new(ExprAsNu {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,15 +1,20 @@
|
|||||||
mod alias;
|
mod alias;
|
||||||
mod dsl;
|
mod as_nu;
|
||||||
|
mod col;
|
||||||
mod expressions_macro;
|
mod expressions_macro;
|
||||||
mod to_nu;
|
mod lit;
|
||||||
|
mod otherwise;
|
||||||
|
mod when;
|
||||||
|
|
||||||
use nu_protocol::engine::StateWorkingSet;
|
use nu_protocol::engine::StateWorkingSet;
|
||||||
|
|
||||||
use crate::dataframe::expressions::dsl::*;
|
pub(crate) use crate::dataframe::expressions::alias::ExprAlias;
|
||||||
|
use crate::dataframe::expressions::as_nu::ExprAsNu;
|
||||||
use crate::dataframe::expressions::alias::ExprAlias;
|
pub(super) use crate::dataframe::expressions::col::ExprCol;
|
||||||
use crate::dataframe::expressions::expressions_macro::*;
|
pub(crate) use crate::dataframe::expressions::expressions_macro::*;
|
||||||
use crate::dataframe::expressions::to_nu::ExprToNu;
|
pub(super) use crate::dataframe::expressions::lit::ExprLit;
|
||||||
|
pub(super) use crate::dataframe::expressions::otherwise::ExprOtherwise;
|
||||||
|
pub(super) use crate::dataframe::expressions::when::ExprWhen;
|
||||||
|
|
||||||
pub fn add_expressions(working_set: &mut StateWorkingSet) {
|
pub fn add_expressions(working_set: &mut StateWorkingSet) {
|
||||||
macro_rules! bind_command {
|
macro_rules! bind_command {
|
||||||
@ -25,9 +30,11 @@ pub fn add_expressions(working_set: &mut StateWorkingSet) {
|
|||||||
bind_command!(
|
bind_command!(
|
||||||
ExprAlias,
|
ExprAlias,
|
||||||
ExprCol,
|
ExprCol,
|
||||||
|
ExprCount,
|
||||||
ExprLit,
|
ExprLit,
|
||||||
ExprToNu,
|
ExprAsNu,
|
||||||
ExprWhen,
|
ExprWhen,
|
||||||
|
ExprOtherwise,
|
||||||
ExprList,
|
ExprList,
|
||||||
ExprAggGroups,
|
ExprAggGroups,
|
||||||
ExprFlatten,
|
ExprFlatten,
|
||||||
|
125
crates/nu-command/src/dataframe/expressions/otherwise.rs
Normal file
125
crates/nu-command/src/dataframe/expressions/otherwise.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuWhen};
|
||||||
|
use nu_engine::CallExt;
|
||||||
|
use nu_protocol::{
|
||||||
|
ast::Call,
|
||||||
|
engine::{Command, EngineState, Stack},
|
||||||
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ExprOtherwise;
|
||||||
|
|
||||||
|
impl Command for ExprOtherwise {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"dfr otherwise"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"completes a when expression"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build(self.name())
|
||||||
|
.required(
|
||||||
|
"otherwise expression",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"expressioini to apply when no when predicate matches",
|
||||||
|
)
|
||||||
|
.category(Category::Custom("expression".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Create a when conditions",
|
||||||
|
example: "dfr when ((dfr col a) > 2) 4 | dfr otherwise 5",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Create a when conditions",
|
||||||
|
example:
|
||||||
|
"dfr when ((dfr col a) > 2) 4 | dfr when ((dfr col a) < 0) 6 | dfr otherwise 0",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Create a new column for the dataframe",
|
||||||
|
example: r#"[[a b]; [6 2] [1 4] [4 1]]
|
||||||
|
| dfr to-lazy
|
||||||
|
| dfr with-column (
|
||||||
|
dfr when ((dfr col a) > 2) 4 | dfr otherwise 5 | dfr as c
|
||||||
|
)
|
||||||
|
| dfr with-column (
|
||||||
|
dfr when ((dfr col a) > 5) 10 | dfr when ((dfr col a) < 2) 6 | dfr otherwise 0 | dfr as d
|
||||||
|
)
|
||||||
|
| dfr collect"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(1), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4), Value::test_int(1)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"c".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(5), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"d".to_string(),
|
||||||
|
vec![Value::test_int(10), Value::test_int(6), Value::test_int(0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let otherwise_predicate: Value = call.req(engine_state, stack, 0)?;
|
||||||
|
let otherwise_predicate = NuExpression::try_from_value(otherwise_predicate)?;
|
||||||
|
|
||||||
|
let value = input.into_value(call.head);
|
||||||
|
let complete: NuExpression = match NuWhen::try_from_value(value)? {
|
||||||
|
NuWhen::WhenThen(when_then) => when_then
|
||||||
|
.otherwise(otherwise_predicate.into_polars())
|
||||||
|
.into(),
|
||||||
|
NuWhen::WhenThenThen(when_then_then) => when_then_then
|
||||||
|
.otherwise(otherwise_predicate.into_polars())
|
||||||
|
.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(complete.into_value(call.head), None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use crate::dataframe::eager::WithColumn;
|
||||||
|
use crate::dataframe::expressions::when::ExprWhen;
|
||||||
|
use crate::dataframe::expressions::{ExprAlias, ExprAsNu, ExprCol};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![
|
||||||
|
Box::new(WithColumn {}),
|
||||||
|
Box::new(ExprCol {}),
|
||||||
|
Box::new(ExprAlias {}),
|
||||||
|
Box::new(ExprWhen {}),
|
||||||
|
Box::new(ExprOtherwise {}),
|
||||||
|
Box::new(ExprAsNu {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
140
crates/nu-command/src/dataframe/expressions/when.rs
Normal file
140
crates/nu-command/src/dataframe/expressions/when.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuWhen};
|
||||||
|
use nu_engine::CallExt;
|
||||||
|
use nu_protocol::{
|
||||||
|
ast::Call,
|
||||||
|
engine::{Command, EngineState, Stack},
|
||||||
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
|
};
|
||||||
|
use polars::prelude::when;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ExprWhen;
|
||||||
|
|
||||||
|
impl Command for ExprWhen {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"dfr when"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Creates and modifies a when expression"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build(self.name())
|
||||||
|
.required(
|
||||||
|
"when expression",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"when expression used for matching",
|
||||||
|
)
|
||||||
|
.required(
|
||||||
|
"then expression",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"expression that will be applied when predicate is true",
|
||||||
|
)
|
||||||
|
.category(Category::Custom("expression".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Create a when conditions",
|
||||||
|
example: "dfr when ((dfr col a) > 2) 4",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Create a when conditions",
|
||||||
|
example: "dfr when ((dfr col a) > 2) 4 | dfr when ((dfr col a) < 0) 6",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Create a new column for the dataframe",
|
||||||
|
example: r#"[[a b]; [6 2] [1 4] [4 1]]
|
||||||
|
| dfr to-lazy
|
||||||
|
| dfr with-column (
|
||||||
|
dfr when ((dfr col a) > 2) 4 | dfr otherwise 5 | dfr as c
|
||||||
|
)
|
||||||
|
| dfr with-column (
|
||||||
|
dfr when ((dfr col a) > 5) 10 | dfr when ((dfr col a) < 2) 6 | dfr otherwise 0 | dfr as d
|
||||||
|
)
|
||||||
|
| dfr collect"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(1), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4), Value::test_int(1)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"c".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(5), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"d".to_string(),
|
||||||
|
vec![Value::test_int(10), Value::test_int(6), Value::test_int(0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let when_predicate: Value = call.req(engine_state, stack, 0)?;
|
||||||
|
let when_predicate = NuExpression::try_from_value(when_predicate)?;
|
||||||
|
|
||||||
|
let then_predicate: Value = call.req(engine_state, stack, 1)?;
|
||||||
|
let then_predicate = NuExpression::try_from_value(then_predicate)?;
|
||||||
|
|
||||||
|
let value = input.into_value(call.head);
|
||||||
|
let when_then: NuWhen = match value {
|
||||||
|
Value::Nothing { .. } => when(when_predicate.into_polars())
|
||||||
|
.then(then_predicate.into_polars())
|
||||||
|
.into(),
|
||||||
|
v => match NuWhen::try_from_value(v)? {
|
||||||
|
NuWhen::WhenThen(when_then) => when_then
|
||||||
|
.when(when_predicate.into_polars())
|
||||||
|
.then(then_predicate.into_polars())
|
||||||
|
.into(),
|
||||||
|
NuWhen::WhenThenThen(when_then_then) => when_then_then
|
||||||
|
.when(when_predicate.into_polars())
|
||||||
|
.then(then_predicate.into_polars())
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(when_then.into_value(call.head), None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use crate::dataframe::eager::WithColumn;
|
||||||
|
use crate::dataframe::expressions::otherwise::ExprOtherwise;
|
||||||
|
use crate::dataframe::expressions::{ExprAlias, ExprAsNu, ExprCol};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![
|
||||||
|
Box::new(WithColumn {}),
|
||||||
|
Box::new(ExprCol {}),
|
||||||
|
Box::new(ExprAlias {}),
|
||||||
|
Box::new(ExprWhen {}),
|
||||||
|
Box::new(ExprOtherwise {}),
|
||||||
|
Box::new(ExprAsNu {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
use crate::dataframe::values::{NuExpression, NuLazyFrame, NuLazyGroupBy};
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame, NuLazyGroupBy};
|
||||||
|
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -12,7 +12,7 @@ pub struct LazyAggregate;
|
|||||||
|
|
||||||
impl Command for LazyAggregate {
|
impl Command for LazyAggregate {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"dfr aggregate"
|
"dfr agg"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -36,26 +36,67 @@ impl Command for LazyAggregate {
|
|||||||
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
||||||
| dfr to-df
|
| dfr to-df
|
||||||
| dfr group-by a
|
| dfr group-by a
|
||||||
| dfr aggregate [
|
| dfr agg [
|
||||||
("b" | dfr min | dfr as "b_min")
|
("b" | dfr min | dfr as "b_min")
|
||||||
("b" | dfr max | dfr as "b_max")
|
("b" | dfr max | dfr as "b_max")
|
||||||
("b" | dfr sum | dfr as "b_sum")
|
("b" | dfr sum | dfr as "b_sum")
|
||||||
]"#,
|
]"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(2)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_min".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_max".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(6)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_sum".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(10)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Group by and perform an aggregation",
|
description: "Group by and perform an aggregation",
|
||||||
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
||||||
| dfr to-df
|
|
||||||
| dfr to-lazy
|
| dfr to-lazy
|
||||||
| dfr group-by a
|
| dfr group-by a
|
||||||
| dfr aggregate [
|
| dfr agg [
|
||||||
("b" | dfr min | dfr as "b_min")
|
("b" | dfr min | dfr as "b_min")
|
||||||
("b" | dfr max | dfr as "b_max")
|
("b" | dfr max | dfr as "b_max")
|
||||||
("b" | dfr sum | dfr as "b_sum")
|
("b" | dfr sum | dfr as "b_sum")
|
||||||
]
|
]
|
||||||
| dfr collect"#,
|
| dfr collect"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(2)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_min".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_max".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(6)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_sum".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(10)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -78,14 +119,33 @@ impl Command for LazyAggregate {
|
|||||||
let from_eager = group_by.from_eager;
|
let from_eager = group_by.from_eager;
|
||||||
|
|
||||||
let group_by = group_by.into_polars();
|
let group_by = group_by.into_polars();
|
||||||
let lazy: NuLazyFrame = group_by.agg(&expressions).into();
|
let lazy = NuLazyFrame {
|
||||||
|
lazy: group_by.agg(&expressions).into(),
|
||||||
let res = if from_eager {
|
from_eager,
|
||||||
lazy.collect(call.head)?.into_value(call.head)
|
|
||||||
} else {
|
|
||||||
lazy.into_value(call.head)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let res = lazy.into_value(call.head)?;
|
||||||
Ok(PipelineData::Value(res, None))
|
Ok(PipelineData::Value(res, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::ExprAlias;
|
||||||
|
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
|
||||||
|
use crate::dataframe::lazy::{LazyMax, LazyMin, LazySum};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![
|
||||||
|
Box::new(LazyAggregate {}),
|
||||||
|
Box::new(ToLazyGroupBy {}),
|
||||||
|
Box::new(ExprAlias {}),
|
||||||
|
Box::new(LazyMin {}),
|
||||||
|
Box::new(LazyMax {}),
|
||||||
|
Box::new(LazySum {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use super::super::values::{NuDataFrame, NuLazyFrame};
|
use crate::dataframe::values::{Column, NuDataFrame};
|
||||||
|
|
||||||
|
use super::super::values::NuLazyFrame;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature,
|
Category, Example, PipelineData, ShellError, Signature, Span, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -15,7 +16,7 @@ impl Command for LazyCollect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Collect lazy dataframe into dataframe"
|
"Collect lazy dataframe into eager dataframe"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
@ -24,9 +25,22 @@ impl Command for LazyCollect {
|
|||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "",
|
description: "drop duplicates",
|
||||||
example: "",
|
example: "[[a b]; [1 2] [3 4]] | dfr to-lazy | dfr collect",
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(3)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +53,22 @@ impl Command for LazyCollect {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
|
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
|
||||||
let eager = lazy.collect(call.head)?;
|
let eager = lazy.collect(call.head)?;
|
||||||
|
let value = Value::CustomValue {
|
||||||
|
val: Box::new(eager),
|
||||||
|
span: call.head,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(PipelineData::Value(
|
Ok(PipelineData::Value(value, None))
|
||||||
NuDataFrame::into_value(eager, call.head),
|
}
|
||||||
None,
|
}
|
||||||
))
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![Box::new(LazyCollect {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use super::super::values::NuLazyFrame;
|
use super::super::values::NuLazyFrame;
|
||||||
use crate::dataframe::values::NuDataFrame;
|
use crate::dataframe::values::{Column, NuDataFrame};
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -31,9 +31,22 @@ impl Command for LazyFetch {
|
|||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "",
|
description: "Fetch a rows from the dataframe",
|
||||||
example: "",
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr fetch 2",
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(2)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,13 +81,13 @@ impl Command for LazyFetch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod test {
|
mod test {
|
||||||
// use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
// use super::*;
|
use super::*;
|
||||||
//
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn test_examples() {
|
fn test_examples() {
|
||||||
// test_dataframe(vec![Box::new(LazyFetch {})])
|
test_dataframe(vec![Box::new(LazyFetch {})])
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
@ -44,22 +44,23 @@ impl Command for LazyFillNA {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let fill: Value = call.req(engine_state, stack, 0)?;
|
let fill: Value = call.req(engine_state, stack, 0)?;
|
||||||
|
let value = input.into_value(call.head);
|
||||||
|
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
|
if NuExpression::can_downcast(&value) {
|
||||||
|
let expr = NuExpression::try_from_value(value)?;
|
||||||
|
let fill = NuExpression::try_from_value(fill)?.into_polars();
|
||||||
|
let expr: NuExpression = expr.into_polars().fill_nan(fill).into();
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(
|
||||||
|
NuExpression::into_value(expr, call.head),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
let expr = NuExpression::try_from_value(fill)?.into_polars();
|
let expr = NuExpression::try_from_value(fill)?.into_polars();
|
||||||
let lazy: NuLazyFrame = lazy.fill_nan(expr).into();
|
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().fill_nan(expr));
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
|
||||||
//mod test {
|
|
||||||
// use super::super::super::test_dataframe::test_dataframe;
|
|
||||||
// use super::*;
|
|
||||||
//
|
|
||||||
// #[test]
|
|
||||||
// fn test_examples() {
|
|
||||||
// test_dataframe(vec![Box::new(LazyFillNA {})])
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::dataframe::values::{NuExpression, NuLazyFrame};
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -30,9 +30,22 @@ impl Command for LazyFillNull {
|
|||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "",
|
description: "Fills the null values by 0",
|
||||||
example: "",
|
example: "[1 2 2 3 3] | dfr to-df | dfr shift 2 | dfr fill-null 0",
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![Column::new(
|
||||||
|
"0".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(0),
|
||||||
|
Value::test_int(0),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(2),
|
||||||
|
Value::test_int(2),
|
||||||
|
],
|
||||||
|
)])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,22 +57,35 @@ impl Command for LazyFillNull {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let fill: Value = call.req(engine_state, stack, 0)?;
|
let fill: Value = call.req(engine_state, stack, 0)?;
|
||||||
|
let value = input.into_value(call.head);
|
||||||
|
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
|
if NuExpression::can_downcast(&value) {
|
||||||
|
let expr = NuExpression::try_from_value(value)?;
|
||||||
|
let fill = NuExpression::try_from_value(fill)?.into_polars();
|
||||||
|
let expr: NuExpression = expr.into_polars().fill_null(fill).into();
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(
|
||||||
|
NuExpression::into_value(expr, call.head),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
let expr = NuExpression::try_from_value(fill)?.into_polars();
|
let expr = NuExpression::try_from_value(fill)?.into_polars();
|
||||||
let lazy: NuLazyFrame = lazy.fill_null(expr).into();
|
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().fill_null(expr));
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod test {
|
mod test {
|
||||||
// use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::series::Shift;
|
||||||
// use super::*;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
//
|
use super::*;
|
||||||
// #[test]
|
|
||||||
// fn test_examples() {
|
#[test]
|
||||||
// test_dataframe(vec![Box::new(LazyFillNull {})])
|
fn test_examples() {
|
||||||
// }
|
test_dataframe(vec![Box::new(LazyFillNull {}), Box::new(Shift {})])
|
||||||
//}
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::dataframe::values::{NuExpression, NuLazyFrame, NuLazyGroupBy};
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame, NuLazyGroupBy};
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
use polars::prelude::Expr;
|
use polars::prelude::Expr;
|
||||||
|
|
||||||
@ -36,26 +36,67 @@ impl Command for ToLazyGroupBy {
|
|||||||
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
||||||
| dfr to-df
|
| dfr to-df
|
||||||
| dfr group-by a
|
| dfr group-by a
|
||||||
| dfr aggregate [
|
| dfr agg [
|
||||||
("b" | dfr min | dfr as "b_min")
|
("b" | dfr min | dfr as "b_min")
|
||||||
("b" | dfr max | dfr as "b_max")
|
("b" | dfr max | dfr as "b_max")
|
||||||
("b" | dfr sum | dfr as "b_sum")
|
("b" | dfr sum | dfr as "b_sum")
|
||||||
]"#,
|
]"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(2)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_min".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_max".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(6)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_sum".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(10)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Group by and perform an aggregation",
|
description: "Group by and perform an aggregation",
|
||||||
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
|
||||||
| dfr to-df
|
| dfr to-df
|
||||||
| dfr to-lazy
|
|
||||||
| dfr group-by a
|
| dfr group-by a
|
||||||
| dfr aggregate [
|
| dfr agg [
|
||||||
("b" | dfr min | dfr as "b_min")
|
("b" | dfr min | dfr as "b_min")
|
||||||
("b" | dfr max | dfr as "b_max")
|
("b" | dfr max | dfr as "b_max")
|
||||||
("b" | dfr sum | dfr as "b_sum")
|
("b" | dfr sum | dfr as "b_sum")
|
||||||
]
|
]
|
||||||
| dfr collect"#,
|
| dfr collect"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(2)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_min".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_max".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(6)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b_sum".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(10)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -86,7 +127,8 @@ impl Command for ToLazyGroupBy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let value = input.into_value(call.head);
|
let value = input.into_value(call.head);
|
||||||
let (lazy, from_eager) = NuLazyFrame::maybe_is_eager(value)?;
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
|
let from_eager = lazy.from_eager;
|
||||||
|
|
||||||
let group_by = NuLazyGroupBy {
|
let group_by = NuLazyGroupBy {
|
||||||
group_by: Some(lazy.into_polars().groupby(&expressions)),
|
group_by: Some(lazy.into_polars().groupby(&expressions)),
|
||||||
@ -96,3 +138,24 @@ impl Command for ToLazyGroupBy {
|
|||||||
Ok(PipelineData::Value(group_by.into_value(call.head), None))
|
Ok(PipelineData::Value(group_by.into_value(call.head), None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
use crate::dataframe::expressions::ExprAlias;
|
||||||
|
use crate::dataframe::lazy::aggregate::LazyAggregate;
|
||||||
|
use crate::dataframe::lazy::{LazyMax, LazyMin, LazySum};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![
|
||||||
|
Box::new(LazyAggregate {}),
|
||||||
|
Box::new(ToLazyGroupBy {}),
|
||||||
|
Box::new(ExprAlias {}),
|
||||||
|
Box::new(LazyMin {}),
|
||||||
|
Box::new(LazyMax {}),
|
||||||
|
Box::new(LazySum {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::dataframe::values::{NuExpression, NuLazyFrame};
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
use polars::prelude::{Expr, JoinType};
|
use polars::prelude::{Expr, JoinType};
|
||||||
|
|
||||||
@ -46,16 +46,116 @@ impl Command for LazyJoin {
|
|||||||
Example {
|
Example {
|
||||||
description: "Join two lazy dataframes",
|
description: "Join two lazy dataframes",
|
||||||
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | dfr to-lazy);
|
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | dfr to-lazy);
|
||||||
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [1 "c" "var"] [1 "c" "const"]] | dfr to-lazy);
|
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | dfr to-lazy);
|
||||||
$df_a | dfr join $df_b a foo | dfr collect"#,
|
$df_a | dfr join $df_b a foo | dfr collect"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(2),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_string("a"),
|
||||||
|
Value::test_string("b"),
|
||||||
|
Value::test_string("c"),
|
||||||
|
Value::test_string("c"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"c".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(0),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(2),
|
||||||
|
Value::test_int(3),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"bar".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_string("a"),
|
||||||
|
Value::test_string("c"),
|
||||||
|
Value::test_string("a"),
|
||||||
|
Value::test_string("a"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"ham".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_string("let"),
|
||||||
|
Value::test_string("var"),
|
||||||
|
Value::test_string("let"),
|
||||||
|
Value::test_string("let"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Join one eager dataframe with a lazy dataframe",
|
description: "Join one eager dataframe with a lazy dataframe",
|
||||||
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | dfr to-df);
|
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | dfr to-df);
|
||||||
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [1 "c" "var"] [1 "c" "const"]] | dfr to-lazy);
|
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | dfr to-lazy);
|
||||||
$df_a | dfr join $df_b a foo"#,
|
$df_a | dfr join $df_b a foo"#,
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(2),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_string("a"),
|
||||||
|
Value::test_string("b"),
|
||||||
|
Value::test_string("c"),
|
||||||
|
Value::test_string("c"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"c".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(0),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(2),
|
||||||
|
Value::test_int(3),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"bar".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_string("a"),
|
||||||
|
Value::test_string("c"),
|
||||||
|
Value::test_string("a"),
|
||||||
|
Value::test_string("a"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"ham".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_string("let"),
|
||||||
|
Value::test_string("var"),
|
||||||
|
Value::test_string("let"),
|
||||||
|
Value::test_string("let"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -82,7 +182,7 @@ impl Command for LazyJoin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let other: Value = call.req(engine_state, stack, 0)?;
|
let other: Value = call.req(engine_state, stack, 0)?;
|
||||||
let (other, _) = NuLazyFrame::maybe_is_eager(other)?;
|
let other = NuLazyFrame::try_from_value(other)?;
|
||||||
let other = other.into_polars();
|
let other = other.into_polars();
|
||||||
|
|
||||||
let left_on: Value = call.req(engine_state, stack, 1)?;
|
let left_on: Value = call.req(engine_state, stack, 1)?;
|
||||||
@ -114,10 +214,11 @@ impl Command for LazyJoin {
|
|||||||
let suffix = suffix.unwrap_or_else(|| "_x".into());
|
let suffix = suffix.unwrap_or_else(|| "_x".into());
|
||||||
|
|
||||||
let value = input.into_value(call.head);
|
let value = input.into_value(call.head);
|
||||||
let (lazy, from_eager) = NuLazyFrame::maybe_is_eager(value)?;
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
|
let from_eager = lazy.from_eager;
|
||||||
let lazy = lazy.into_polars();
|
let lazy = lazy.into_polars();
|
||||||
|
|
||||||
let lazy: NuLazyFrame = lazy
|
let lazy = lazy
|
||||||
.join_builder()
|
.join_builder()
|
||||||
.with(other)
|
.with(other)
|
||||||
.left_on(left_on)
|
.left_on(left_on)
|
||||||
@ -125,15 +226,21 @@ impl Command for LazyJoin {
|
|||||||
.how(how)
|
.how(how)
|
||||||
.force_parallel(true)
|
.force_parallel(true)
|
||||||
.suffix(suffix)
|
.suffix(suffix)
|
||||||
.finish()
|
.finish();
|
||||||
.into();
|
|
||||||
|
|
||||||
let res = if from_eager {
|
let lazy = NuLazyFrame::new(from_eager, lazy);
|
||||||
lazy.collect(call.head)?.into_value(call.head)
|
|
||||||
} else {
|
|
||||||
lazy.into_value(call.head)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(PipelineData::Value(res, None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![Box::new(LazyJoin {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
/// Definition of multiple lazyframe commands using a macro rule
|
/// Definition of multiple lazyframe commands using a macro rule
|
||||||
/// All of these commands have an identical body and only require
|
/// All of these commands have an identical body and only require
|
||||||
/// to have a change in the name, description and function
|
/// to have a change in the name, description and function
|
||||||
use crate::dataframe::values::{NuExpression, NuLazyFrame};
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature,
|
Category, Example, PipelineData, ShellError, Signature, Span, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! lazy_command {
|
macro_rules! lazy_command {
|
||||||
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident) => {
|
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident, $test: ident) => {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct $command;
|
pub struct $command;
|
||||||
|
|
||||||
@ -37,10 +37,21 @@ macro_rules! lazy_command {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
|
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
|
||||||
let lazy: NuLazyFrame = lazy.$func().into();
|
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().$func());
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod $test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![Box::new($command {})])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -53,11 +64,25 @@ lazy_command!(
|
|||||||
"dfr reverse",
|
"dfr reverse",
|
||||||
"Reverses the LazyFrame",
|
"Reverses the LazyFrame",
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "",
|
description: "Reverses the dataframe",
|
||||||
example: "",
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr reverse",
|
||||||
result: None,
|
result: Some(
|
||||||
}],
|
NuDataFrame::try_from_columns(vec![
|
||||||
reverse
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(4), Value::test_int(6),],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(2), Value::test_int(2),],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},],
|
||||||
|
reverse,
|
||||||
|
test_reverse
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazyCache command
|
// LazyCache command
|
||||||
@ -67,17 +92,18 @@ lazy_command!(
|
|||||||
"dfr cache",
|
"dfr cache",
|
||||||
"Caches operations in a new LazyFrame",
|
"Caches operations in a new LazyFrame",
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "",
|
description: "Caches the result into a new LazyFrame",
|
||||||
example: "",
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr reverse | dfr cache",
|
||||||
result: None,
|
result: None,
|
||||||
}],
|
}],
|
||||||
cache
|
cache,
|
||||||
|
test_cache
|
||||||
);
|
);
|
||||||
|
|
||||||
// Creates a command that may result in a lazy frame operation or
|
// Creates a command that may result in a lazy frame operation or
|
||||||
// lazy frame expression
|
// lazy frame expression
|
||||||
macro_rules! lazy_expr_command {
|
macro_rules! lazy_expr_command {
|
||||||
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident) => {
|
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident, $test: ident) => {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct $command;
|
pub struct $command;
|
||||||
|
|
||||||
@ -91,7 +117,8 @@ macro_rules! lazy_expr_command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("lazyframe".into()))
|
Signature::build(self.name())
|
||||||
|
.category(Category::Custom("lazyframe or expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -115,21 +142,31 @@ macro_rules! lazy_expr_command {
|
|||||||
NuExpression::into_value(expr, call.head),
|
NuExpression::into_value(expr, call.head),
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
} else if NuLazyFrame::can_downcast(&value) {
|
|
||||||
let lazy = NuLazyFrame::try_from_value(value)?.into_polars();
|
|
||||||
let lazy: NuLazyFrame = lazy.$func().into();
|
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::CantConvert(
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
"expression or lazyframe".into(),
|
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().$func());
|
||||||
value.get_type().to_string(),
|
|
||||||
value.span()?,
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
None,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod $test {
|
||||||
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
|
use super::*;
|
||||||
|
use crate::dataframe::lazy::aggregate::LazyAggregate;
|
||||||
|
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
test_dataframe(vec![
|
||||||
|
Box::new($command {}),
|
||||||
|
Box::new(LazyAggregate {}),
|
||||||
|
Box::new(ToLazyGroupBy {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,12 +176,43 @@ lazy_expr_command!(
|
|||||||
LazyMax,
|
LazyMax,
|
||||||
"dfr max",
|
"dfr max",
|
||||||
"Aggregates columns to their max value or creates a max expression",
|
"Aggregates columns to their max value or creates a max expression",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Max value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr to-df | dfr max",
|
||||||
}],
|
result: Some(
|
||||||
max
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_int(6)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_int(4)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Max aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 4] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr max)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(1)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
max,
|
||||||
|
test_max
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazyMin command
|
// LazyMin command
|
||||||
@ -153,12 +221,43 @@ lazy_expr_command!(
|
|||||||
LazyMin,
|
LazyMin,
|
||||||
"dfr min",
|
"dfr min",
|
||||||
"Aggregates columns to their min value or creates a min expression",
|
"Aggregates columns to their min value or creates a min expression",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Min value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr to-df | dfr min",
|
||||||
}],
|
result: Some(
|
||||||
min
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_int(1)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_int(1)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Min aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 4] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr min)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(2), Value::test_int(1)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
min,
|
||||||
|
test_min
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazySum command
|
// LazySum command
|
||||||
@ -166,13 +265,44 @@ lazy_expr_command!(
|
|||||||
lazy_expr_command!(
|
lazy_expr_command!(
|
||||||
LazySum,
|
LazySum,
|
||||||
"dfr sum",
|
"dfr sum",
|
||||||
"Aggregates columns to their sum value or creates a sum expression",
|
"Aggregates columns to their sum value or creates a sum expression for an aggregation",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Sums all columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr to-df | dfr sum",
|
||||||
}],
|
result: Some(
|
||||||
sum
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_int(11)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_int(7)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Sum aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 4] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr sum)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(1)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sum,
|
||||||
|
test_sum
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazyMean command
|
// LazyMean command
|
||||||
@ -180,13 +310,44 @@ lazy_expr_command!(
|
|||||||
lazy_expr_command!(
|
lazy_expr_command!(
|
||||||
LazyMean,
|
LazyMean,
|
||||||
"dfr mean",
|
"dfr mean",
|
||||||
"Aggregates columns to their mean value or creates a mean expression",
|
"Aggregates columns to their mean value or creates a mean expression for an aggregation",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Mean value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr mean",
|
||||||
}],
|
result: Some(
|
||||||
mean
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_float(2.0)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Mean aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 4] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr mean)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_float(3.0), Value::test_float(1.0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mean,
|
||||||
|
test_mean
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazyMedian command
|
// LazyMedian command
|
||||||
@ -194,13 +355,44 @@ lazy_expr_command!(
|
|||||||
lazy_expr_command!(
|
lazy_expr_command!(
|
||||||
LazyMedian,
|
LazyMedian,
|
||||||
"dfr median",
|
"dfr median",
|
||||||
"Aggregates columns to their median value or creates a median expression",
|
"Aggregates columns to their median value or creates a median expression for an aggregation",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Median value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr median",
|
||||||
}],
|
result: Some(
|
||||||
median
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_float(2.0)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Median aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 4] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr median)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_float(3.0), Value::test_float(1.0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
median,
|
||||||
|
test_median
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazyStd command
|
// LazyStd command
|
||||||
@ -208,13 +400,44 @@ lazy_expr_command!(
|
|||||||
lazy_expr_command!(
|
lazy_expr_command!(
|
||||||
LazyStd,
|
LazyStd,
|
||||||
"dfr std",
|
"dfr std",
|
||||||
"Aggregates columns to their std value",
|
"Aggregates columns to their std value or creates a std expression for an aggregation",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Std value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr std",
|
||||||
}],
|
result: Some(
|
||||||
std
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_float(2.0)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Std aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 2] [two 1] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr std)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_float(0.0), Value::test_float(0.0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
std,
|
||||||
|
test_std
|
||||||
);
|
);
|
||||||
|
|
||||||
// LazyVar command
|
// LazyVar command
|
||||||
@ -222,11 +445,42 @@ lazy_expr_command!(
|
|||||||
lazy_expr_command!(
|
lazy_expr_command!(
|
||||||
LazyVar,
|
LazyVar,
|
||||||
"dfr var",
|
"dfr var",
|
||||||
"Aggregates columns to their var value",
|
"Aggregates columns to their var value or create a var expression for an aggregation",
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Var value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr var",
|
||||||
}],
|
result: Some(
|
||||||
var
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Var aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 2] [two 1] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr var)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_float(0.0), Value::test_float(0.0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
var,
|
||||||
|
test_var
|
||||||
);
|
);
|
||||||
|
@ -13,10 +13,10 @@ mod to_lazy;
|
|||||||
|
|
||||||
use nu_protocol::engine::StateWorkingSet;
|
use nu_protocol::engine::StateWorkingSet;
|
||||||
|
|
||||||
use crate::dataframe::lazy::macro_commands::*;
|
pub(crate) use crate::dataframe::lazy::macro_commands::*;
|
||||||
|
|
||||||
use crate::dataframe::lazy::aggregate::LazyAggregate;
|
use crate::dataframe::lazy::aggregate::LazyAggregate;
|
||||||
use crate::dataframe::lazy::collect::LazyCollect;
|
pub use crate::dataframe::lazy::collect::LazyCollect;
|
||||||
use crate::dataframe::lazy::fetch::LazyFetch;
|
use crate::dataframe::lazy::fetch::LazyFetch;
|
||||||
use crate::dataframe::lazy::fill_na::LazyFillNA;
|
use crate::dataframe::lazy::fill_na::LazyFillNA;
|
||||||
use crate::dataframe::lazy::fill_null::LazyFillNull;
|
use crate::dataframe::lazy::fill_null::LazyFillNull;
|
||||||
@ -25,7 +25,7 @@ use crate::dataframe::lazy::join::LazyJoin;
|
|||||||
use crate::dataframe::lazy::quantile::LazyQuantile;
|
use crate::dataframe::lazy::quantile::LazyQuantile;
|
||||||
use crate::dataframe::lazy::select::LazySelect;
|
use crate::dataframe::lazy::select::LazySelect;
|
||||||
use crate::dataframe::lazy::sort_by_expr::LazySortBy;
|
use crate::dataframe::lazy::sort_by_expr::LazySortBy;
|
||||||
use crate::dataframe::lazy::to_lazy::ToLazyFrame;
|
pub use crate::dataframe::lazy::to_lazy::ToLazyFrame;
|
||||||
|
|
||||||
pub fn add_lazy_decls(working_set: &mut StateWorkingSet) {
|
pub fn add_lazy_decls(working_set: &mut StateWorkingSet) {
|
||||||
macro_rules! bind_command {
|
macro_rules! bind_command {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::dataframe::values::NuLazyFrame;
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
use polars::prelude::QuantileInterpolOptions;
|
use polars::prelude::QuantileInterpolOptions;
|
||||||
|
|
||||||
@ -30,11 +30,41 @@ impl Command for LazyQuantile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "quantile value from columns in a dataframe",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr to-df | dfr quantile 0.5",
|
||||||
}]
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new("a".to_string(), vec![Value::test_float(4.0)]),
|
||||||
|
Column::new("b".to_string(), vec![Value::test_float(2.0)]),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Quantile aggregation for a group by",
|
||||||
|
example: r#"[[a b]; [one 2] [one 4] [two 1]]
|
||||||
|
| dfr to-df
|
||||||
|
| dfr group-by a
|
||||||
|
| dfr agg ("b" | dfr quantile 0.5)"#,
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_string("one"), Value::test_string("two")],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_float(4.0), Value::test_float(1.0)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -44,24 +74,46 @@ impl Command for LazyQuantile {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let value = input.into_value(call.head);
|
||||||
let quantile: f64 = call.req(engine_state, stack, 0)?;
|
let quantile: f64 = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
|
if NuExpression::can_downcast(&value) {
|
||||||
let lazy: NuLazyFrame = lazy
|
let expr = NuExpression::try_from_value(value)?;
|
||||||
|
let expr: NuExpression = expr
|
||||||
|
.into_polars()
|
||||||
.quantile(quantile, QuantileInterpolOptions::default())
|
.quantile(quantile, QuantileInterpolOptions::default())
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(
|
||||||
|
NuExpression::into_value(expr, call.head),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
|
let lazy = NuLazyFrame::new(
|
||||||
|
lazy.from_eager,
|
||||||
|
lazy.into_polars()
|
||||||
|
.quantile(quantile, QuantileInterpolOptions::default()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod test {
|
mod test {
|
||||||
// use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
// use super::*;
|
use super::*;
|
||||||
//
|
use crate::dataframe::lazy::aggregate::LazyAggregate;
|
||||||
// #[test]
|
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
|
||||||
// fn test_examples() {
|
|
||||||
// test_dataframe(vec![Box::new(LazyQuantile {})])
|
#[test]
|
||||||
// }
|
fn test_examples() {
|
||||||
//}
|
test_dataframe(vec![
|
||||||
|
Box::new(LazyQuantile {}),
|
||||||
|
Box::new(LazyAggregate {}),
|
||||||
|
Box::new(ToLazyGroupBy {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::dataframe::values::{NuExpression, NuLazyFrame};
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
|
||||||
|
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
use polars::prelude::Expr;
|
use polars::prelude::Expr;
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ impl Command for LazySelect {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.required(
|
.rest(
|
||||||
"select expressions",
|
"select expressions",
|
||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"Expression(s) that define the column selection",
|
"Expression(s) that define the column selection",
|
||||||
@ -32,9 +32,16 @@ impl Command for LazySelect {
|
|||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![Example {
|
||||||
description: "",
|
description: "Select a column from the dataframe",
|
||||||
example: "",
|
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr to-df | dfr select a",
|
||||||
result: None,
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(6), Value::test_int(4), Value::test_int(2)],
|
||||||
|
)])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +52,11 @@ impl Command for LazySelect {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let value: Value = call.req(engine_state, stack, 0)?;
|
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
||||||
|
let value = Value::List {
|
||||||
|
vals,
|
||||||
|
span: call.head,
|
||||||
|
};
|
||||||
let expressions = NuExpression::extract_exprs(value)?;
|
let expressions = NuExpression::extract_exprs(value)?;
|
||||||
|
|
||||||
if expressions
|
if expressions
|
||||||
@ -59,20 +70,20 @@ impl Command for LazySelect {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
|
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
|
||||||
let lazy: NuLazyFrame = lazy.select(&expressions).into();
|
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().select(&expressions));
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod test {
|
mod test {
|
||||||
// use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
// use super::*;
|
use super::*;
|
||||||
//
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn test_examples() {
|
fn test_examples() {
|
||||||
// test_dataframe(vec![Box::new(LazySelect {})])
|
test_dataframe(vec![Box::new(LazySelect {})])
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use super::super::values::NuLazyFrame;
|
use super::super::values::NuLazyFrame;
|
||||||
use crate::dataframe::values::NuExpression;
|
use crate::dataframe::values::{Column, NuDataFrame, NuExpression};
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -21,26 +21,70 @@ impl Command for LazySortBy {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.required(
|
.rest(
|
||||||
"filter expression",
|
"sort expression",
|
||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"filtering expression",
|
"sort expression for the dataframe",
|
||||||
)
|
)
|
||||||
.named(
|
.named(
|
||||||
"reverse",
|
"reverse",
|
||||||
SyntaxShape::List(Box::new(SyntaxShape::Boolean)),
|
SyntaxShape::List(Box::new(SyntaxShape::Boolean)),
|
||||||
"list indicating if reverse search should be done in the column. Default is false",
|
"Reverse sorting. Default is false",
|
||||||
Some('r'),
|
Some('r'),
|
||||||
)
|
)
|
||||||
.category(Category::Custom("lazyframe".into()))
|
.category(Category::Custom("lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![
|
||||||
description: "",
|
Example {
|
||||||
example: "",
|
description: "Sort dataframe by one column",
|
||||||
result: None,
|
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr to-df | dfr sort-by a",
|
||||||
}]
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![Value::test_int(1), Value::test_int(4), Value::test_int(6)],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![Value::test_int(4), Value::test_int(1), Value::test_int(2)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Sort column using two columns",
|
||||||
|
example:
|
||||||
|
"[[a b]; [6 2] [1 1] [1 4] [2 4]] | dfr to-df | dfr sort-by [a b] -r [false true]",
|
||||||
|
result: Some(
|
||||||
|
NuDataFrame::try_from_columns(vec![
|
||||||
|
Column::new(
|
||||||
|
"a".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(2),
|
||||||
|
Value::test_int(6),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![
|
||||||
|
Value::test_int(4),
|
||||||
|
Value::test_int(1),
|
||||||
|
Value::test_int(4),
|
||||||
|
Value::test_int(2),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Span::test_data()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -50,7 +94,11 @@ impl Command for LazySortBy {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let value: Value = call.req(engine_state, stack, 0)?;
|
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
||||||
|
let value = Value::List {
|
||||||
|
vals,
|
||||||
|
span: call.head,
|
||||||
|
};
|
||||||
let expressions = NuExpression::extract_exprs(value)?;
|
let expressions = NuExpression::extract_exprs(value)?;
|
||||||
|
|
||||||
let reverse: Option<Vec<bool>> = call.get_flag(engine_state, stack, "reverse")?;
|
let reverse: Option<Vec<bool>> = call.get_flag(engine_state, stack, "reverse")?;
|
||||||
@ -76,25 +124,25 @@ impl Command for LazySortBy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
|
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
|
||||||
let lazy: NuLazyFrame = lazy
|
let lazy = NuLazyFrame::new(
|
||||||
.into_polars()
|
lazy.from_eager,
|
||||||
.sort_by_exprs(&expressions, reverse)
|
lazy.into_polars().sort_by_exprs(&expressions, reverse),
|
||||||
.into();
|
);
|
||||||
|
|
||||||
Ok(PipelineData::Value(
|
Ok(PipelineData::Value(
|
||||||
NuLazyFrame::into_value(lazy, call.head),
|
NuLazyFrame::into_value(lazy, call.head)?,
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod test {
|
mod test {
|
||||||
// use super::super::super::test_dataframe::test_dataframe;
|
use super::super::super::test_dataframe::test_dataframe;
|
||||||
// use super::*;
|
use super::*;
|
||||||
//
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn test_examples() {
|
fn test_examples() {
|
||||||
// test_dataframe(vec![Box::new(LazySortBy {})])
|
test_dataframe(vec![Box::new(LazySortBy {})])
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use super::super::values::{NuDataFrame, NuLazyFrame};
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature,
|
Category, Example, PipelineData, ShellError, Signature, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -39,7 +39,11 @@ impl Command for ToLazyFrame {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let df = NuDataFrame::try_from_iter(input.into_iter())?;
|
let df = NuDataFrame::try_from_iter(input.into_iter())?;
|
||||||
let lazy = NuLazyFrame::from_dataframe(df);
|
let lazy = NuLazyFrame::from_dataframe(df);
|
||||||
|
let value = Value::CustomValue {
|
||||||
|
val: Box::new(lazy),
|
||||||
|
span: call.head,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(value, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ impl Command for IsNotNull {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
|
Signature::build(self.name()).category(Category::Custom("dataframe or lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -20,7 +20,7 @@ impl Command for IsNull {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
|
Signature::build(self.name()).category(Category::Custom("dataframe or expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -22,7 +22,7 @@ impl Command for NotSeries {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
|
Signature::build(self.name()).category(Category::Custom("dataframe or lazyframes".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -45,7 +45,7 @@ impl Command for NotSeries {
|
|||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Creates a not expression from a column",
|
description: "Creates a not expression from a column",
|
||||||
example: "dfr col a | dfr not",
|
example: "((dfr col a) > 2) | dfr not",
|
||||||
result: None,
|
result: None,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -17,7 +17,6 @@ mod arg_min;
|
|||||||
mod cumulative;
|
mod cumulative;
|
||||||
mod n_null;
|
mod n_null;
|
||||||
mod n_unique;
|
mod n_unique;
|
||||||
mod rename;
|
|
||||||
mod rolling;
|
mod rolling;
|
||||||
mod shift;
|
mod shift;
|
||||||
mod unique;
|
mod unique;
|
||||||
@ -32,7 +31,6 @@ pub use arg_min::ArgMin;
|
|||||||
pub use cumulative::Cumulative;
|
pub use cumulative::Cumulative;
|
||||||
pub use n_null::NNull;
|
pub use n_null::NNull;
|
||||||
pub use n_unique::NUnique;
|
pub use n_unique::NUnique;
|
||||||
pub use rename::Rename;
|
|
||||||
pub use rolling::Rolling;
|
pub use rolling::Rolling;
|
||||||
pub use shift::Shift;
|
pub use shift::Shift;
|
||||||
pub use unique::Unique;
|
pub use unique::Unique;
|
||||||
@ -80,7 +78,6 @@ pub fn add_series_decls(working_set: &mut StateWorkingSet) {
|
|||||||
NNull,
|
NNull,
|
||||||
NUnique,
|
NUnique,
|
||||||
NotSeries,
|
NotSeries,
|
||||||
Rename,
|
|
||||||
Replace,
|
Replace,
|
||||||
ReplaceAll,
|
ReplaceAll,
|
||||||
Rolling,
|
Rolling,
|
||||||
|
@ -11,7 +11,7 @@ pub struct NUnique;
|
|||||||
|
|
||||||
impl Command for NUnique {
|
impl Command for NUnique {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"dfr count-unique"
|
"dfr n-unique"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -19,14 +19,14 @@ impl Command for NUnique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
|
Signature::build(self.name()).category(Category::Custom("dataframe or expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
description: "Counts unique values",
|
description: "Counts unique values",
|
||||||
example: "[1 1 2 2 3 3 4] | dfr to-df | dfr count-unique",
|
example: "[1 1 2 2 3 3 4] | dfr to-df | dfr n-unique",
|
||||||
result: Some(
|
result: Some(
|
||||||
NuDataFrame::try_from_columns(vec![Column::new(
|
NuDataFrame::try_from_columns(vec![Column::new(
|
||||||
"count_unique".to_string(),
|
"count_unique".to_string(),
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
use super::super::values::{Column, NuDataFrame};
|
|
||||||
|
|
||||||
use nu_engine::CallExt;
|
|
||||||
use nu_protocol::{
|
|
||||||
ast::Call,
|
|
||||||
engine::{Command, EngineState, Stack},
|
|
||||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Rename;
|
|
||||||
|
|
||||||
impl Command for Rename {
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
"dfr rename"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
|
||||||
"Renames a series"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
|
||||||
Signature::build(self.name())
|
|
||||||
.required("name", SyntaxShape::String, "new series name")
|
|
||||||
.category(Category::Custom("dataframe".into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
|
||||||
vec![Example {
|
|
||||||
description: "Renames a series",
|
|
||||||
example: "[5 6 7 8] | dfr to-df | dfr rename new_name",
|
|
||||||
result: Some(
|
|
||||||
NuDataFrame::try_from_columns(vec![Column::new(
|
|
||||||
"new_name".to_string(),
|
|
||||||
vec![
|
|
||||||
Value::test_int(5),
|
|
||||||
Value::test_int(6),
|
|
||||||
Value::test_int(7),
|
|
||||||
Value::test_int(8),
|
|
||||||
],
|
|
||||||
)])
|
|
||||||
.expect("simple df for test should not fail")
|
|
||||||
.into_value(Span::test_data()),
|
|
||||||
),
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(
|
|
||||||
&self,
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
call: &Call,
|
|
||||||
input: PipelineData,
|
|
||||||
) -> Result<PipelineData, ShellError> {
|
|
||||||
command(engine_state, stack, call, input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command(
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
call: &Call,
|
|
||||||
input: PipelineData,
|
|
||||||
) -> Result<PipelineData, ShellError> {
|
|
||||||
let name: String = call.req(engine_state, stack, 0)?;
|
|
||||||
|
|
||||||
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
|
|
||||||
let mut series = df.as_series(call.head)?;
|
|
||||||
series.rename(&name);
|
|
||||||
|
|
||||||
NuDataFrame::try_from_series(vec![series], call.head)
|
|
||||||
.map(|df| PipelineData::Value(NuDataFrame::into_value(df, call.head), None))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::super::super::test_dataframe::test_dataframe;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_examples() {
|
|
||||||
test_dataframe(vec![Box::new(Rename {})])
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,10 +27,10 @@ impl Command for Shift {
|
|||||||
.named(
|
.named(
|
||||||
"fill",
|
"fill",
|
||||||
SyntaxShape::Any,
|
SyntaxShape::Any,
|
||||||
"Expression to use to fill the null values (lazy df)",
|
"Expression used to fill the null values (lazy df)",
|
||||||
Some('f'),
|
Some('f'),
|
||||||
)
|
)
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or lazyframe".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -106,7 +106,7 @@ fn command_lazy(
|
|||||||
None => lazy.shift(shift).into(),
|
None => lazy.shift(shift).into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -40,11 +40,12 @@ impl Command for Unique {
|
|||||||
"Keep the same order as the original DataFrame (lazy df)",
|
"Keep the same order as the original DataFrame (lazy df)",
|
||||||
Some('k'),
|
Some('k'),
|
||||||
)
|
)
|
||||||
.category(Category::Custom("dataframe".into()))
|
.category(Category::Custom("dataframe or expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![
|
||||||
|
Example {
|
||||||
description: "Returns unique values from a series",
|
description: "Returns unique values from a series",
|
||||||
example: "[2 2 2 2 2] | dfr to-df | dfr unique",
|
example: "[2 2 2 2 2] | dfr to-df | dfr unique",
|
||||||
result: Some(
|
result: Some(
|
||||||
@ -55,7 +56,13 @@ impl Command for Unique {
|
|||||||
.expect("simple df for test should not fail")
|
.expect("simple df for test should not fail")
|
||||||
.into_value(Span::test_data()),
|
.into_value(Span::test_data()),
|
||||||
),
|
),
|
||||||
}]
|
},
|
||||||
|
Example {
|
||||||
|
description: "Creates a is unique expression from a column",
|
||||||
|
example: "dfr col a | dfr unique",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -134,7 +141,7 @@ fn command_lazy(
|
|||||||
lazy.unique_stable(subset, strategy).into()
|
lazy.unique_stable(subset, strategy).into()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(PipelineData::Value(lazy.into_value(call.head), None))
|
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -6,6 +6,7 @@ use nu_protocol::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::eager::ToDataFrame;
|
use super::eager::ToDataFrame;
|
||||||
|
use super::lazy::{LazyCollect, ToLazyFrame};
|
||||||
use crate::Let;
|
use crate::Let;
|
||||||
|
|
||||||
pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
|
pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
|
||||||
@ -23,6 +24,8 @@ pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
|
|||||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||||
working_set.add_decl(Box::new(Let));
|
working_set.add_decl(Box::new(Let));
|
||||||
working_set.add_decl(Box::new(ToDataFrame));
|
working_set.add_decl(Box::new(ToDataFrame));
|
||||||
|
working_set.add_decl(Box::new(ToLazyFrame));
|
||||||
|
working_set.add_decl(Box::new(LazyCollect));
|
||||||
|
|
||||||
// Adding the command that is being tested to the working set
|
// Adding the command that is being tested to the working set
|
||||||
for cmd in cmds {
|
for cmd in cmds {
|
||||||
|
@ -2,9 +2,11 @@ mod nu_dataframe;
|
|||||||
mod nu_expression;
|
mod nu_expression;
|
||||||
mod nu_lazyframe;
|
mod nu_lazyframe;
|
||||||
mod nu_lazygroupby;
|
mod nu_lazygroupby;
|
||||||
|
mod nu_when;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub use nu_dataframe::{Axis, Column, NuDataFrame};
|
pub use nu_dataframe::{Axis, Column, NuDataFrame};
|
||||||
pub use nu_expression::NuExpression;
|
pub use nu_expression::NuExpression;
|
||||||
pub use nu_lazyframe::NuLazyFrame;
|
pub use nu_lazyframe::NuLazyFrame;
|
||||||
pub use nu_lazygroupby::NuLazyGroupBy;
|
pub use nu_lazygroupby::NuLazyGroupBy;
|
||||||
|
pub use nu_when::NuWhen;
|
||||||
|
@ -715,7 +715,7 @@ pub fn from_parsed_columns(column_values: ColumnMap) -> Result<NuDataFrame, Shel
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataFrame::new(df_series)
|
DataFrame::new(df_series)
|
||||||
.map(NuDataFrame::new)
|
.map(|df| NuDataFrame::new(false, df))
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
ShellError::GenericError(
|
ShellError::GenericError(
|
||||||
"Error creating dataframe".into(),
|
"Error creating dataframe".into(),
|
||||||
|
@ -12,7 +12,10 @@ impl CustomValue for NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clone_value(&self, span: nu_protocol::Span) -> Value {
|
fn clone_value(&self, span: nu_protocol::Span) -> Value {
|
||||||
let cloned = NuDataFrame(self.0.clone());
|
let cloned = NuDataFrame {
|
||||||
|
df: self.df.clone(),
|
||||||
|
from_lazy: false,
|
||||||
|
};
|
||||||
|
|
||||||
Value::CustomValue {
|
Value::CustomValue {
|
||||||
val: Box::new(cloned),
|
val: Box::new(cloned),
|
||||||
|
@ -8,11 +8,11 @@ pub use operations::Axis;
|
|||||||
|
|
||||||
use indexmap::map::IndexMap;
|
use indexmap::map::IndexMap;
|
||||||
use nu_protocol::{did_you_mean, PipelineData, ShellError, Span, Value};
|
use nu_protocol::{did_you_mean, PipelineData, ShellError, Span, Value};
|
||||||
use polars::prelude::{DataFrame, DataType, PolarsObject, Series};
|
use polars::prelude::{DataFrame, DataType, IntoLazy, LazyFrame, PolarsObject, Series};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{cmp::Ordering, fmt::Display, hash::Hasher};
|
use std::{cmp::Ordering, fmt::Display, hash::Hasher};
|
||||||
|
|
||||||
use super::utils::DEFAULT_ROWS;
|
use super::{utils::DEFAULT_ROWS, NuLazyFrame};
|
||||||
|
|
||||||
// DataFrameValue is an encapsulation of Nushell Value that can be used
|
// DataFrameValue is an encapsulation of Nushell Value that can be used
|
||||||
// to define the PolarsObject Trait. The polars object trait allows to
|
// to define the PolarsObject Trait. The polars object trait allows to
|
||||||
@ -70,29 +70,39 @@ impl PolarsObject for DataFrameValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct NuDataFrame(DataFrame);
|
pub struct NuDataFrame {
|
||||||
|
pub df: DataFrame,
|
||||||
|
pub from_lazy: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl AsRef<DataFrame> for NuDataFrame {
|
impl AsRef<DataFrame> for NuDataFrame {
|
||||||
fn as_ref(&self) -> &polars::prelude::DataFrame {
|
fn as_ref(&self) -> &polars::prelude::DataFrame {
|
||||||
&self.0
|
&self.df
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsMut<DataFrame> for NuDataFrame {
|
impl AsMut<DataFrame> for NuDataFrame {
|
||||||
fn as_mut(&mut self) -> &mut polars::prelude::DataFrame {
|
fn as_mut(&mut self) -> &mut polars::prelude::DataFrame {
|
||||||
&mut self.0
|
&mut self.df
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DataFrame> for NuDataFrame {
|
impl From<DataFrame> for NuDataFrame {
|
||||||
fn from(dataframe: DataFrame) -> Self {
|
fn from(df: DataFrame) -> Self {
|
||||||
Self(dataframe)
|
Self {
|
||||||
|
df,
|
||||||
|
from_lazy: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NuDataFrame {
|
impl NuDataFrame {
|
||||||
pub fn new(dataframe: DataFrame) -> Self {
|
pub fn new(from_lazy: bool, df: DataFrame) -> Self {
|
||||||
Self(dataframe)
|
Self { df, from_lazy }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lazy(&self) -> LazyFrame {
|
||||||
|
self.df.clone().lazy()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_value(span: Span) -> Value {
|
fn default_value(span: Span) -> Value {
|
||||||
@ -102,17 +112,25 @@ impl NuDataFrame {
|
|||||||
|
|
||||||
pub fn dataframe_into_value(dataframe: DataFrame, span: Span) -> Value {
|
pub fn dataframe_into_value(dataframe: DataFrame, span: Span) -> Value {
|
||||||
Value::CustomValue {
|
Value::CustomValue {
|
||||||
val: Box::new(Self::new(dataframe)),
|
val: Box::new(Self::new(false, dataframe)),
|
||||||
span,
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_value(self, span: Span) -> Value {
|
pub fn into_value(self, span: Span) -> Value {
|
||||||
|
if self.from_lazy {
|
||||||
|
let lazy = NuLazyFrame::from_dataframe(self);
|
||||||
|
Value::CustomValue {
|
||||||
|
val: Box::new(lazy),
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Value::CustomValue {
|
Value::CustomValue {
|
||||||
val: Box::new(self),
|
val: Box::new(self),
|
||||||
span,
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn series_to_value(series: Series, span: Span) -> Result<Value, ShellError> {
|
pub fn series_to_value(series: Series, span: Span) -> Result<Value, ShellError> {
|
||||||
match DataFrame::new(vec![series]) {
|
match DataFrame::new(vec![series]) {
|
||||||
@ -170,7 +188,7 @@ impl NuDataFrame {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Self::new(dataframe))
|
Ok(Self::new(false, dataframe))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_from_columns(columns: Vec<Column>) -> Result<Self, ShellError> {
|
pub fn try_from_columns(columns: Vec<Column>) -> Result<Self, ShellError> {
|
||||||
@ -187,9 +205,30 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_from_value(value: Value) -> Result<Self, ShellError> {
|
pub fn try_from_value(value: Value) -> Result<Self, ShellError> {
|
||||||
|
if Self::can_downcast(&value) {
|
||||||
|
Ok(Self::get_df(value)?)
|
||||||
|
} else if NuLazyFrame::can_downcast(&value) {
|
||||||
|
let span = value.span()?;
|
||||||
|
let lazy = NuLazyFrame::try_from_value(value)?;
|
||||||
|
let df = lazy.collect(span)?;
|
||||||
|
Ok(df)
|
||||||
|
} else {
|
||||||
|
Err(ShellError::CantConvert(
|
||||||
|
"lazy or eager dataframe".into(),
|
||||||
|
value.get_type().to_string(),
|
||||||
|
value.span()?,
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_df(value: Value) -> Result<Self, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<Self>() {
|
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<Self>() {
|
||||||
Some(df) => Ok(NuDataFrame(df.0.clone())),
|
Some(df) => Ok(NuDataFrame {
|
||||||
|
df: df.df.clone(),
|
||||||
|
from_lazy: false,
|
||||||
|
}),
|
||||||
None => Err(ShellError::CantConvert(
|
None => Err(ShellError::CantConvert(
|
||||||
"dataframe".into(),
|
"dataframe".into(),
|
||||||
"non-dataframe".into(),
|
"non-dataframe".into(),
|
||||||
@ -220,9 +259,9 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn column(&self, column: &str, span: Span) -> Result<Self, ShellError> {
|
pub fn column(&self, column: &str, span: Span) -> Result<Self, ShellError> {
|
||||||
let s = self.0.column(column).map_err(|_| {
|
let s = self.df.column(column).map_err(|_| {
|
||||||
let possibilities = self
|
let possibilities = self
|
||||||
.0
|
.df
|
||||||
.get_column_names()
|
.get_column_names()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| name.to_string())
|
.map(|name| name.to_string())
|
||||||
@ -232,7 +271,7 @@ impl NuDataFrame {
|
|||||||
ShellError::DidYouMean(option, span)
|
ShellError::DidYouMean(option, span)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let dataframe = DataFrame::new(vec![s.clone()]).map_err(|e| {
|
let df = DataFrame::new(vec![s.clone()]).map_err(|e| {
|
||||||
ShellError::GenericError(
|
ShellError::GenericError(
|
||||||
"Error creating dataframe".into(),
|
"Error creating dataframe".into(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
@ -242,11 +281,14 @@ impl NuDataFrame {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Self(dataframe))
|
Ok(Self {
|
||||||
|
df,
|
||||||
|
from_lazy: false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_series(&self) -> bool {
|
pub fn is_series(&self) -> bool {
|
||||||
self.0.width() == 1
|
self.df.width() == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_series(&self, span: Span) -> Result<Series, ShellError> {
|
pub fn as_series(&self, span: Span) -> Result<Series, ShellError> {
|
||||||
@ -261,7 +303,7 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let series = self
|
let series = self
|
||||||
.0
|
.df
|
||||||
.get_columns()
|
.get_columns()
|
||||||
.get(0)
|
.get(0)
|
||||||
.expect("We have already checked that the width is 1");
|
.expect("We have already checked that the width is 1");
|
||||||
@ -286,7 +328,7 @@ impl NuDataFrame {
|
|||||||
|
|
||||||
// Print is made out a head and if the dataframe is too large, then a tail
|
// Print is made out a head and if the dataframe is too large, then a tail
|
||||||
pub fn print(&self, span: Span) -> Result<Vec<Value>, ShellError> {
|
pub fn print(&self, span: Span) -> Result<Vec<Value>, ShellError> {
|
||||||
let df = &self.0;
|
let df = &self.df;
|
||||||
let size: usize = 20;
|
let size: usize = 20;
|
||||||
|
|
||||||
if df.height() > size {
|
if df.height() > size {
|
||||||
@ -305,7 +347,7 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> usize {
|
pub fn height(&self) -> usize {
|
||||||
self.0.height()
|
self.df.height()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn head(&self, rows: Option<usize>, span: Span) -> Result<Vec<Value>, ShellError> {
|
pub fn head(&self, rows: Option<usize>, span: Span) -> Result<Vec<Value>, ShellError> {
|
||||||
@ -316,7 +358,7 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tail(&self, rows: Option<usize>, span: Span) -> Result<Vec<Value>, ShellError> {
|
pub fn tail(&self, rows: Option<usize>, span: Span) -> Result<Vec<Value>, ShellError> {
|
||||||
let df = &self.0;
|
let df = &self.df;
|
||||||
let to_row = df.height();
|
let to_row = df.height();
|
||||||
let size = rows.unwrap_or(DEFAULT_ROWS);
|
let size = rows.unwrap_or(DEFAULT_ROWS);
|
||||||
let from_row = to_row.saturating_sub(size);
|
let from_row = to_row.saturating_sub(size);
|
||||||
@ -332,12 +374,12 @@ impl NuDataFrame {
|
|||||||
to_row: usize,
|
to_row: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<Vec<Value>, ShellError> {
|
) -> Result<Vec<Value>, ShellError> {
|
||||||
let df = &self.0;
|
let df = &self.df;
|
||||||
let upper_row = to_row.min(df.height());
|
let upper_row = to_row.min(df.height());
|
||||||
|
|
||||||
let mut size: usize = 0;
|
let mut size: usize = 0;
|
||||||
let columns = self
|
let columns = self
|
||||||
.0
|
.df
|
||||||
.get_columns()
|
.get_columns()
|
||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(
|
||||||
|
@ -73,11 +73,11 @@ impl NuDataFrame {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if self.0.height() != rhs.0.height() {
|
if self.df.height() != rhs.df.height() {
|
||||||
return Err(ShellError::IncompatibleParameters {
|
return Err(ShellError::IncompatibleParameters {
|
||||||
left_message: format!("rows {}", self.0.height()),
|
left_message: format!("rows {}", self.df.height()),
|
||||||
left_span: lhs_span,
|
left_span: lhs_span,
|
||||||
right_message: format!("rows {}", rhs.0.height()),
|
right_message: format!("rows {}", rhs.df.height()),
|
||||||
right_span: *rhs_span,
|
right_span: *rhs_span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -119,10 +119,10 @@ impl NuDataFrame {
|
|||||||
let mut columns: Vec<&str> = Vec::new();
|
let mut columns: Vec<&str> = Vec::new();
|
||||||
|
|
||||||
let new_cols = self
|
let new_cols = self
|
||||||
.0
|
.df
|
||||||
.get_columns()
|
.get_columns()
|
||||||
.iter()
|
.iter()
|
||||||
.chain(other.0.get_columns())
|
.chain(other.df.get_columns())
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
let name = if columns.contains(&s.name()) {
|
let name = if columns.contains(&s.name()) {
|
||||||
format!("{}_{}", s.name(), "x")
|
format!("{}_{}", s.name(), "x")
|
||||||
@ -147,10 +147,10 @@ impl NuDataFrame {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(NuDataFrame::new(df_new))
|
Ok(NuDataFrame::new(false, df_new))
|
||||||
}
|
}
|
||||||
Axis::Column => {
|
Axis::Column => {
|
||||||
if self.0.width() != other.0.width() {
|
if self.df.width() != other.df.width() {
|
||||||
return Err(ShellError::IncompatibleParametersSingle(
|
return Err(ShellError::IncompatibleParametersSingle(
|
||||||
"Dataframes with different number of columns".into(),
|
"Dataframes with different number of columns".into(),
|
||||||
span,
|
span,
|
||||||
@ -158,10 +158,10 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self
|
if !self
|
||||||
.0
|
.df
|
||||||
.get_column_names()
|
.get_column_names()
|
||||||
.iter()
|
.iter()
|
||||||
.all(|col| other.0.get_column_names().contains(col))
|
.all(|col| other.df.get_column_names().contains(col))
|
||||||
{
|
{
|
||||||
return Err(ShellError::IncompatibleParametersSingle(
|
return Err(ShellError::IncompatibleParametersSingle(
|
||||||
"Dataframes with different columns names".into(),
|
"Dataframes with different columns names".into(),
|
||||||
@ -170,12 +170,12 @@ impl NuDataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let new_cols = self
|
let new_cols = self
|
||||||
.0
|
.df
|
||||||
.get_columns()
|
.get_columns()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
let other_col = other
|
let other_col = other
|
||||||
.0
|
.df
|
||||||
.column(s.name())
|
.column(s.name())
|
||||||
.expect("Already checked that dataframes have same columns");
|
.expect("Already checked that dataframes have same columns");
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ impl NuDataFrame {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(NuDataFrame::new(df_new))
|
Ok(NuDataFrame::new(false, df_new))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,7 @@ impl NuExpression {
|
|||||||
pub fn can_downcast(value: &Value) -> bool {
|
pub fn can_downcast(value: &Value) -> bool {
|
||||||
match value {
|
match value {
|
||||||
Value::CustomValue { val, .. } => val.as_any().downcast_ref::<Self>().is_some(),
|
Value::CustomValue { val, .. } => val.as_any().downcast_ref::<Self>().is_some(),
|
||||||
|
Value::List { vals, .. } => vals.iter().all(Self::can_downcast),
|
||||||
Value::String { .. } | Value::Int { .. } | Value::Bool { .. } | Value::Float { .. } => {
|
Value::String { .. } | Value::Int { .. } | Value::Bool { .. } | Value::Float { .. } => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ impl CustomValue for NuLazyFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clone_value(&self, span: nu_protocol::Span) -> Value {
|
fn clone_value(&self, span: nu_protocol::Span) -> Value {
|
||||||
let cloned = NuLazyFrame(self.0.clone());
|
let cloned = NuLazyFrame {
|
||||||
|
lazy: self.lazy.clone(),
|
||||||
|
from_eager: self.from_eager,
|
||||||
|
};
|
||||||
|
|
||||||
Value::CustomValue {
|
Value::CustomValue {
|
||||||
val: Box::new(cloned),
|
val: Box::new(cloned),
|
||||||
|
@ -10,7 +10,10 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|||||||
// Polars LazyFrame is behind and Option to allow easy implementation of
|
// Polars LazyFrame is behind and Option to allow easy implementation of
|
||||||
// the Deserialize trait
|
// the Deserialize trait
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct NuLazyFrame(Option<LazyFrame>);
|
pub struct NuLazyFrame {
|
||||||
|
pub lazy: Option<LazyFrame>,
|
||||||
|
pub from_eager: bool,
|
||||||
|
}
|
||||||
|
|
||||||
// Mocked serialization of the LazyFrame object
|
// Mocked serialization of the LazyFrame object
|
||||||
impl Serialize for NuLazyFrame {
|
impl Serialize for NuLazyFrame {
|
||||||
@ -43,7 +46,7 @@ impl AsRef<LazyFrame> for NuLazyFrame {
|
|||||||
fn as_ref(&self) -> &polars::prelude::LazyFrame {
|
fn as_ref(&self) -> &polars::prelude::LazyFrame {
|
||||||
// The only case when there cannot be a lazy frame is if it is created
|
// The only case when there cannot be a lazy frame is if it is created
|
||||||
// using the default function or if created by deserializing something
|
// using the default function or if created by deserializing something
|
||||||
self.0.as_ref().expect("there should always be a frame")
|
self.lazy.as_ref().expect("there should always be a frame")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,35 +54,56 @@ impl AsMut<LazyFrame> for NuLazyFrame {
|
|||||||
fn as_mut(&mut self) -> &mut polars::prelude::LazyFrame {
|
fn as_mut(&mut self) -> &mut polars::prelude::LazyFrame {
|
||||||
// The only case when there cannot be a lazy frame is if it is created
|
// The only case when there cannot be a lazy frame is if it is created
|
||||||
// using the default function or if created by deserializing something
|
// using the default function or if created by deserializing something
|
||||||
self.0.as_mut().expect("there should always be a frame")
|
self.lazy.as_mut().expect("there should always be a frame")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LazyFrame> for NuLazyFrame {
|
impl From<LazyFrame> for NuLazyFrame {
|
||||||
fn from(lazy_frame: LazyFrame) -> Self {
|
fn from(lazy_frame: LazyFrame) -> Self {
|
||||||
Self(Some(lazy_frame))
|
Self {
|
||||||
|
lazy: Some(lazy_frame),
|
||||||
|
from_eager: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NuLazyFrame {
|
impl NuLazyFrame {
|
||||||
pub fn from_dataframe(df: NuDataFrame) -> Self {
|
pub fn new(from_eager: bool, lazy: LazyFrame) -> Self {
|
||||||
let lazy = df.as_ref().clone().lazy();
|
Self {
|
||||||
Self(Some(lazy))
|
lazy: Some(lazy),
|
||||||
|
from_eager,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_value(self, span: Span) -> Value {
|
pub fn from_dataframe(df: NuDataFrame) -> Self {
|
||||||
Value::CustomValue {
|
let lazy = df.as_ref().clone().lazy();
|
||||||
|
Self {
|
||||||
|
lazy: Some(lazy),
|
||||||
|
from_eager: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_value(self, span: Span) -> Result<Value, ShellError> {
|
||||||
|
if self.from_eager {
|
||||||
|
let df = self.collect(span)?;
|
||||||
|
Ok(Value::CustomValue {
|
||||||
|
val: Box::new(df),
|
||||||
|
span,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(Value::CustomValue {
|
||||||
val: Box::new(self),
|
val: Box::new(self),
|
||||||
span,
|
span,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_polars(self) -> LazyFrame {
|
pub fn into_polars(self) -> LazyFrame {
|
||||||
self.0.expect("lazyframe cannot be none to convert")
|
self.lazy.expect("lazyframe cannot be none to convert")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect(self, span: Span) -> Result<NuDataFrame, ShellError> {
|
pub fn collect(self, span: Span) -> Result<NuDataFrame, ShellError> {
|
||||||
self.0
|
self.lazy
|
||||||
.expect("No empty lazy for collect")
|
.expect("No empty lazy for collect")
|
||||||
.collect()
|
.collect()
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@ -91,13 +115,40 @@ impl NuLazyFrame {
|
|||||||
Vec::new(),
|
Vec::new(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(NuDataFrame::new)
|
.map(|df| NuDataFrame {
|
||||||
|
df,
|
||||||
|
from_lazy: !self.from_eager,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_from_value(value: Value) -> Result<Self, ShellError> {
|
pub fn try_from_value(value: Value) -> Result<Self, ShellError> {
|
||||||
|
if Self::can_downcast(&value) {
|
||||||
|
Ok(Self::get_lazy_df(value)?)
|
||||||
|
} else if NuDataFrame::can_downcast(&value) {
|
||||||
|
let df = NuDataFrame::try_from_value(value)?;
|
||||||
|
Ok(NuLazyFrame::from_dataframe(df))
|
||||||
|
} else {
|
||||||
|
Err(ShellError::CantConvert(
|
||||||
|
"lazy or eager dataframe".into(),
|
||||||
|
value.get_type().to_string(),
|
||||||
|
value.span()?,
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_from_pipeline(input: PipelineData, span: Span) -> Result<Self, ShellError> {
|
||||||
|
let value = input.into_value(span);
|
||||||
|
Self::try_from_value(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_lazy_df(value: Value) -> Result<Self, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<Self>() {
|
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<Self>() {
|
||||||
Some(expr) => Ok(Self(expr.0.clone())),
|
Some(expr) => Ok(Self {
|
||||||
|
lazy: expr.lazy.clone(),
|
||||||
|
from_eager: false,
|
||||||
|
}),
|
||||||
None => Err(ShellError::CantConvert(
|
None => Err(ShellError::CantConvert(
|
||||||
"lazy frame".into(),
|
"lazy frame".into(),
|
||||||
"non-dataframe".into(),
|
"non-dataframe".into(),
|
||||||
@ -114,11 +165,6 @@ impl NuLazyFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_from_pipeline(input: PipelineData, span: Span) -> Result<Self, ShellError> {
|
|
||||||
let value = input.into_value(span);
|
|
||||||
Self::try_from_value(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn can_downcast(value: &Value) -> bool {
|
pub fn can_downcast(value: &Value) -> bool {
|
||||||
if let Value::CustomValue { val, .. } = value {
|
if let Value::CustomValue { val, .. } = value {
|
||||||
val.as_any().downcast_ref::<Self>().is_some()
|
val.as_any().downcast_ref::<Self>().is_some()
|
||||||
@ -127,30 +173,17 @@ impl NuLazyFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_is_eager(value: Value) -> Result<(Self, bool), ShellError> {
|
|
||||||
if Self::can_downcast(&value) {
|
|
||||||
Ok((Self::try_from_value(value)?, false))
|
|
||||||
} else if NuDataFrame::can_downcast(&value) {
|
|
||||||
let df = NuDataFrame::try_from_value(value)?;
|
|
||||||
Ok((NuLazyFrame::from_dataframe(df), true))
|
|
||||||
} else {
|
|
||||||
Err(ShellError::CantConvert(
|
|
||||||
"lazy or eager dataframe".into(),
|
|
||||||
value.get_type().to_string(),
|
|
||||||
value.span()?,
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn apply_with_expr<F>(self, expr: NuExpression, f: F) -> Self
|
pub fn apply_with_expr<F>(self, expr: NuExpression, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(LazyFrame, Expr) -> LazyFrame,
|
F: Fn(LazyFrame, Expr) -> LazyFrame,
|
||||||
{
|
{
|
||||||
let df = self.0.expect("Lazy frame must not be empty to apply");
|
let df = self.lazy.expect("Lazy frame must not be empty to apply");
|
||||||
let expr = expr.into_polars();
|
let expr = expr.into_polars();
|
||||||
let new_frame = f(df, expr);
|
let new_frame = f(df, expr);
|
||||||
|
|
||||||
new_frame.into()
|
Self {
|
||||||
|
from_eager: self.from_eager,
|
||||||
|
lazy: Some(new_frame),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,8 @@ impl NuLazyGroupBy {
|
|||||||
from_eager: group.from_eager,
|
from_eager: group.from_eager,
|
||||||
}),
|
}),
|
||||||
None => Err(ShellError::CantConvert(
|
None => Err(ShellError::CantConvert(
|
||||||
"lazy frame".into(),
|
"lazy groupby".into(),
|
||||||
"non-dataframe".into(),
|
"custom value".into(),
|
||||||
span,
|
span,
|
||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
use super::NuWhen;
|
||||||
|
use nu_protocol::{CustomValue, ShellError, Span, Value};
|
||||||
|
|
||||||
|
// CustomValue implementation for NuDataFrame
|
||||||
|
impl CustomValue for NuWhen {
|
||||||
|
fn typetag_name(&self) -> &'static str {
|
||||||
|
"when"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn typetag_deserialize(&self) {
|
||||||
|
unimplemented!("typetag_deserialize")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_value(&self, span: nu_protocol::Span) -> Value {
|
||||||
|
let cloned = self.clone();
|
||||||
|
|
||||||
|
Value::CustomValue {
|
||||||
|
val: Box::new(cloned),
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_string(&self) -> String {
|
||||||
|
self.typetag_name().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_base_value(&self, span: Span) -> Result<Value, ShellError> {
|
||||||
|
let val = match self {
|
||||||
|
NuWhen::WhenThen(_) => "whenthen".into(),
|
||||||
|
NuWhen::WhenThenThen(_) => "whenthenthen".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = Value::String { val, span };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_json(&self) -> nu_json::Value {
|
||||||
|
nu_json::Value::Null
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
79
crates/nu-command/src/dataframe/values/nu_when/mod.rs
Normal file
79
crates/nu-command/src/dataframe/values/nu_when/mod.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
mod custom_value;
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
|
use nu_protocol::{ShellError, Span, Value};
|
||||||
|
use polars::prelude::{col, when, WhenThen, WhenThenThen};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum NuWhen {
|
||||||
|
WhenThen(WhenThen),
|
||||||
|
WhenThenThen(WhenThenThen),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mocked serialization of the LazyFrame object
|
||||||
|
impl Serialize for NuWhen {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mocked deserialization of the LazyFrame object
|
||||||
|
impl<'de> Deserialize<'de> for NuWhen {
|
||||||
|
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
Ok(NuWhen::WhenThen(when(col("a")).then(col("b"))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for NuWhen {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "NuWhen")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WhenThen> for NuWhen {
|
||||||
|
fn from(when_then: WhenThen) -> Self {
|
||||||
|
NuWhen::WhenThen(when_then)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WhenThenThen> for NuWhen {
|
||||||
|
fn from(when_then_then: WhenThenThen) -> Self {
|
||||||
|
NuWhen::WhenThenThen(when_then_then)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NuWhen {
|
||||||
|
pub fn into_value(self, span: Span) -> Value {
|
||||||
|
Value::CustomValue {
|
||||||
|
val: Box::new(self),
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_from_value(value: Value) -> Result<Self, ShellError> {
|
||||||
|
match value {
|
||||||
|
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<Self>() {
|
||||||
|
Some(expr) => Ok(expr.clone()),
|
||||||
|
None => Err(ShellError::CantConvert(
|
||||||
|
"when expression".into(),
|
||||||
|
"non when expression".into(),
|
||||||
|
span,
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
x => Err(ShellError::CantConvert(
|
||||||
|
"when expression".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
|
x.span()?,
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user