#python #pandas #dataframe #lambda #apply
Вопрос:
Я пытаюсь применить операцию 'x-y/y'
, являющуюся x
столбцом 'Faturamento'
и y
столбцом 'Custo'
из вызываемого 'df'
фрейма данных , и сохранить результаты в новом вызываемом столбце 'Roi'
.
Моя попытка использовать функцию применить:
df['Roi'] = df.apply(lambda x, y: x['Faturamento']-y['Custo']/y['Custo'], axis=1)
Возвращается:
Ошибка типа: () отсутствует 1 требуемый позиционный аргумент: «y»
Как я могу это сделать?
Комментарии:
1. Попробуйте изменить эту строку на:
df['Roi'] = df.apply(lambda x: (x['Faturamento']-x['Custo'])/x['Custo'], axis=1)
2. Используйте встроенную функцию Pandas, когда это возможно. В этом случае вам не нужно полагаться на
.apply()
функцию и лямбда, которая используется в основном для ситуаций без встроенной функции. Просто используйте операции по столбцам с помощью Pandas, которые лучше всего подходят для этого варианта использования.3. Я собираюсь дать вам несколько контрольных цифр, и вы поймете разницу.
4. Посмотрите на огромную разницу в 833 раза быстрее для встроенной функции Pandas по столбцам по сравнению
.apply
lambda
с функцией для набора данных из 40000 строк. Даже для небольшого набора данных из 4 строк встроенный Pandas работает все еще быстрее.5. Определенно, вам следует использовать встроенную функцию арифметических операций Pandas вместо использования
.apply()
lambda
Ответ №1:
Вы можете просто использовать операцию со столбцом с синтаксисом, подобным простой арифметике. Панды автоматически выровняют индекс для вас, так что вы будете работать строка за строкой для каждой операции.
df['Roi'] = (df['Faturamento'] - df['Custo']) / df['Custo']
или
df['Roi'] = df['Faturamento'] / df['Custo'] - 1
Таким образом, вы можете наслаждаться быстрой векторизованной обработкой Панд, которая была оптимизирована для быстрой работы. Если вы используете .apply()
с включенной функцией лямбда axis=1
, это просто медленный цикл Python в базовой обработке, и он будет медленным.
Контрольный показатель производительности
Тест 1. Маленький df
с 4 рядами
Faturamento Custo
0 50 20
1 10 5
2 5 15
3 100 400
%%timeit
df['Roi'] = df.apply(lambda x: (x['Faturamento']-x['Custo'])/x['Custo'], axis=1)
721 µs ± 3.54 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit
df['Roi'] = df['Faturamento'] / df['Custo'] - 1
490 µs ± 4.83 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Краткое описание: .apply
лямбда занимает 721 µs
, в то время как встроенные Панды занимают 490 µs
: в 1,47 раза быстрее для небольшого набора данных .
Тест 2. Большой df
с 40000 строками
df2 = pd.concat([df] * 10000, ignore_index=True)
%%timeit
df2['Roi'] = df2.apply(lambda x: (x['Faturamento']-x['Custo'])/x['Custo'], axis=1)
639 ms ± 3.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
df2['Roi'] = df2['Faturamento'] / df2['Custo'] - 1
767 µs ± 12.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Сводка: .apply
лямбда занимает 639 ms (= 639,000 µs)
, в то время как встроенные Панды занимают 767 µs
: в 833 раза быстрее для большого набора данных .
Комментарии:
1. ясс!!! спасибо, это работает
2. @CarolVieira Я думаю, что вам следует использовать векторизованную и все же более простую версию, подобную этому решению, вместо того, чтобы по-прежнему использовать
.apply
функцию и лямбда.
Ответ №2:
Я думаю, ты имеешь в виду:
df['Roi'] = df.apply(lambda x: (x['Faturamento']-x['Custo'])/x['Custo'], axis=1)
x
относится к фрейму данных