Question: I have the following code: import polars as pl from typing import NamedTuple class Event(NamedTuple): name: str description: str def event_table(num) -> list[Event]: events = [] for i in range(num): events.append(Event("name", "description")) return events data = {"events": [1, 2]} df = pl.DataFrame(data).select(events=pl.col("events").map_elements(event_table)) """ shape: (2, 1) ┌───────────────────────────────────┐ │ events │ │ --- │ │ list[struct[2]] │ ╞═══════════════════════════════════╡ │ [{"name","description"}] │ │ [{"name","description"}, {"name"… │ └───────────────────────────────────┘ """  But if the first list is empty, I get a list[list[str]] instead of the list[struct[2]] that I need: data = {"events": [0, 1, 2]} df = pl.DataFrame(data).select(events=pl.col("events").map_elements(event_table)) print(df) """ shape: (3, 1) ┌───────────────────────────────────┐ │ events │ │ --- │ │ list[list[str]] │ ╞═══════════════════════════════════╡ │ [] │ │ [["name", "description"]] │ │ [["name", "description"], ["name… │ └───────────────────────────────────┘ """  I tried using the return_dtype of the map_elements function like: data = {"events": [0, 1, 2]} df = pl.DataFrame(data).select( events=pl.col("events").map_elements( event_table, return_dtype=pl.List(pl.Struct({"name": pl.String, "description": pl.String})), ) )  but this failed with: Traceback (most recent call last): File "script.py", line 18, in <module> df = pl.DataFrame(data).select( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/polars/dataframe/frame.py", line 8193, in select return self.lazy().select(*exprs, **named_exprs).collect(_eager=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/polars/lazyframe/frame.py", line 1943, in collect return wrap_df(ldf.collect()) ^^^^^^^^^^^^^ polars.exceptions.SchemaError: expected output type 'List(Struct([Field { name: "name", dtype: String }, Field { name: "description", dtype: String }]))', got 'List(List(String))'; set `return_dtype` to the proper datatype  How can I get this to work? i need the type of this column to be list[struct[2]] event if the first list is empty.

Answer: Quick fix right now Here's a map_batches implementation that should be at least marginally faster. def event_table(col: pl.Series) -> pl.Series: return pl.Series( [ [ Event("name", "description")._asdict() #note ._asdict() for _ in range(num) ] for num in col ] )  It uses nested list comprehensions which ought to be a bit faster than appending to a list in an explicit for loop but that is a python optimization not polars. pl.DataFrame(data).select(events=pl.col("events").map_batches(event_table)) shape: (3, 1) ┌───────────────────────────────────┐ │ events │ │ --- │ │ list[struct[2]] │ ╞═══════════════════════════════════╡ │ [] │ │ [{"name","description"}] │ │ [{"name","description"}, {"name"… │ └───────────────────────────────────┘  You actually just need to use _asdict() rather than relying on polars to infer what a NamedTuple ought to be. Medium to Long term fix The issue is here specifically that in certain paths, it treats tuples and lists the same and since a NamedTuple is a tuple, that's why it gets returned as a list. This PR makes it check for the _asdict method and shifts to treating it as a dict/struct. With this PR you can do class Event(NamedTuple): name: str description: str def event_table(num: int) -> list[Event]: return [Event("name", "desc") for _ in range(num)] data = {"events": [0, 1, 2]} pl.DataFrame(data).select( events=pl.col("events").map_elements( event_table, return_dtype=pl.List( pl.Struct({"name": pl.String, "description": pl.String}) ), ) ) shape: (3, 1) ┌───────────────────────────────────┐ │ events │ │ --- │ │ list[struct[2]] │ ╞═══════════════════════════════════╡ │ [] │ │ [{"name","desc"}] │ │ [{"name","desc"}, {"name","desc"… │ └───────────────────────────────────┘