Реализация if-else в фрейме данных Python с использованием лямбды при наличии нескольких переменных - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь реализовать логику if-elif или if-else в python при работе с фреймом данных.Я испытываю трудности при работе с несколькими столбцами.

образец фрейма данных

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

Если моя логика if-else основана только на одном столбце - я знаю, как это сделать.

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

Но я хочу изменить столбец «один» на основе значений столбца «два» - и я чувствую, что он будет примерно таким -

lambda x, y: x*100 if y>8 else (x*1 if y<8 else x**2)

Но я не уверенкак указать второй столбец.Я пробовал таким образом, но, очевидно, это неправильно

df['one'] = df["one"]["two"].apply(lambda x, y: x*100 if y>8 else (x*1 if y<8 else x**2))

Вопрос 1 - какой будет правильный синтаксис для приведенного выше кода?

Вопрос 2 -Как реализовать приведенную ниже логику, используя лямбду?

if df['name'].isin(['a','b'])  df['one'] = 100 else df['one'] = df['two']

Если я напишу что-то вроде x.isin (['a', 'b']), это не сработает.

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Применить к столбцам

Использовать pd.DataFrame.apply вместо pd.Series.apply и указать axis=1:

df['one'] = df.apply(lambda row: row['one']*100 if row['two']>8 else \
                     (row['one']*1 if row['two']<8 else row['one']**2), axis=1)

Не читается?Да, я согласен.Давайте попробуем еще раз, но на этот раз переписываем как именованную функцию.

Использование функции

Примечание lambda - это просто анонимная функция.Мы можем явно определить функцию и использовать ее с pd.DataFrame.apply:

def calc(row):
    if row['two'] > 8:
        return row['one'] * 100
    elif row['two'] < 8:
        return row['one']
    else:
        return row['one']**2

df['one'] = df.apply(calc, axis=1)

Readable?Да.Но это не векторизация.Мы перебираем каждый ряд по одному за раз.Мы могли бы также использовать список.Pandas не только для умного форматирования таблиц, вы можете использовать его для векторизованных вычислений, используя массивы в смежных блоках памяти.Итак, давайте попробуем еще раз.

Векторизованные вычисления

Использование numpy.where:

df['one'] = np.where(row['two'] > 8, row['one'] * 100,
                     np.where(row['two'] < 8, row['one'],
                              row['one']**2))

Итак, поехали.Читаемые и эффективны.Мы эффективно векторизовали наши if / else заявления.Значит ли это, что мы делаем больше вычислений, чем необходимо?Да!Но это более чем компенсируется способом , в котором мы выполняем вычисления, то есть с четко определенными блоками памяти, а не указателями.Вы найдете улучшение производительности на порядок.

Другой пример

Ну, мы можем просто использовать numpy.where снова.

df['one'] = np.where(df['name'].isin(['a', 'b']), 100, df['two'])
0 голосов
/ 07 июня 2018

вы можете сделать

df.apply(lambda x: x["one"] + x["two"], axis=1)

, но я не думаю, что такая длинная лямбда, как lambda x: x["one"]*100 if x["two"]>8 else (x["one"]*1 if x["two"]<8 else x["one"]**2), очень питонна.применить принимает любой обратный вызов:

def my_callback(x):
    if x["two"] > 8:
        return x["one"]*100
    elif x["two"] < 8:
        return x["one"]
    else:
        return x["one"]**2

df.apply(my_callback, axis=1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...