คำตอบด้านบนมีข้อบกพร่องในความคิดของฉัน หวังว่าไม่มีใครมวลการนำเข้าทั้งหมดของหมีแพนด้าเข้าไปใน namespace from pandas import *
ของพวกเขาด้วย นอกจากนี้map
ควรสงวนวิธีการไว้สำหรับช่วงเวลาดังกล่าวเมื่อส่งผ่านพจนานุกรมหรือซีรีส์ สามารถใช้ฟังก์ชันได้ แต่นี่คือสิ่งที่apply
ใช้สำหรับ
ดังนั้นถ้าคุณต้องใช้แนวทางข้างต้นฉันจะเขียนแบบนี้
df["A1"], df["A2"] = zip(*df["a"].apply(calculate))
ไม่มีเหตุผลที่จะใช้ zip ที่นี่ คุณสามารถทำได้ง่ายๆ:
df["A1"], df["A2"] = calculate(df['a'])
วิธีที่สองนี้เร็วกว่ามากใน DataFrames ขนาดใหญ่
df = pd.DataFrame({'a': [1,2,3] * 100000, 'b': [2,3,4] * 100000})
DataFrame สร้างด้วย 300,000 แถว
%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)
เร็วกว่าซิป 60 เท่า
โดยทั่วไปควรหลีกเลี่ยงการใช้ Apply
โดยทั่วไปการสมัครจะไม่เร็วไปกว่าการทำซ้ำในรายการ Python มาทดสอบประสิทธิภาพของ for-loop เพื่อทำสิ่งเดียวกันกับด้านบน
%%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)
นี่จึงช้าเป็นสองเท่าซึ่งไม่ใช่การถดถอยของประสิทธิภาพที่แย่มาก แต่ถ้าเราไซ ธ อนข้างต้นเราจะได้ประสิทธิภาพที่ดีขึ้นมาก สมมติว่าคุณกำลังใช้ 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)
มอบหมายโดยตรงโดยไม่ต้องใช้
คุณจะได้รับการปรับปรุงความเร็วให้ดียิ่งขึ้นหากคุณใช้การดำเนินการแบบเวกเตอร์โดยตรง
%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)
สิ่งนี้ใช้ประโยชน์จากการดำเนินการเวกเตอร์ที่รวดเร็วมากของ NumPy แทนการวนซ้ำของเรา ตอนนี้เรามีสปีดอัพ 30 เท่าจากต้นฉบับ
การทดสอบความเร็วที่ง่ายที่สุดด้วย apply
ตัวอย่างข้างต้นควรแสดงให้เห็นอย่างชัดเจนว่าapply
สามารถทำได้ช้าเพียงใด แต่เพื่อให้ชัดเจนเป็นพิเศษลองดูตัวอย่างพื้นฐานที่สุด ลองยกชุดตัวเลข 10 ล้านตัวเลขที่มีและไม่มีใช้
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)
โดยไม่ต้องสมัครจะเร็วขึ้น 50 เท่า
%timeit s ** 2
66 ms ± 2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)