Membuat kolom baru berdasarkan kondisi if-elif-else

100

Saya memiliki DataFrame df:

    A    B
a   2    2 
b   3    1
c   1    3

Saya ingin membuat kolom baru berdasarkan kriteria berikut:

jika baris A == B: 0

jika barisA > B: 1

jika baris A < B: -1

Jadi mengingat tabel di atas, seharusnya:

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

Untuk if elsekasus - kasus umum yang saya lakukan np.where(df.A > df.B, 1, -1), apakah panda menyediakan sintaks khusus untuk menyelesaikan masalah saya dengan satu langkah (tanpa perlu membuat 3 kolom baru dan kemudian menggabungkan hasilnya)?

gila
sumber
Anda bisa saja mendefinisikan sebuah fungsi dan meneruskan ini ke applydan mengaturnya axis=1akan berhasil, saya tidak yakin saya bisa memikirkan operasi yang akan memberi Anda apa yang Anda inginkan
EdChum
Solusi Anda menyiratkan membuat 3 kolom dan menggabungkannya menjadi 1 kolom, atau Anda memiliki pemikiran yang berbeda?
nutship
Anda terus mengatakan "membuat 3 kolom", tetapi saya tidak yakin apa yang Anda maksud.
DSM
1
@DSM telah menjawab pertanyaan ini tetapi yang saya maksud adalah di df['C']=df.apply(myFunc(row), axis=1)mana myFunc melakukan apa yang Anda inginkan, ini tidak melibatkan pembuatan '3 kolom'
EdChum

Jawaban:

146

Untuk memformalkan beberapa pendekatan yang diuraikan di atas:

Buat fungsi yang beroperasi pada baris dataframe Anda seperti ini:

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

Kemudian terapkan ke dataframe Anda dengan memasukkan axis=1opsi:

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

Tentu saja, ini tidak vektor sehingga kinerja mungkin tidak sebaik saat diskalakan ke sejumlah besar rekaman. Namun, menurut saya ini jauh lebih mudah dibaca. Terutama yang berlatar belakang SAS.

Edit

Berikut adalah versi vektornya

df['C'] = np.where(
    df['A'] == df['B'], 0, np.where(
    df['A'] >  df['B'], 1, -1)) 
Zelazny7
sumber
1
Terima kasih, saya mulai dengan panda dan ini sangat membantu +1
nutship
4
Bagaimana jika saya ingin melewatkan parameter lain bersama dengan baris dalam fungsi? Jika saya melakukannya, dikatakan baris tidak ditentukan ..
prashanth manohar
3
Anda harus menggunakan argsparameter .applyfungsi: pandas.pydata.org/pandas-docs/stable/generated/…
Zelazny7
1
Saya pengguna SAS lama yang mempelajari Python, dan pasti ada kurva belajarnya! :-) Sebagai contoh, kode di atas dapat ditulis dalam SAS sebagai: data df; set df; if A=B then C=0; else if A>B then C=1; else C=-1; run;Sangat elegan dan sederhana.
RobertF
1
Jawaban yang terdefinisi dengan baik
Sahil Nagpal
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

Mudah dipecahkan menggunakan pengindeksan. Baris pertama kode berbunyi demikian, jika kolom Asama dengan kolom Bmaka buat dan atur kolom Csama dengan 0.

Brian
sumber
17

Untuk hubungan khusus ini, Anda dapat menggunakan 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
sumber
6

masukkan deskripsi gambar di sini

Katakanlah di atas satu adalah kerangka data asli Anda dan Anda ingin menambahkan kolom baru 'lama'

Jika usia lebih dari 50 maka kami anggap lebih tua = ya jika tidak Salah

langkah 1: Dapatkan indeks baris yang usianya lebih dari 50

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

langkah 2: Menggunakan .loc kita dapat menetapkan nilai baru ke kolom

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

sama untuk usia di bawah kurang dari 50 tahun

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

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

Ravi G
sumber