Применение функции с несколькими аргументами для создания нового столбца панд

165

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

import pandas as pd
df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})

def fx(x):
    return x * x

print(df)
df['newcolumn'] = df.A.apply(fx)
print(df)

Однако я не могу понять, как сделать то же самое, когда функция требует нескольких аргументов. Например, как мне создать новый столбец, передав столбец A и столбец B в функцию ниже?

def fxy(x, y):
    return x * y
Майкл
источник

Ответы:

136

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

>>> import numpy as np
>>> df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> df['new_column'] = np.multiply(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300

или векторизовать произвольную функцию в общем случае:

>>> def fx(x, y):
...     return x*y
...
>>> df['new_column'] = np.vectorize(fx)(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300
ALKO
источник
2
Спасибо за ответ! Мне любопытно, это самое быстрое решение?
MV23
6
Использование векторизованной версии np.vectorize()удивительно быстро. Спасибо.
stackoverflowuser2010
Это полезное решение. Если размер входных аргументов функции x и y не равен, вы получите ошибку. В этом случае решение @RomanPekar работает без проблем. Я не сравнивал производительность.
Садр
Я знаю, что это старый ответ, но: у меня есть крайний случай, в котором np.vectorizeне работает. Причина в том, что один из столбцов имеет тип pandas._libs.tslibs.timestamps.Timestamp, который превращается в тип numpy.datetime64посредством векторизации. Эти два типа не являются взаимозаменяемыми, что приводит к плохому поведению функции. Есть предложения по этому поводу? (За исключением того, .applyчто этого, по-видимому, следует избегать)
ElRudi
Отличное решение! если кому-то интересно, векторизация работает хорошо и очень быстро для функций сравнения строк.
infiniteloop
227

Вы можете пойти с примером @greenAfrican, если вы можете переписать свою функцию. Но если вы не хотите переписывать свою функцию, вы можете обернуть ее в анонимную функцию внутри apply, например:

>>> def fxy(x, y):
...     return x * y

>>> df['newcolumn'] = df.apply(lambda x: fxy(x['A'], x['B']), axis=1)
>>> df
    A   B  newcolumn
0  10  20        200
1  20  30        600
2  30  10        300
Роман Пекар
источник
4
Это отличный совет, и он оставляет ссылки на столбцы рядом с вызовом apply (в нем фактически). Я использовал этот совет и подсказку для вывода из нескольких столбцов @toto_tico, предоставленную для генерации функции 3 столбца, 4 столбца! Прекрасно работает!
RufusVS
7
Ух ты, кажется, ты единственный, кто не фокусируется на голом минимальном примере ОП, но решает всю проблему, спасибо, именно то, что мне нужно! :)
Мэтт
38

Это решает проблему:

df['newcolumn'] = df.A * df.B

Вы также можете сделать:

def fab(row):
  return row['A'] * row['B']

df['newcolumn'] = df.apply(fab, axis=1)
greenafrican
источник
10
Этот ответ решает этот игрушечный пример и мне будет достаточно переписать мою фактическую функцию, но он не рассматривает, как применить ранее определенную функцию, не переписывая ее в ссылочные столбцы.
Майкл
23

Если вам нужно создать несколько столбцов одновременно :

  1. Создайте фрейм данных:

    import pandas as pd
    df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
  2. Создайте функцию:

    def fab(row):                                                  
        return row['A'] * row['B'], row['A'] + row['B']
  3. Назначьте новые столбцы:

    df['newcolumn'], df['newcolumn2'] = zip(*df.apply(fab, axis=1))
toto_tico
источник
1
Мне было интересно, как я могу создать несколько столбцов с одним приложением! Я использовал это с ответом @Roman Pekar, чтобы сгенерировать функцию с 3 столбцами и 4 столбцами! Прекрасно работает!
RufusVS
15

Еще один чистый синтаксис в стиле dict:

df["new_column"] = df.apply(lambda x: x["A"] * x["B"], axis = 1)

или,

df["new_column"] = df["A"] * df["B"]
Surya
источник