Предположим, у меня df
есть столбцы 'ID', 'col_1', 'col_2'
. И я определяю функцию:
f = lambda x, y : my_function_expression
,
Теперь я хочу , чтобы применить f
к df
двум колонкам «S 'col_1', 'col_2'
для поэлементнога рассчитает новый столбец 'col_3'
, несколько как:
df['col_3'] = df[['col_1','col_2']].apply(f)
# Pandas gives : TypeError: ('<lambda>() takes exactly 2 arguments (1 given)'
Как сделать ?
** Добавить образец детали, как показано ниже ***
import pandas as pd
df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']
def get_sublist(sta,end):
return mylist[sta:end+1]
#df['col_3'] = df[['col_1','col_2']].apply(get_sublist,axis=1)
# expect above to output df as below
ID col_1 col_2 col_3
0 1 0 1 ['a', 'b']
1 2 2 4 ['c', 'd', 'e']
2 3 3 5 ['d', 'e', 'f']
f
делаетОтветы:
Вот пример использования
apply
на фрейме данных, с которым я звонюaxis = 1
.Обратите внимание, что отличие состоит в том, что вместо того, чтобы пытаться передать в функцию два значения
f
, перепишите функцию, чтобы принять объект Series pandas, а затем проиндексируйте Series, чтобы получить необходимые значения.В зависимости от вашего варианта использования иногда полезно создать
group
объект pandas , а затем использовать егоapply
в группе.источник
sum
она успешно решается любым из предложенных методов.df
объект, который вы определили, другой подход (с эквивалентными результатами)df.apply(lambda x: x[0] + x[1], axis = 1)
.В Pandas есть чистый, простой способ сделать это:
Это позволяет
f
быть пользовательской функцией с несколькими входными значениями и использует (безопасные) имена столбцов, а не (небезопасные) числовые индексы для доступа к столбцам.Пример с данными (на основе оригинального вопроса):
Выход
print(df)
:Если имена ваших столбцов содержат пробелы или имеют общее имя с существующим атрибутом dataframe, вы можете индексировать в квадратных скобках:
источник
axis=1
столбца and youname
он на самом деле не возвращает данные вашего столбца, аindex
. Похоже на получениеname
вgroupby()
. Я решил это, переименовав мою колонку..loc
в этом примере. Это может понадобиться, если вы адаптируете это к другой проблеме (например, работаете со слайсами).Простое решение:
источник
Интересный вопрос! мой ответ как ниже:
Вывод:
Я изменил имя столбца на ID, J1, J2, J3, чтобы обеспечить идентификатор <J1 <J2 <J3, поэтому столбец отображается в правильной последовательности.
Еще одна краткая версия:
источник
Метод, который вы ищете, - Series.combine. Тем не менее, кажется, что некоторые типы данных необходимо соблюдать осторожность. В вашем примере вы бы (как я делал при тестировании ответа) наивно
Тем не менее, это выдает ошибку:
Мое лучшее предположение состоит в том, что, похоже, ожидается, что результат будет того же типа, что и серия, вызывающая метод (здесь df.col_1). Тем не менее, следующие работы:
источник
То, как вы написали f, требует двух входов. Если вы посмотрите на сообщение об ошибке, оно говорит, что вы не предоставляете два ввода для f, только один. Сообщение об ошибке верно.
Несовпадение связано с тем, что df [['col1', 'col2']] возвращает один кадр данных с двумя столбцами, а не двумя отдельными столбцами.
Вам нужно изменить свой f так, чтобы он принимал один вход, сохранить указанный кадр данных в качестве входного, а затем разбить его на x, y внутри тела функции. Затем делайте все, что вам нужно, и возвращайте одно значение.
Вам нужна эта сигнатура функции, потому что ее синтаксис: .apply (f). Таким образом, f нужно взять одну вещь = dataframe, а не две вещи, которые ожидают ваши текущие f.
Поскольку вы не предоставили основную часть f, я не могу помочь более подробно - но это должно обеспечить выход без фундаментального изменения кода или использования каких-либо других методов, а не применения
источник
Я собираюсь проголосовать за np.vectorize. Он позволяет вам снимать более x столбцов и не иметь дело с кадром данных в функции, поэтому он отлично подходит для функций, которые вы не контролируете или не выполняете что-то вроде отправки 2 столбцов и константы в функцию (например, col_1, col_2, 'Foo').
источник
Возврат списка из
apply
является опасной операцией, поскольку результирующий объект не гарантированно будет Series или DataFrame. И исключения могут быть подняты в некоторых случаях. Давайте рассмотрим простой пример:Есть три возможных результата с возвратом списка из
apply
1) Если длина возвращаемого списка не равна количеству столбцов, возвращается серия списков.
2) Когда длина возвращаемого списка равна количеству столбцов, возвращается DataFrame, и каждый столбец получает соответствующее значение в списке.
3) Если длина возвращаемого списка равна количеству столбцов для первой строки, но имеет хотя бы одну строку, в которой список имеет количество элементов, отличное от количества столбцов, возникает ошибка ValueError.
Отвечая на проблему без применения
Использование
apply
с осью = 1 очень медленно. С помощью базовых итерационных методов можно добиться гораздо большей производительности (особенно для больших наборов данных).Создать больший размер
Задержки
@ Томас ответ
источник
Я уверен, что это не так быстро, как решения, использующие операции Pandas или Numpy, но если вы не хотите переписывать свою функцию, вы можете использовать map. Используя исходные данные примера -
Таким образом, мы можем передать в функцию столько аргументов, сколько захотим. Выход - то, что мы хотели
источник
apply
сaxis=1
Мой пример на ваши вопросы:
источник
Если у вас огромный набор данных, вы можете использовать простой, но более быстрый (время выполнения) способ сделать это с помощью swifter:
источник
Я предполагаю, что вы не хотите менять
get_sublist
функцию, а просто хотите использоватьapply
метод DataFrame для выполнения этой работы. Чтобы получить желаемый результат, я написал две справочные функции:get_sublist_list
иunlist
. Как следует из названия функции, сначала получите список подсписков, затем извлеките этот подсписок из этого списка. Наконец, нам нужно вызватьapply
функцию, чтобыdf[['col_1','col_2']]
впоследствии применить эти две функции к DataFrame.Если вы не используете
[]
для включенияget_sublist
функции, тоget_sublist_list
функция вернет простой список, который будетValueError: could not broadcast input array from shape (3) into shape (2)
создан, как упоминал @Ted Petrou.источник