Создание нового столбца на основе условия if-elif-else

100

У меня есть DataFrame df:

    A    B
a   2    2 
b   3    1
c   1    3

Я хочу создать новый столбец на основе следующих критериев:

если строка A == B: 0

если строкаA > B: 1

если строка A < B: -1

поэтому, учитывая приведенную выше таблицу, это должно быть:

    A    B    C
a   2    2    0
b   3    1    1
c   1    3   -1 

Для типичных if elseслучаев, которые я делаю np.where(df.A > df.B, 1, -1), предоставляет ли pandas специальный синтаксис для решения моей проблемы за один шаг (без необходимости создавать 3 новых столбца и затем объединять результат)?

психопат
источник
Вы можете просто определить функцию и передать ее, applyи установка axis=1будет работать, не уверен, что я могу придумать операцию, которая дала бы вам то, что вы хотите
EdChum
Ваше решение подразумевает создание 3 столбцов и объединение их в 1 столбец, или вы имеете в виду что-то другое?
Nutship
Вы все время говорите «создать 3 столбца», но я не совсем понимаю, о чем вы.
DSM
1
@DSM ответил на этот вопрос, но я имел в виду что-то вроде того, df['C']=df.apply(myFunc(row), axis=1)где myFunc делает то, что вы хотите, это не связано с созданием «3 столбцов»
EdChum
1
Возможный дубликат условного создания Pandas столбца series / dataframe
Георгий

Ответы:

146

Чтобы формализовать некоторые из изложенных выше подходов:

Создайте функцию, которая работает со строками вашего фрейма данных следующим образом:

def f(row):
    if row['A'] == row['B']:
        val = 0
    elif row['A'] > row['B']:
        val = 1
    else:
        val = -1
    return val

Затем примените его к своему фрейму данных, передав axis=1параметр:

In [1]: df['C'] = df.apply(f, axis=1)

In [2]: df
Out[2]:
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1

Конечно, это не векторизация, поэтому производительность может быть не такой хорошей при масштабировании до большого количества записей. Тем не менее, я думаю, что это намного более читабельно. Особенно если исходить из опыта работы с SAS.

редактировать

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

df['C'] = np.where(
    df['A'] == df['B'], 0, np.where(
    df['A'] >  df['B'], 1, -1)) 
Желязный7
источник
1
Спасибо, я начинаю с панд, и это было очень полезно +1
nutship
4
Что, если я хочу передать другой параметр вместе со строкой в ​​функции? Если я это сделаю,
prashanth manohar
3
Вы должны использовать argsпараметр .applyфункции: pandas.pydata.org/pandas-docs/stable/generated/…
Zelazny7
1
Я старый пользователь SAS, изучающий Python, и мне определенно нужно научиться! :-) Например, приведенный выше код можно записать на SAS как: data df; set df; if A=B then C=0; else if A>B then C=1; else C=-1; run;Очень элегантно и просто.
RobertF
1
Сахил
51
df.loc[df['A'] == df['B'], 'C'] = 0
df.loc[df['A'] > df['B'], 'C'] = 1
df.loc[df['A'] < df['B'], 'C'] = -1

Легко решить с помощью индексации. Первая строка кода Aвыглядит так: если столбец равен столбцу, Bсоздайте и установите столбец Cравным 0.

Брайан
источник
17

Для этого конкретного отношения вы можете использовать np.sign:

>>> df["C"] = np.sign(df.A - df.B)
>>> df
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1
DSM
источник
6

введите описание изображения здесь

Допустим, выше один - ваш исходный фрейм данных, и вы хотите добавить новый столбец 'старый'.

Если возраст старше 50 лет, мы считаем, что старше = да, в противном случае - неверно

Шаг 1: Получите индексы строк, возраст которых превышает 50

row_indexes=df[df['age']>=50].index

Шаг 2: Используя .loc, мы можем присвоить новое значение столбцу

df.loc[row_indexes,'elderly']="yes"

то же самое для возраста до 50 лет

row_indexes=df[df['age']<50].index

df[row_indexes,'elderly']="no"

Рави Джи
источник