Как применить результат функции Python к новому столбцу в фрейме данных Polars

Я пробовал искать, но многие ответы кажутся устаревшими и больше не действительны для текущей версии Polars. Как применить возвращаемый результат функции Python к каждой строке кадра данных Polars? Я хочу передать в функцию всю строку вместо передачи определенных столбцов.

import polars as pl

def test2(auth, row):
    c = row["Group"]
    d = row["Val"]
    return "{}-{}-{}".format(c, str(d), auth)

df = pl.DataFrame({
    'Group': ['A', 'B', 'C', 'D', 'E'],
    'Val': [1001, 1002, 1003, 1004, 1005]
})

auth_token = "xxxxxxxxx"

df = df.with_columns(
    pl.struct(pl.all())
    .map_batches(lambda x: test2(auth_token, x))
    .alias("response")
)

print(df)

Приведенный выше код вызывает эту ошибку. Я не понимаю это сообщение. Где мне следует установить strict=False и зачем это нужно?

Traceback (most recent call last):
  File "c:\Scripting\Python\Development\Test.py", line 29, in <module>
    df = df.with_columns(
  File "c:\Scripting\Python\Development\venv\lib\site-packages\polars\dataframe\frame.py", line 8763, in with_columns
    return self.lazy().with_columns(*exprs, **named_exprs).collect(_eager=True)
  File "c:\Scripting\Python\Development\venv\lib\site-packages\polars\lazyframe\frame.py", line 1942, in collect
    return wrap_df(ldf.collect(callback))
polars.exceptions.ComputeError: TypeError: unexpected value while building Series of type Int64; found value of type String: "C"       

Hint: Try setting `strict=False` to allow passing data with mixed types.

Я знаю, что мог бы сделать это, указав конкретные столбцы, такие как приведенный ниже код, но я хочу передать всю строку, а затем выбрать, какие столбцы будут использоваться внутри функции. Любая помощь будет оценена по достоинству. Спасибо.

df = df.with_columns(
    (
        pl.struct(["Group", "Val"]).map_batches(
            lambda x: test(auth_token, x.struct.field("Group"), x.struct.field("Val"))
        )
    ).alias("api_response")
)

в вашем примере вы можете просто использовать map_elements() вместо map_batches(). Но это будет довольно медленно, потому что вы не используете никакую оптимизацию Polars таким образом.

Roman Pekar 03.07.2024 15:43
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вместо этого вы можете использовать map_elements().

df = df.with_columns(
    pl.struct(pl.all())
    .map_elements(lambda x: test2(auth_token, x))
    .alias("response")
)

┌───────┬──────┬──────────────────┐
│ Group ┆ Val  ┆ response         │
│ ---   ┆ ---  ┆ ---              │
│ str   ┆ i64  ┆ str              │
╞═══════╪══════╪══════════════════╡
│ A     ┆ 1001 ┆ A-1001-xxxxxxxxx │
│ B     ┆ 1002 ┆ B-1002-xxxxxxxxx │
│ C     ┆ 1003 ┆ C-1003-xxxxxxxxx │
│ D     ┆ 1004 ┆ D-1004-xxxxxxxxx │
│ E     ┆ 1005 ┆ E-1005-xxxxxxxxx │
└───────┴──────┴──────────────────┘

Если вы хотите разделить результат функции на несколько столбцов (при условии, что вы можете изменить функцию):

def test2(auth, row):
    c = row["Group"]
    d = row["Val"]
    return {"c": c, "d": str(d), "auth": auth}

(
    df
    .with_columns(
        pl.struct(pl.all())
        .map_elements(lambda x: test2(auth_token, x))
        .alias("response")
    )
).unnest("response")

┌───────┬──────┬─────┬──────┬───────────┐
│ Group ┆ Val  ┆ c   ┆ d    ┆ auth      │
│ ---   ┆ ---  ┆ --- ┆ ---  ┆ ---       │
│ str   ┆ i64  ┆ str ┆ str  ┆ str       │
╞═══════╪══════╪═════╪══════╪═══════════╡
│ A     ┆ 1001 ┆ A   ┆ 1001 ┆ xxxxxxxxx │
│ B     ┆ 1002 ┆ B   ┆ 1002 ┆ xxxxxxxxx │
│ C     ┆ 1003 ┆ C   ┆ 1003 ┆ xxxxxxxxx │
│ D     ┆ 1004 ┆ D   ┆ 1004 ┆ xxxxxxxxx │
│ E     ┆ 1005 ┆ E   ┆ 1005 ┆ xxxxxxxxx │
└───────┴──────┴─────┴──────┴───────────┘

Это сработало отлично. Спасибо. Я неправильно понял разницу между Map_batches и Map_elements.

configure.ng 03.07.2024 16:20

Кстати, знаете ли вы, как разбить ответ функции на отдельные столбцы? Например, вместо того, чтобы объединять значения в одну строку и возвращать их в качестве ответа, я хотел бы вернуть каждое значение (c, d и auth) в отдельные столбцы в фрейме данных? Спасибо.

configure.ng 03.07.2024 17:33

вы можете вернуть кортеж или список из функции, а затем разбить список на столбцы

Roman Pekar 03.07.2024 17:59

Есть ли у вас краткий пример синтаксиса для этого? Если да, то очень признателен. Спасибо!

configure.ng 03.07.2024 18:07

Обновил ответ

Roman Pekar 03.07.2024 18:22

Другие вопросы по теме