Menerapkan fungsi dengan beberapa argumen untuk membuat kolom panda baru

165

Saya ingin membuat kolom baru dalam pandasbingkai data dengan menerapkan fungsi ke dua kolom yang ada. Mengikuti jawaban ini, saya dapat membuat kolom baru ketika saya hanya membutuhkan satu kolom sebagai argumen:

import pandas as pd
df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})

def fx(x):
    return x * x

print(df)
df['newcolumn'] = df.A.apply(fx)
print(df)

Namun, saya tidak tahu bagaimana melakukan hal yang sama ketika fungsi tersebut membutuhkan beberapa argumen. Misalnya, bagaimana cara membuat kolom baru dengan meneruskan kolom A dan kolom B ke fungsi di bawah ini?

def fxy(x, y):
    return x * y
Michael
sumber

Jawaban:

136

Atau, Anda dapat menggunakan fungsi dasar numpy:

>>> import numpy as np
>>> df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> df['new_column'] = np.multiply(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300

atau mengubah fungsi sewenang-wenang dalam kasus umum:

>>> def fx(x, y):
...     return x*y
...
>>> df['new_column'] = np.vectorize(fx)(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300
alko
sumber
2
Terima kasih atas jawabannya! Saya penasaran, apakah ini solusi tercepat?
MV23
6
Versi vektor menggunakan np.vectorize()sangat cepat. Terima kasih.
stackoverflowuser2010
Ini solusi yang bermanfaat. Jika ukuran input argumen ke fungsi x dan y tidak sama, Anda mendapatkan kesalahan. Dalam hal ini, solusi @RomanPekar berfungsi tanpa masalah. Saya tidak membandingkan kinerja.
Ehsan Sadr
Saya tahu ini adalah jawaban lama, tetapi: Saya memiliki kasus tepi, di mana np.vectorizetidak berfungsi. Alasannya adalah, bahwa salah satu kolom adalah tipe pandas._libs.tslibs.timestamps.Timestamp, yang diubah menjadi tipe numpy.datetime64oleh vektorisasi. Kedua jenis ini tidak dapat dipertukarkan, menyebabkan fungsi berperilaku buruk. Ada saran tentang ini? (Selain .applykarena ini tampaknya harus dihindari)
ElRudi
Solusi bagus! kalau-kalau ada yang bertanya-tanya vectorize bekerja dengan baik dan super cepat untuk fungsi perbandingan string juga.
infiniteloop
227

Anda dapat menggunakan contoh @greenAfrican, jika mungkin bagi Anda untuk menulis ulang fungsi Anda. Tetapi jika Anda tidak ingin menulis ulang fungsi Anda, Anda dapat membungkusnya menjadi fungsi anonim di dalam berlaku, seperti ini:

>>> def fxy(x, y):
...     return x * y

>>> df['newcolumn'] = df.apply(lambda x: fxy(x['A'], x['B']), axis=1)
>>> df
    A   B  newcolumn
0  10  20        200
1  20  30        600
2  30  10        300
Roman Pekar
sumber
4
Ini adalah tip yang bagus, dan meninggalkan referensi kolom di dekat panggilan yang berlaku (di dalamnya sebenarnya). Saya menggunakan tip ini dan tip output multi-kolom @toto_tico disediakan untuk menghasilkan 3 kolom, 4 fungsi kolom! Bagus sekali!
RufusVS
7
Wow, sepertinya Anda satu-satunya yang tidak fokus pada contoh minimal OP tetapi menangani seluruh masalah, terima kasih, persis apa yang saya butuhkan! :)
Matt
38

Ini memecahkan masalah:

df['newcolumn'] = df.A * df.B

Anda juga bisa:

def fab(row):
  return row['A'] * row['B']

df['newcolumn'] = df.apply(fab, axis=1)
greenafrican
sumber
10
Jawaban ini memecahkan contoh mainan ini dan akan cukup bagi saya untuk menulis ulang fungsi saya yang sebenarnya, tetapi itu tidak membahas bagaimana menerapkan fungsi yang didefinisikan sebelumnya tanpa menulis ulang ke kolom referensi.
Michael
23

Jika Anda perlu membuat beberapa kolom sekaligus :

  1. Buat kerangka data:

    import pandas as pd
    df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
  2. Buat fungsinya:

    def fab(row):                                                  
        return row['A'] * row['B'], row['A'] + row['B']
  3. Tetapkan kolom baru:

    df['newcolumn'], df['newcolumn2'] = zip(*df.apply(fab, axis=1))
toto_tico
sumber
1
Saya bertanya-tanya bagaimana saya bisa menghasilkan banyak kolom dengan satu berlaku! Saya menggunakan ini dengan jawaban @Roman Pekar untuk menghasilkan fungsi 3 kolom, 4 kolom! Bagus sekali!
RufusVS
15

Satu lagi sintaks gaya bersih dict:

df["new_column"] = df.apply(lambda x: x["A"] * x["B"], axis = 1)

atau,

df["new_column"] = df["A"] * df["B"]
Surya
sumber