Используйте спецификатор формата для преобразования столбца float/int в фрейме данных Polars в строку

У меня есть этот код:

import polars as pl
df = pl.DataFrame({'size': [34.2399, 1232.22, -479.1]})
df.with_columns(pl.format('{:,.2f}', pl.col('size')))

Но это не удается:

ValueError - Traceback, line 3
      2 df = pl.DataFrame({'size': [34.2399, 1232.22, -479.1]})
----> 3 df.with_columns(pl.format('{:,.2f}', pl.col('size')))

File polars\functions\as_datatype.py:718, in format(f_string, *args)
    717     msg = "number of placeholders should equal the number of arguments"
--> 718     raise ValueError(msg)

ValueError: number of placeholders should equal the number of arguments

Как я могу отформатировать столбец float или int, используя спецификатор формата, например '{:,.2f}'?

🤔 А знаете ли вы, что...
В Python есть среды разработки, такие как Jupyter Notebook, которые упрощают работу с данными и исследованиями.


3
52
2

Ответы:

pl.format распознает буквальный {}, в отличие от f-строк Python (если вы запустите df.with_columns(pl.format('{:,.2f}')), вы увидите, что {:,.2f} остается неизменным).

Таким образом, вы не можете использовать pl.format так, как хотите (как указано в комментарии к вопросу, это запрос функции).

Вместо этого вы можете использовать один из методов, описанных здесь.

Код pl.format, показывающий, как это работает: он просто разбивает строки на {} (f_string.split("{}")) и объединяет их обратно с выражениями между ними:

def format(f_string: str, *args: Expr | str) -> Expr:
    if f_string.count("{}") != len(args):
        msg = "number of placeholders should equal the number of arguments"
        raise ValueError(msg)

    exprs = []

    arguments = iter(args)
    for i, s in enumerate(f_string.split("{}")):
        if i > 0:
            e = wrap_expr(parse_into_expression(next(arguments)))
            exprs.append(e)

        if len(s) > 0:
            exprs.append(F.lit(s))

    return concat_str(exprs, separator = "")

Решено

Как отметил @mozway, строки общего формата как часть pl.format пока не поддерживаются. Соответствующий запрос функции уже содержит красивую полярную реализацию (наиболее распространенного) форматирования sprint в стиле C.

Если эффективность не является большой проблемой (например, при исследовательском анализе данных), вы можете просто использовать pl.Expr.map_elements и вернуться к простому решению на Python.

df.with_columns(
    pl.col("size").map_elements(lambda x: f"{x:,.2f}", return_dtype=pl.String)
)
shape: (3, 1)
┌──────────┐
│ size     │
│ ---      │
│ str      │
╞══════════╡
│ 34.24    │
│ 1,232.22 │
│ -479.10  │
└──────────┘

Интересные вопросы для изучения