Pandas DataFrame применяет функцию к нескольким столбцам и выводит несколько столбцов - PullRequest
2 голосов
/ 11 ноября 2019

Я искал SO для лучшего способа применения функции, которая принимает несколько отдельных столбцов Pandas DataFrame и выводит несколько новых столбцов в одном и том же указанном DataFrame. Допустим, у меня есть следующее:

def apply_func_to_df(df):
    df[['new_A', 'new_B']] = df.apply(lambda x: transform_func(x['A'], x['B'], x['C']), axis=1)

def transform_func(value_A, value_B, value_C):
    # do some processing and transformation and stuff
    return new_value_A, new_value_B

Я пытаюсь применить эту функцию, как показано выше, ко всему фрейму данных df, чтобы вывести 2 НОВЫХ столбца. Тем не менее, это может быть обобщено на случай использования / функцию, который принимает n столбцы DataFrame и выводит m новые столбцы в тот же DataFrame.

Ниже приведены вещи, на которые я смотрел (с различной степеньюуспех):

  • Создать серию Pandas для вызова функции, затем добавить к существующему DataFrame,
  • Сжать выходные столбцы (но в моей текущей реализации есть некоторые проблемы, которые случаются)
  • Переписать базовую функцию transform_func, чтобы явно ожидать строки (т. Е. Поля) A, B, C следующим образом, а затем применить к df:

def transform_func_mod(df_row):
    # do something with df_row['A'], df_row['B'], df_row['C]
    return new_value_A, new_value_B

Я бы хотел очень общий и Pythonic способ выполнить эту задачу, принимая во внимание производительность (как с точки зрения памяти, так и с точки зрения времени). Я был бы признателен за любой вклад в это, так как я боролся с этим из-за моего незнакомства с пандами.

1 Ответ

3 голосов
/ 11 ноября 2019

Напишите transform_func следующим образом:

  • он должен иметь один параметр - текущая строка,
  • эта функция можетчитать отдельные столбцы из текущей строки и использовать их,
  • возвращаемый объект должен быть Series с:
    • значениями - все, что вы хотите вернуть,
    • index - имена целевых столбцов.

Пример. Предполагается, что все 3 столбца имеют тип string , сцепление A и B столбцы, добавьте "некоторую строку" к C :

def transform_func(row):
    a = row.A; b = row.B; c = row.C;
    return pd.Series([ a + b, c + '_xx'], index=['new_A', 'new_B'])

Чтобы получить только новые значения, примените этоФункция для каждой строки:

df.apply(transform_func, axis=1)

Обратите внимание, что результирующий DataFrame сохраняет ключи исходных строк (мы воспользуемся этой функцией через мгновение).

Или, если вы хотите добавьте эти новые столбцы в ваш DataFrame, объедините ваш df с результатом вышеупомянутого приложения, сохранив результат объединения воригинал df :

df = df.join(df.apply(transform_func, axis=1))

Редактировать после комментария по состоянию на 03: 36: 34Z

Использование zip , вероятно, самый медленный вариант. Функция на основе строк должна быть быстрее, и это более интуитивная конструкция. Вероятно, самый быстрый способ - написать 2 векторизованных выражения для каждого столбца отдельно. В этом случае что-то вроде:

df['new_A'] = df.A + df.B
df['new_B'] = df.C + '_xx'

Но, как правило, проблема в том, может ли основанная на строках функция быть выражена как векторизованные выражения (как я делал выше). В «отрицательном» случае вы можете применить основанную на строке функцию.

Чтобы сравнить, насколько быстро каждое решение, используйте % timeit .

...