Search code examples
rustrust-polars

In Rust, how to rename all columns of a Polars Dataframe?


Rust newbie here, I want to use Polars to summarize a dataset that didn't come with column names. If I just use df directly, the error was: cannot borrow df as mutable because it is also borrowed as immutable. How to fix it?

use polars::prelude::*;

fn main() {
    let mut df = df! [
        "names" => ["a", "b", "c"],
        "values" => [1, 2, 3],
    ].unwrap();

    let columns = vec![
        "name_chg",
        "value_chg",
    ];

    df
    .get_column_names()
    .iter()
    .zip(columns)
    .for_each(|(old, new)| {df.rename(old, new);}); // cannot borrow `df` as mutable because it is also borrowed as immutable

    println!("{df}");
}

Solution

  • If you want to rename all columns, you can use df.set_column_names.

    use polars::prelude::*;
    
    fn main() {
        let mut df = df! [
            "names" => ["a", "b", "c"],
            "values" => [1, 2, 3],
        ]
        .unwrap();
    
        println!("BEFORE: {df}");
        
        let columns = vec!["name_chg", "value_chg"];    
        df.set_column_names(columns.as_slice()).unwrap();
    
        println!("AFTER: {df}");
    }
    

    This will produce following output:

    BEFORE: shape: (3, 2)
    ┌───────┬────────┐
    │ names ┆ values │
    │ ---   ┆ ---    │
    │ str   ┆ i32    │
    ╞═══════╪════════╡
    │ a     ┆ 1      │
    │ b     ┆ 2      │
    │ c     ┆ 3      │
    └───────┴────────┘
    AFTER: shape: (3, 2)
    ┌──────────┬───────────┐
    │ name_chg ┆ value_chg │
    │ ---      ┆ ---       │
    │ str      ┆ i32       │
    ╞══════════╪═══════════╡
    │ a        ┆ 1         │
    │ b        ┆ 2         │
    │ c        ┆ 3         │
    └──────────┴───────────┘
    

    set_column_names API will zip the current columns and the column names you passed in. And then perform the .rename operation. It's equivalent to

    pub fn set_column_names<S: AsRef<str>>(&mut self, names: &[S]) -> PolarsResult<()> {
            // Skipping other part of the code for brevity
            let columns = mem::take(&mut self.columns);
            self.columns = columns
                .into_iter()
                .zip(names)
                .map(|(s, name)| {
                    let mut s = s;
                    s.rename(name.as_ref());
                    s
                })
                .collect();
            Ok(())
        }