Я работаю с библиотекой pandas и хочу добавить два новых столбца в фрейм данных df
с n столбцами (n> 0).
Эти новые столбцы являются результатом применения функции к одному из столбцов во фрейме данных.
Применяемая функция выглядит так:
def calculate(x):
...operate...
return z, y
Один из способов создания нового столбца для функции, возвращающей только значение:
df['new_col']) = df['column_A'].map(a_function)
Итак, что я хочу и безуспешно пробовал (*), это что-то вроде:
(df['new_col_zetas'], df['new_col_ys']) = df['column_A'].map(calculate)
Каким может быть лучший способ добиться этого? Я просмотрел документацию, ничего не понимая.
** df['column_A'].map(calculate)
возвращает серию панд для каждого элемента, состоящего из кортежа z, y. И попытка назначить это двум столбцам фрейма данных приводит к ошибке ValueError. *
На мой взгляд, главный ответ ошибочен. Надеюсь, никто не будет массово импортировать все панды в свое пространство имен с помощью
from pandas import *
. Кроме того,map
метод следует зарезервировать для тех случаев, когда ему передается словарь или серия. Он может выполнять функцию, но это то,apply
для чего используется.Итак, если вы должны использовать вышеуказанный подход, я бы написал его так
На самом деле нет причин использовать здесь zip. Вы можете просто сделать это:
Этот второй метод также намного быстрее на больших DataFrames.
DataFrame создан из 300 000 строк
В 60 раз быстрее, чем zip
В общем, избегайте использования apply
Apply обычно не намного быстрее, чем итерация по списку Python. Давайте проверим производительность цикла for, чтобы сделать то же, что и выше.
Таким образом, это вдвое медленнее, что не является ужасным падением производительности, но если мы цитонизируем вышесказанное, мы получим гораздо лучшую производительность. Предполагая, что вы используете ipython:
Непосредственное назначение без применения
Вы можете получить еще большее увеличение скорости, если используете прямые векторизованные операции.
Это использует преимущества чрезвычайно быстрых векторизованных операций NumPy вместо наших циклов. Теперь у нас есть 30-кратное ускорение по сравнению с оригиналом.
Самый простой тест скорости с
apply
Приведенный выше пример должен ясно показать, насколько медленным
apply
может быть, но для большей ясности давайте рассмотрим самый простой пример. Возведем в квадрат серию из 10 миллионов чисел с применением и безБез применения в 50 раз быстрее
источник
applymap
случае, когда вам нужно реализовать определенную функцию для каждого элемента фрейма данных?func(series)
вместо,series.apply(func)
применим только тогда, когда функция полностью определена с использованием операций, которые ведут себя одинаково как для отдельного значения, так и для серии. Так обстоит дело в примере в первом ответе, но не в вопросе OP, который в более общем плане спрашивает о применении функций к столбцам. 1/2DataFrame({'a': ['Aaron', 'Bert', 'Christopher'], 'b': ['Bold', 'Courageous', 'Distrusted']})
andcalc
is:def calc(x): return x[0], len(x)
thentdf.a.apply(calc))
иcalc(tdf.a)
возвращает очень разные вещи.