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

  • After a few tries, I think I found a solution without cloning the dataframe.

    the trick was to end the immutable borrow resulted from df.get_column_names(), so I created a new vector of Strings to store the old column names and iterate over the new vector, while making changes to the dataframe. Still not ideal, but sort of acceptable.

    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",
        ];
        // so the way to fix it was to end the immutable borrow created get_column_names()
        let old_cols:Vec<String> = df.get_column_names().iter().map(|s| s.to_owned().to_owned()).collect();
    
        old_cols
        .iter()
        .zip(columns)
        .for_each(
            |(old, new)| {
                df
                .rename(old, new)
                .expect(format!("cannot rename column {old}").as_str());}); 
        println!("{df}");
    }