Return a new `DataFrame` that aggregates the rows of the current `DataFrame`, first optionally grouping by the given expressions. # Example ``` # use datafusion::prelude::*; # use datafusion::error::Result; # use datafusion::functions_aggregate::expr_fn::min; # use datafusion_common::assert_batches_sorted_eq; # #[tokio::main] # async fn main() -> Result<()> { let ctx = SessionContext::new(); let
(
self,
group_expr: Vec<Expr>,
aggr_expr: Vec<Expr>,
)
| 644 | /// # } |
| 645 | /// ``` |
| 646 | pub fn aggregate( |
| 647 | self, |
| 648 | group_expr: Vec<Expr>, |
| 649 | aggr_expr: Vec<Expr>, |
| 650 | ) -> Result<DataFrame> { |
| 651 | let is_grouping_set = matches!(group_expr.as_slice(), [Expr::GroupingSet(_)]); |
| 652 | let aggr_expr_len = aggr_expr.len(); |
| 653 | let options = |
| 654 | LogicalPlanBuilderOptions::new().with_add_implicit_group_by_exprs(true); |
| 655 | let plan = LogicalPlanBuilder::from(self.plan) |
| 656 | .with_options(options) |
| 657 | .aggregate(group_expr, aggr_expr)? |
| 658 | .build()?; |
| 659 | let plan = if is_grouping_set { |
| 660 | let grouping_id_pos = plan.schema().fields().len() - 1 - aggr_expr_len; |
| 661 | // For grouping sets we do a project to not expose the internal grouping id |
| 662 | let exprs = plan |
| 663 | .schema() |
| 664 | .columns() |
| 665 | .into_iter() |
| 666 | .enumerate() |
| 667 | .filter(|(idx, _)| *idx != grouping_id_pos) |
| 668 | .map(|(_, column)| Expr::Column(column)) |
| 669 | .collect::<Vec<_>>(); |
| 670 | LogicalPlanBuilder::from(plan).project(exprs)?.build()? |
| 671 | } else { |
| 672 | plan |
| 673 | }; |
| 674 | Ok(DataFrame { |
| 675 | session_state: self.session_state, |
| 676 | plan, |
| 677 | projection_requires_validation: !is_grouping_set, |
| 678 | }) |
| 679 | } |
| 680 | |
| 681 | /// Return a new DataFrame that adds the result of evaluating one or more |
| 682 | /// window functions ([`Expr::WindowFunction`]) to the existing columns |