บทความนี้ผมจะพูดถึงเรื่องการสร้างฟังก์ชันขึ้นมาใช้เองใน Python ซึ่งเป็นพื้นฐานที่สำคัญต่อจากที่ได้อธิบายเรื่อง Loop และ RegEx ไปแล้วในบทความก่อน
เดี๋ยวเรามาดูกันครับว่า ฟังก์ชันคืออะไร? ต่างจาก library หรือ method ยังไง? แล้วทำไมเราต้องสร้างฟังก์ชันชึ้นมาเองด้วย?
สารบัญ
ฟังก์ชันคืออะไร?
ฟังก์ชัน มันคือคล้ายๆ กับ “กล่องดำ” ที่คุณเอา input เข้าไป แล้วมีการประมลผลอะไรบางอย่างในกล่องดำนั้น แล้วเราก็จะได้ output ออกมา
ซึ่งถ้าเราใช้ Excel เราก็จะคุ้นเคยกับฟังก์ชันอยู่แล้วล่ะ เช่น ฟังก์ชัน ROUND เอาไว้ปัดตัวเลขตามหลักคณิตศาสตร์ LEN เอาไว้นับจำนวนอักขระ หรือ LEFT เอาไว้สกัดเอาข้อความจากด้านซ้าย
ส่วนใหญ่แล้วสิ่งที่คนทั่วไปทำงานกับฟังก์ชันใน Excel คืออยู่ในฐานะ “ผู้ใช้ฟังก์ชัน” มากกว่าผู้สร้าง ซึ่งถ้าเราเป็นผู้สร้างฟังก์ขันขึ้นมาเองได้ มันจะเจ๋งกว่าเดิมมากเลยนะ
แล้ว library หรือ method ล่ะ?
- Library: คือห้องสมุดที่รวบรวมฟังก์ชันและโค้ดอื่นๆ ที่มีคนทำไว้ให้แล้ว อย่าง
numpy
หรือpandas
คือ library ที่ช่วยในการจัดการข้อมูล ซึ่งเต็มไปด้วยฟังก์ชันมากมาย - Method: มันก็คือฟังก์ชัน ที่ “ผูกติดไว้กับ object” นั่นเอง เช่น string.upper() เราเรียกฟังก์ชัน upper ที่ผูกกับ string ว่า Method ซึ่งถ้าจะสร้าง Method ขึ้นมาเองเราจะต้องไปเรียนรู้เรื่อง OOP ซะก่อน ซึ่งผมจะขอพูดถึงในอนาคต นะครับ
ทำไมต้องสร้างฟังก์ชันขึ้นมาเอง?
การเขียนฟังก์ชันขึ้นมาเองนั้นมีประโยชน์หลายอย่าง ฟังก์ชันนั้นจะเพิ่มความสะดวกให้เรา และทำให้เราไม่ต้องเขียนโค้ดเดิมๆ ซ้ำๆ เพราะเราสามารถเขียนขึ้นมาครั้งเดียวแล้วสามารถเรียกใช้ฟังก์ชันได้เรื่อยๆ ตามต้องการ
รวมถึงลดความซ้ำซ้อน นั่นคือ แก้ไขการทำงานที่เดียว มันก็จะปรับปรุงทุกที่ที่มีการเรียกใช้ฟังก์ชัน แถมยังสามารถเรียกใช้ฟังก์ชันนึงในอีกฟังก์ชันนึงได้ด้วย ซึ่งจะยิ่งเพิ่มพลังให้การเขียน Code เรามหาศาลเลย
และเวลาจะหาจุดที่ผิดพลาด ก็สามารถทำได้ง่าย สะดวกกว่าที่จะไปควานหาใน Code ที่ทุกอย่างถูกเขียนปนกันไว้
เห็นประโยชน์มากมายแล้ว ลองไปดูวิธีสร้างฟังก์ชันดีกว่า
สร้างฟังก์ชันใน Python ยังไง?
การสร้างฟังก์ชันใน Python เนี่ย ทำได้ง่ายที่สุดแล้วเมื่อเทียบกับวิธีการอื่นๆ ใน Excel ทั่วไป (เช่น LAMBDA Function , VBA, หรือ Power Query )
ซึ่งการสร้างฟังก์ชันใน Python สามารถทำได้โดยการใส่คำสั่ง def ดังนี้
def function_name(arguments):
function body
หรือถ้าฟังก์ชันนั้นสามารถให้ค่าผลลัพธ์คืนกลับมาได้ด้วย ก็ใช้คำสั่ง return เพิ่มเข้าไป เช่น
def function_name(arguments):
function body
return xxx
ซึ่งฟังก์ชันใน Python นั้นต่างจาก LAMBDA Function หรือ ฟังก์ชันใน Power Query อย่างนึงก็คือ มันจะ return ค่าออกมา หรือไม่ return ก็ได้นะ แต่ปกติแล้วถ้าเราใช้ใน Excel เราจะมักใช้แบบ return ค่ากลับมาด้วย
ผมขอยกตัวอย่างฟังก์ชันแบบง่ายๆ ก่อนนะ เดี๋ยวตัวซับซ้อนมาทีหลัง
สมมติเราจะสร้างฟังก์ชันที่สามารถคำนวณ ราคาสินค้าหลังหักส่วนลด โดยที่รับ input 2 ตัวคือ ราคาก่อนลด และ %ส่วนลด เราอาจทำดังนี้
def AfterDiscount(OriginalPrice,DiscountRate):
DiscountAmt=OriginalPrice*DiscountRate
AfterDiscountAmt=OriginalPrice-DiscountAmt
return AfterDiscountAmt
เราสามารถกำหนดค่า default ของ input ในฟังก์ชันได้ด้วย การใส่เครื่องหมาย = เช่น
def AfterDiscount(OriginalPrice,DiscountRate=0.2):
DiscountAmt=OriginalPrice*DiscountRate
AfterDiscountAmt=OriginalPrice-DiscountAmt
return AfterDiscountAmt
สรุปความหมาย
- ฟังก์ชันทีเราเขียน ชื่อว่า AfterDiscount
- ซึ่งรับค่า input 2 ค่า คือ OriginalPrice กับ DiscountRate
- OriginalPrice จำเป็นต้องระบุ
- DiscountRate ถ้าไม่ระบุ จะให้ถือว่าเป็น 0.2 หรือ 20% (แต่ถ้ามีการระบุชัดเจนก็จะเชื่อที่เราระบุ)
- วิธีการทำงาน จะเอา 2 ค่านี้ไปคำนวณประมวลผลตามวิธีที่เราระบุ
- แล้วสุดท้ายก็ return ค่าราคาหลังลดแล้วออกมาเป็นผลลัพธ์ของฟังก์ชัน
เรียกใช้ฟังก์ชัน
เวลาจะเรียกใช้งานฟังก์ชัน ก็สามารถพิมพ์เรียกใช้ได้เลยตรงๆ คล้ายๆ ตอนเรียกใช้ฟังก์ชัน Excel นี่แหละ
ชื่อฟังก์ชัน(พารามิเตอร์)
เนื่องจากเรากำหนดฟังก์ชันไว้ว่า AfterDiscount(OriginalPrice,DiscountRate) ดังนั้นเวลาเรียกใช้ฟังก์ชัน ก็ต้องส่งค่าเข้าไป 2 ตัว โดย ตัวแรกคือ OriginalPrice และตัวที่สองคือ DiscountRate นั่นเอง (แต่ DiscountRate จะไม่ใส่ก็ได้)
สมมติผมใส่ไปแบบนี้
AfterDiscount(200,0.1)
#แปลว่า ราคาเริ่มต้น 200 แล้วลดราคา 10%
แต่ถ้าระบุแค่
AfterDiscount(200)
#แปลว่า ราคาเริ่มต้น 200 แล้วตามค่า default ซึ่งก็คือ 0.2 หรือ 20%

ซึ่งแน่นอนว่าเรา link ค่า cell ใน Excel ให้กลายเป็น input ที่จะส่งเข้าฟังก์ชันของเราได้ ซึ่งมันก็จะสามารถทำงานเหมือนสูตร Excel เลย และสามารถเขียนสูตรช่องเดียวแล้ว Copy ลงไปข้างล่างได้ด้วย
AfterDiscount(xl("A4"),xl("B4"))

ลองใช้ร่วมกับความรู้ที่เรียนผ่านมาแล้ว
สมมติผมจะเอาความรู้ที่เราเรียนผ่านมา มาทำฟังก์ชันบ้าง
สมมติว่าเราต้องการดึงเอาเฉพาะตัวเลขออกมาจากข้อความ แล้ว convert แต่ละ item ให้เป็นตัวเลขด้วย เราอาจใช้ความรู้เรื่อง RegEx กับ List Comprehension มาช่วยก็ได้ เช่น
def ExtractNum(OriginalText):
import re
REresult = re.findall('[0-9]+', OriginalText)
result=[int(i) for i in REresult]
return result
ป.ล. เราสามารถ Import Library ในฟังก์ชันก็ได้นะ (แต่อาจจะดูแปลกๆ นิดหน่อย เพราะว่ามันอาจจะมีการเรียกใช้หลายรอบได้)
ถ้าจะให้ดีกว่า คือ import ทีเดียวไปเลย เอาไว้บนสุด แบบนี้
import re
def ExtractNum(OriginalText):
REresult = re.findall('[0-9]+', OriginalText)
result=[int(i) for i in REresult]
return result

ขออีกซักตัวอย่างนึง เพื่อจะทำให้สามารถ TRIM ข้อมูลได้ง่ายๆ แบบ Excel เราอาจสร้างฟังก์ชันแบบนี้ขึ้มาได้
def TrimLikeExcel(OriginalText):
StripText=OriginalText.strip()
TrimText=re.sub(' +', ' ', StripText)
return TrimText
แล้วเราก็สามารถเรียกใช้ฟังก์ชันพวกนี้ อาจจะทำใน DataFrame ก็ได้ โดยที่เราจะใช้ฟังก์ชัน TrimLikeExcel ของเราตรงๆ กับ Series ของ DataFrame ไม่ได้ เพราะเราตั้งใจจะรับค่ามาเป็น Text ธรรมดา
เราต้องใช้ฟังก์ชันเรากับแต่ละ item ใน Series นั้นต่างหาก ซึ่งเราสามารถใช้ method apply หรือ map มาช่วยได้ เช่น
df=xl("CharacterTable[#All]", headers=True)
df["Name"]=df["Name"].map(TrimLikeExcel)
df

Lambda Function
นอกจากการสร้างฟังก์ชันด้วย def ตามที่อธิบายไปข้างต้นทั้งหมดแล้ว มันยังมีวิธีการสร้างฟังก์ชันอีกแบบนึงที่เรียกว่า Lambda Function ด้วย ซึ่งจะเหมาะกับการทำฟังก์ชันเร็วๆ ที่อาจจะใช้แค่ครั้งเดียวใน Code ของเรา
ซึ่งลักษะของ Lambda Function คือ จะมีกี่ argument (input) ก็ได้ แต่มีได้แค่ expression เดียว คือบอกเลยว่าจะทำอะไร โดยไม่ต้องเขียน return เพราะว่ามันจะ return ค่าของ expression ออกมานั่นแหละ
lambda argument(s) : expression
เช่น สมมติว่าจะทำกับฟังก์ชันคำนวณการลดราคา ก็ทำแบบนี้ได้ ซึ่งจะได้ผลกลับมาเป็น function object
lambda OriginalPrice,DiscountRate=0.2 : OriginalPrice*(1-DiscountRate)

แล้วเราสามารถทดสอบฟังก์ชันนี้ ด้วยการใส่วงเล็บต่อท้าย คล้ายๆ กับการทดสอบ LAMBDA ใน Excel เป๊ะๆ เลย เช่น
(lambda OriginalPrice,DiscountRate=0.2 : OriginalPrice*(1-DiscountRate))(200,0.1)

นอกจากนี้เราสามารถเก็บเจ้า function object เนี่ยเข้าไว้ในตัวแปร แล้วเรียกใช้ตัวแปรนั้นเหมือนเป็นฟังก์ชันได้ด้วย (คล้ายกับใน Excel ที่เอา LAMBDA ไปใส่ใน Name Manager) เช่น
AfterDiscountLam=lambda OriginalPrice,DiscountRate=0.2 : OriginalPrice*(1-DiscountRate)

แต่ปกติแล้วเรามักจะเรียกใช้ Lambda Function นี้แบบเร็วๆ ในฟังก์ชันอื่นอีกที หรือ เรียกใช้ในการ Transform อะไรซักอย่าง เช่น ทำใน List Comprehension, Filter, Map, Apply อะไรแบบนี้ซะมากกว่า
เช่น ผมจะเพิ่มคอลัมน์ชื่อที่เป็นพิมพ์ใหญ่ ผมจะใช้ upper ตรงๆ กับ series ของ DataFrame ไม่ได้นะ เพราะ upper มันเป็น String Method แต่ผมอาจจะเขียนแบบโดยใช้ apply หรือ map มาช่วยอีกทีได้
df["NameUpper"]=df["Name"].apply(lambda x:x.upper())
df

ตอนต่อไป
เดี๋ยวตอนต่อไปจะพูดถึงเรื่องของการทำกราฟด้วย Python ด้วย Matplotlib แล้วค่อยไปต่อเรื่อง Machine Learning ครับ
Leave a Reply