Лямбда в том числе, если... elif... else

Я хочу применить лямбда-функцию к столбцу DataFrame, используя if... elif... else в лямбда-функции.

df и код имеют вид. как:

df=pd.DataFrame({"one":[1,2,3,4,5],"two":[6,7,8,9,10]})

df["one"].apply(lambda x: x*10 if x<2 elif x<4 x**2 else x+10)

очевидно, что он не работает. Есть ли способ применить, если.... elif.... else to lambda? Как я могу изменить один и тот же результат с помощью List Comprehension?

Спасибо за любой ответ.

Ответ 1

Гнездо if .. else s:

lambda x: x*10 if x<2 else (x**2 if x<4 else x+10)

Ответ 2

Я не рекомендую использовать apply здесь: его следует избегать, если есть лучшие альтернативы.

Например, если вы выполняете следующую операцию над серией:

if cond1:
    exp1
elif cond2:
    exp2
else:
    exp3

Обычно это хороший вариант использования для np.where или np.select.


numpy.where

Приведенную выше цепочку if else можно записать с помощью

np.where(cond1, exp1, np.where(cond2, exp2, ...))

np.where позволяет вкладывать. С одним уровнем вложенности ваша проблема может быть решена с помощью

df['three'] = (
    np.where(
        df['one'] < 2, 
        df['one'] * 10, 
        np.where(df['one'] < 4, df['one'] ** 2, df['one'] + 10))
df

   one  two  three
0    1    6     10
1    2    7      4
2    3    8      9
3    4    9     14
4    5   10     15

numpy.select

Позволяет гибкий синтаксис и легко расширяемый. Это следует за формой,

np.select([cond1, cond2, ...], [exp1, exp2, ...])

Или, в этом случае,

np.select([cond1, cond2], [exp1, exp2], default=exp3)

df['three'] = (
    np.select(
        condlist=[df['one'] < 2, df['one'] < 4], 
        choicelist=[df['one'] * 10, df['one'] ** 2], 
        default=df['one'] + 10))
df

   one  two  three
0    1    6     10
1    2    7      4
2    3    8      9
3    4    9     14
4    5   10     15

and/or (аналогично if/else)

Аналогично if-else, требует lambda:

df['three'] = df["one"].apply(
    lambda x: (x < 2 and x * 10) or (x < 4 and x ** 2) or x + 10) 

df
   one  two  three
0    1    6     10
1    2    7      4
2    3    8      9
3    4    9     14
4    5   10     15

Понимание списка

Loopy решение, которое все еще быстрее, чем apply.

df['three'] = [x*10 if x<2 else (x**2 if x<4 else x+10) for x in df['one']]
# df['three'] = [
#    (x < 2 and x * 10) or (x < 4 and x ** 2) or x + 10) for x in df['one']
# ]
df
   one  two  three
0    1    6     10
1    2    7      4
2    3    8      9
3    4    9     14
4    5   10     15

Ответ 3

Для удобства чтения я предпочитаю написать функцию, особенно если вы имеете дело со многими условиями. Исходный вопрос:

def parse_values(x):
    if x < 2:
       return x * 10
    elif x < 4:
       return x ** 2
    else:
       return x + 10

df['one'].apply(parse_values)