У меня есть фрейм данных Polars с двумя столбцами, один содержит списки строк, а другой - одну строку. Я хочу применить следующее выражение к обоим столбцам. Однако по какой-то причине isinstance(x, list) не работает должным образом.
def process_column(column_name: str, alias_name: str) -> pl.Expr:
return (
pl.col(column_name).map_elements(
lambda x: " ".join(x) if isinstance(x, list) else x
)
.str.to_lowercase()
.str.split(by = "-")
.list.join(" ")
.alias(alias_name)
)
Вот пример кадра данных
df = pl.DataFrame({
"lists": [["hello", "World"], ["polars", "IS", "fast"]],
"strings": ["foo-hello", "bOO"]
})
Применение process_column к столбцу "strings" дает ожидаемый результат.
df.with_columns(process_column("strings", "processed_string"))
Однако для столбца "lists" ставится SchemaError.
df.with_columns(process_column("lists", "processed_lists"))
polars.exceptions.SchemaError: invalid series dtype: expected `String`, got `list[str]`
Я попробовал использовать map_elements с return_dtype=pl.String. Это не возвращает ошибку, но вывод неправильный.






Я бы начал с проверки того, что происходит при применении pl.Expr.map_elements к столбцу типа List[pl.String] следующим образом.
def check(x):
print(x)
return x
df.with_columns(
pl.col("lists").map_elements(check)
)
shape: (2,)
Series: '' [str]
[
"hello"
"World"
]
shape: (3,)
Series: '' [str]
[
"polars"
"IS"
"fast"
]
shape: (2, 2)
┌──────────────────────────┬───────────┐
│ lists ┆ strings │
│ --- ┆ --- │
│ list[str] ┆ str │
╞══════════════════════════╪═══════════╡
│ ["hello", "World"] ┆ foo-hello │
│ ["polars", "IS", "fast"] ┆ bOO │
└──────────────────────────┴───────────┘
Это говорит о том, что функция, переданная в pl.Expr.map_elements, получает не собственные списки Python, а вместо этого pl.Series объекты. Следовательно, нам следует заменить
lambda x: " ".join(x) if isinstance(x, list) else x
с
lambda x: x.str.concat(" ").item() if isinstance(x, pl.Series) else x
для получения ожидаемого результата.
def process_column(column_name: str, alias_name: str) -> pl.Expr:
return (
pl.col(column_name)
.map_elements(
lambda x: x.str.concat(" ").item() if isinstance(x, pl.Series) else x,
return_dtype=pl.String
)
.str.to_lowercase()
.str.split(by = "-")
.list.join(" ")
.alias(alias_name)
)
df.with_columns(process_column("lists", "processed_lists"))
Примечание. Я также добавил параметр return_dtype=pl.String, чтобы отключить предупреждение о вызове map_elements без указания return_dtype, что может привести к непредсказуемым результатам.
shape: (2, 3)
┌──────────────────────────┬───────────┬─────────────────┐
│ lists ┆ strings ┆ processed_lists │
│ --- ┆ --- ┆ --- │
│ list[str] ┆ str ┆ str │
╞══════════════════════════╪═══════════╪═════════════════╡
│ ["hello", "World"] ┆ foo-hello ┆ hello world │
│ ["polars", "IS", "fast"] ┆ bOO ┆ polars is fast │
└──────────────────────────┴───────────┴─────────────────┘