สร้าง Column ใหม่จาก Condition ด้วย Numpy.where และ Numpy.select

Sasiwut Chaiyadecha
2 min readMar 27, 2020

--

การใช้ Numpy.where และ Numpy.select

การสร้าง Column ใหม่จาก Condition เนี่ย มันโคตรจะเป็นอะไรที่ Basic มากสำหรับการทำโมเดลใด ๆ แล้วก็เป็นเรื่องที่โดนมองข้ามด้วย เพราะมันไม่ค่อยจะเป็นปัญหาเลยด้วยซ้ำ

จากที่เคยแนะนำตัวไปใน Blog ตอนนี้ ว่า ผมเองเป็น SAS User มาก่อน (ซึ่งเขียนจนถึงตอนนี้แล้ว ยังไม่ได้แชร์อะไรเกี่ยวกับ SAS เลย) ช่วงหลังนี้เองเพิ่งจะมาใช้ Python ในการเขียนโมเดล ซึ่งยอมรับว่ามันมีเรื่องดีและเรื่องที่ต้องปรับตัวแตกต่างกันไป

เข้าเรื่องดีกว่า…

การใช้ Condition logic แบบ if… else… นี้มันเป็นพื้นฐานสำหรับ Modeller เลยนะ เอาจริง ๆ มันอาจจะเป็นพื้นฐานสำหรับทุกเรื่องก็ได้ พอเราทำงานบน SAS หรือ Excel มันก็ไม่มีอะไรมาก มันสร้างเขียนคำสั่งได้ง่าย ๆ เช่น

หรือใน Excel ก็เขียนได้ไม่ยากเช่นกัน (คงไม่ต้องเขียนให้ดูมั้ง…) คราวนี้เนี่ย ผมก็อยากใช้ Logic เดียวกัน สร้าง Column ใหม่ใน Pandas dataframe เลยลองค้นหาดู มันก็มีวิธีทำนะ มันต้องเขียนฟังก์ชั่นใหม่ขึ้นมา ที่ม Condition ที่เราต้องการอยู่ แล้วก็ใช้คำสั่ง apply เพื่อรันคำสั่งนั้น ๆ ให้สร้างเป็น Column ใหม่ขึ้นมา หน้าตาก็จะประมาณนี้ (อย่าเพิ่งด่าว่าโง่เลยนะ)

ฟังดูเหมือนมันแค่โง่ แต่มันก็ไม่มีปัญหาอะไรใช่ไหม?

พอใช้งานไปสักพัก… มันเริ่มไม่ไหวแหะ มันเริ่มช้า พอเจอข้อมูลแบบหลายสิบล้าน จนไปถึงร้อยล้าน rows นี่ เครื่องรันไม่ได้เลย ตอนแรกก็โทษเครื่องนะว่าช้า แต่พอมาคิดดี ๆ มันต้องมีวิธีสิ

ค้นไปค้นมา ก็เจอวิธีใช้ numpy.where และ numpy.select คือจริง ๆ ไม่รู้ว่ามันเกิดมาเพราะอะไรหรอก 2 Packages นี้ แต่ว่ามันช่วยงานผมได้เยอะมาก ๆ วันนี้เลยจะมาลองรัน test ความเร็วกัน

การใช้ Numpy.where และ Numpy.select

เริ่มต้นด้วยการ Import packages เหมือนเดิม ครั้งนี้แตกต่างออกไป เพราะไม่ได้เอาข้อมูลจริง ๆ มันทำแล้ว อยากสร้างข้อมูลที่มีจำนวนเยอะ ๆ เพื่อที่จะได้เห็นความเร็วตอน run code การสร้างก็ไม่ได้ยาก random number ระหว่าง 0 ถึง 100 มาทั้งหมด 1 column กับอีกล้านกว่า rows

เรามาเริ่มกันที่ Pandas กันก่อน ครั้งนี้ทดสอบทั้งหมด 2 logic ง่าย ๆ คือ

  1. flag ค่าที่น้อยกว่า 50 กับมากกว่า 50
  2. flag ค่าที่น้อยกว่า 30 อยู่ระหว่าง 31 ถึง 50 และมากกว่า 50

แล้วก็สั่งให้มัน print เวลาออกมา ผลที่ได้คือ

Apply 1 time = 15.393322229385376
Apply 2 time = 24.506651163101196

ใช้เวลานานมากกกกกกก ไม่รู้ทำไมนานขนาดนี้เหมือนกัน หรือเพราะว่ามันไม่ได้เกิดมาเพื่อทำอะไรแบบนี้ ใครรู้รบกวนแชร์ความเห็นหน่อยนะครับ

ต่อมามาลองใช้ Package numpy.where กับ numpy.select กันบ้างนะ โดยจะใช้ Condition เหมือนเดิมเลย ส่วนเรื่อง Syntax ก็ง่ายละสั้นมาก ๆ ตาม Code ข้างล่างได้เลย

numpy.where ใช้สำหรับ 1 เงื่อนไขตามข้อ 1. คือถ้าไม่อย่างใด ก็ต้องทำอย่างหนึ่ง ส่วน numpy.select ใช้สำหรับมากกว่า 1 เงื่อนไขตามข้อ 2. จริง ๆ มันสามารถเขียนแบบไม่ต้องใช้ option default ก็ได้นะ มันก็จะเป็นแบบนี้ df[‘select’] = np.select([df[‘test’] < 30, df[‘test’] < 50, df[‘test’] >= 50], [1,2,3]) อันนี้แล้วแต่คนถนัดของแต่ละคนเลย ส่วนผลลัพธ์ที่ออกมาก็คือ

Where time = 0.009963750839233398
Select time = 0.031511783599853516

บอกได้เลยว่ามันแตกต่างมาก ๆ คราวนี้ใครรู้ว่าเพราะอะไรมันถึงต่างกันขนาดนี้ ช่วยบอกผมหน่อยนะครับ

--

--

Sasiwut Chaiyadecha
Sasiwut Chaiyadecha

No responses yet