Polars is_in not accepting reference

Hello,
Can anyone help with my issue in polars?
Unfortunately I have to repost from stackoverflow:

I am trying to filter a dataframe as follows:

    let allowed = Series::from_iter(vec![
        "string1".to_string(),
        "string2".to_string(),
    ]);
    let df = LazyCsvReader::new(&fullpath)
        .has_header(true)
        .finish().unwrap()
        .filter(col("string_id").is_in(&allowed)).collect().unwrap(); 

It looks good to me since the signature of the is_in method looks like this:

fn is_in(
    &self,
    _other: &Series
) -> Result<ChunkedArray<BooleanType>, PolarsError>

from [SeriesTrait in polars::series - Rust]

However, when I compile it I get the following error:

error[E0277]: the trait bound `Expr: From<&polars::prelude::Series>` is not satisfied
    --> src/main.rs:33:40
     |
33   |         .filter(col("string_id").is_in(&allowed)).collect().unwrap();
     |                                  ----- ^^^^^^^^ the trait `From<&polars::prelude::Series>` is not implemented for `Expr`
     |                                  |
     |                                  required by a bound introduced by this call
     |
     = help: the following other types implement trait `From<T>`:
               <Expr as From<&str>>
               <Expr as From<AggExpr>>
               <Expr as From<bool>>
               <Expr as From<f32>>
               <Expr as From<f64>>
               <Expr as From<i32>>
               <Expr as From<i64>>
               <Expr as From<u32>>
               <Expr as From<u64>>
     = note: required for `&polars::prelude::Series` to implement `Into<Expr>`
note: required by a bound in `polars_plan::dsl::<impl Expr>::is_in`
    --> /home/myself/.cargo/registry/src/
     |
1393 |     pub fn is_in<E: Into<Expr>>(self, other: E) -> Self {
     |                     ^^^^^^^^^^ required by this bound in `polars_plan::dsl::<impl Expr>::is_in`

For more information about this error, try `rustc --explain E0277`.

To me this error looks very cryptic. I read the result of rustc --explain E0277 that says "You tried to use a type which doesn't implement some trait in a place which
expected that trait", but this doesn't help in the slightest to identify which type doesn't implement which trait.

  • How do I fix this? Why doesn't it work?

NOTE:
I know that writing lit(allowed) instead of &allowed works, but this is not possible because it prevents using allowed anywhere else.
For example, I would like to do the following, but the following code gets (obviously) an error "use of moved value":

    let df = LazyCsvReader::new(&fullpath)
        .has_header(true)
        .finish().unwrap()
        .with_column(
            when(
                col("firstcolumn").is_in(lit(allowed))
                    .and(
                    col("secondcolumn").is_in(lit(allowed))
                    )
                )
                .then(lit("very good"))
                .otherwise(lit("very bad"))
                .alias("good_bad")
        )
        .collect().unwrap();

Bonus questions:

  • Why does it work with lit(allowed)? Shouldn't I pass the variable by reference as specified in the documentation?
  • How can I repeatedly use a Series for is_in like in the example above without having an error?

You're looking at the wrong is_in. From the error message you can see that it's Expr::is_in

note: required by a bound in `polars_plan::dsl::<impl Expr>::is_in`
    --> /home/myself/.cargo/registry/src/
     |
1393 |     pub fn is_in<E: Into<Expr>>(self, other: E) -> Self {
     |                     ^^^^^^^^^^ required by this bound in `polars_plan::dsl::<impl Expr>::is_in`

Expr::is_in takes in something that implements Into<Expr>, which &Series doesn't.

The error also tells you which type doesn't implement which trait here:

33   |         .filter(col("string_id").is_in(&allowed)).collect().unwrap();
     |                                  ----- ^^^^^^^^ the trait `From<&polars::prelude::Series>` is not implemented for `Expr`

If using an owned value works, you can clone it:

is_in(allowed.clone())

From Series's docs we can see that it's a wrapper around an Arc, so cloning it is not particularly expensive.

Thanks a lot for the answer!

I also tried using is_in(lit(allowed.clone()) , which worked but somehow didn't feel right :sweat_smile:

1 Like