#python #pandas
Вопрос:
Мне интересно, почему функция pandas assign не может обрабатывать возвращаемые списки.
Например
df = pd.DataFrame({
"id" : [1,2,3,4,5],
"val" : [10,20,30,30,40]
})
def squareMe(x):
return x**2
df = df.assign(val2 = lambda x: squareMe(x.val))
# Out > Works fine : Returns a DataFrame with squared values
Но если мы вернем список,
def squareMe(x):
return [x**2]
df = df.assign(val2 = lambda x: squareMe(x.val))
#Out > ValueError: Length of values (1) does not match length of index (5)
Однако функция pandas apply отлично работает при возврате списка
def squareMe(x):
return [x**2]
df["val2"] = df.val.apply(lambda x: squareMe(x))
Есть ли какая-то особая причина, по которой это происходит, или я делаю что-то не так?
Ответ №1:
Поскольку вы ссылаетесь x.val
в вызове на squareMe
, этой функции передается список (вы можете легко проверить это, добавив инструкцию отладки для печати type(x)
внутри функции).
Таким образом, x ** 2
возвращает ряд (поскольку выражение векторизовано), и назначение работает правильно.
Но когда вы возвращаетесь, [x ** 2]
вы возвращаете серии внутри списка, который не имеет смысла применять, поскольку все, что видит, повторяемое из Размер «1» (в серии внутри него) и он считает это неправильные длина для колонки назначение таблицы данных 5-го размера (что ValueError: Length of values (1) does not match length of index (5)
означает).
Разница в apply
том, что функция получает число, а не ряд. И поэтому вы все равно возвращаете один элемент (список), который принимает приложение, но все равно технически неверен, поскольку вам не нужно заключать результат в список.
Дополнительная информация: df.назначить, df.применить
P.S.: вы, вероятно, уже понимаете это, но вы можете упростить это до df['val'] = df['x'] ** 2
Ответ №2:
assign
специально не предназначен для этого, он предназначен для назначения столбцов, уже возвращенных последовательностями в качестве аргументов.
**Параметры : кварги : дикт {str: вызываемый или серия}
Имена столбцов являются ключевыми словами. Если значения можно вызвать, они вычисляются в фрейме данных и присваиваются новым столбцам. Вызываемый объект не должен изменять фрейм входных данных (хотя pandas не проверяет это). Если значения не могут быть вызваны (например, ряд, скаляр или массив), они просто присваиваются.
Выполнение [x ** 2]
возвращает серию списков, которые будут обрабатываться как матрица (или фрейм данных), и, следовательно, как указано в ошибке:
ValueError: Length of values (1) does not match length of index (5)
Длина значений не будет соответствовать индексу.