Jawaban teratas menurut saya salah. Mudah-mudahan, tidak ada yang mengimpor semua panda secara massal ke namespace mereka dengan from pandas import *. Selain itu, mapmetode ini harus disediakan untuk saat-saat ketika meneruskan kamus atau Seri. Ini bisa mengambil fungsi tapi untuk itulah applydigunakan.
Jadi, jika Anda harus menggunakan pendekatan di atas, saya akan menulisnya seperti ini
df["A1"], df["A2"] = zip(*df["a"].apply(calculate))
Sebenarnya tidak ada alasan untuk menggunakan zip di sini. Anda cukup melakukan ini:
df["A1"], df["A2"] = calculate(df['a'])
Metode kedua ini juga jauh lebih cepat pada DataFrames yang lebih besar
df = pd.DataFrame({'a': [1,2,3] * 100000, 'b': [2,3,4] * 100000})
DataFrame dibuat dengan 300.000 baris
%timeit df["A1"], df["A2"] = calculate(df['a'])
2.65 ms ± 92.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df["A1"], df["A2"] = zip(*df["a"].apply(calculate))
159 ms ± 5.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
60x lebih cepat dari zip
Secara umum, hindari penggunaan apply
Penerapan umumnya tidak lebih cepat daripada melakukan iterasi pada daftar Python. Mari kita uji performa for-loop untuk melakukan hal yang sama seperti di atas
%%timeit
A1, A2 = [], []
for val in df['a']:
A1.append(val**2)
A2.append(val**3)
df['A1'] = A1
df['A2'] = A2
298 ms ± 7.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Jadi ini dua kali lebih lambat yang bukan merupakan regresi kinerja yang buruk, tetapi jika kita melakukan cythonisasi di atas, kita mendapatkan kinerja yang jauh lebih baik. Dengan asumsi, Anda menggunakan ipython:
%load_ext cython
%%cython
cpdef power(vals):
A1, A2 = [], []
cdef double val
for val in vals:
A1.append(val**2)
A2.append(val**3)
return A1, A2
%timeit df['A1'], df['A2'] = power(df['a'])
72.7 ms ± 2.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Menugaskan secara langsung tanpa melamar
Anda bisa mendapatkan peningkatan kecepatan yang lebih besar jika Anda menggunakan operasi vektor langsung.
%timeit df['A1'], df['A2'] = df['a'] ** 2, df['a'] ** 3
5.13 ms ± 320 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Ini mengambil keuntungan dari operasi vektorisasi NumPy yang sangat cepat daripada loop kita. Kami sekarang memiliki percepatan 30x dari aslinya.
Tes kecepatan paling sederhana dengan apply
Contoh di atas harus dengan jelas menunjukkan betapa lambatnya applybisa, tetapi agar lebih jelas mari kita lihat contoh paling dasar. Mari kita kuadratkan Seri 10 juta angka dengan dan tanpa menerapkan
s = pd.Series(np.random.rand(10000000))
%timeit s.apply(calc)
3.3 s ± 57.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Tanpa penerapan, 50x lebih cepat
%timeit s ** 2
66 ms ± 2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)