การใช้ Lambda กับ Pandas ใน Python
สวัสดีครับทุกคนวันนี้จะมาสาธิตการใช้ lambda กันครับ เนื่องจากไม่ค่อยเห็นคนพูดถึงใน medium เลยอยากนำมาฝากให้กับมือใหม่เหมือนกัน ช่วยให้บอกลา for loop แสนยาวได้ 😂 หรือพี่ๆทีมีประสบการ์ณแล้วมาอ่านก็หวังว่าจะได้อะไรไปบ้างนะครับ :) จะเริ่มจากสาธิตในตัว python เดี่ยวๆก่อนแล้วค่อยไปรวมกับ Pandas นะครับ ใครรู้เรื่องอยู่แล้วข้ามไปตรง Pandas ก่อนได้เลยครับ
Introduction
ก่อนอื่นเลยอธิบายคร่าวๆก่อนนะครับว่า lambda คืออะไร ให้พูดภาษาบ้านๆคือเหมือนกับ function ที่เราเขียนได้ในบรรทัดเดียว สมมติผมจะทำ function ง่ายๆสำหรับการแปลงหน่วยเมตรเป็นเซนติเมตร
def convert(metres):
return metres * 100
ถ้าใช้ lambda แบบนี้ก็ได้เหมือนกันครับและจบในบรรทัดเดียว เหมาะมากๆกับฟังก์ชั่นเล็กๆ
convert = lambda metres: metres * 100
จะกับฟังก์ชั่นหลายตัวแปรหน่อยก็ได้นะครับ lambda จะมี syntax คือแค่
lambda arguments: expression
arguments กี่ตัวก็ได้แต่ expression เดียวนะครับ
เช่น
multiply_num = lambda a, b : a*b
multiply_num(3,5)
output : 15
แต่จุดเด่นๆจริงๆเลยคือเมื่อเราใช้ lambda ร่วมกับ function ที่รับอีก function เป็น argument เช่น map(), filter(), reduce() (ขออนุญาตโชว์แค่ map, filter ก่อนนะครับเพื่อความกระชับ) เพราะ function lambda ไม่จำเป็นต้องตั้งชื่อก่อน
map(func, list) จะรับ function เข้ามาและใช้ function นั้นกับทุกตัวในลิสต์ครับ
ตัวอย่าง:
metres_list = [1, 5, 6, 7, 9, 2, 2.5, 4]
cm_list = list(map(lambda x: x*100, metres_list)))
print(cm_list)
output: [100, 500, 600, 700, 900, 200, 250.0, 400]
ถ้าเราไม่ใช้ lambda อาจจะดูไม่ยาวต่างกันมาก แต่ถ้าต้องทำอะไรแนวนี้เยอะๆ ก็อาจจะเกิดปัญหาว่าเรามีชื่อฟังก์ชั่นเต็มไปหมดกันได้นะครับ 😂 lambda จะเข้ามาช่วยส่วนนี้ได้ lambda ใช้กับ condition ก็ได้นะครับในการกรองโดยใช้ filter เช่น
metres_list = [1, 5, 6, 7, 9, 2, 2.5, 4]
cm_list = list(map(lambda x: x*100, metres_list))
print(list(filter(lambda x: x < 500, cm_list)))
output: [100, 200, 250.0, 400]
Pandas
วันนี้จะ focus ที่การใช้ lambda ร่วมกับ apply() เป็นฟังก์ชั่นของ Dataframe ที่นำ function ที่เราใส่ไปใช้กับข้อมูลนะครับ ทำได้หลายอย่างมากครับ
สมมติว่าผมี dataframe แบบนี้นะครับ
เริ่มจากอะไรชิลๆก่อน สมมติว่าผมอยากเปลี่ยน column height ให้หน่วยเป็นเมตร แทนที่จะใช้ for loop ผมสามารถใช้ lambda ได้เลย
df['height'] = df['height'].apply(lambda cm: cm/100)
df.head()
ตอนนี้ผมก็ได้เป็นแบบนี้แล้วครับ บรรทัดเดียวจบเลย!!😍😍
เช่นเดียวกันสมมติว่าผมอยากเพิ่ม column ที่เป็น BMI ของคนเหล่านี้คำนวณได้จาก น้ำหนัก / ส่วนสูง(เมตร)² ผมก็ใช้ lambda ได้ครับ แต่อันนี้มันใช้ข้อมูลจากสอง column จะเป็นแบบนี้ครับ
df['BMI'] = df.apply(lambda x: round(x['weight'] / x['height'] ** 2), axis=1)
df.head()
จะเห็นได้นะครับรอบนี้สิ่งที่ถูกส่งเข้าไปในฟังก์ชั่นของเราคือทั้ง Dataframe เราก็ access แต่ละ column ได้เหมือนปกติเลยครับ แต่อย่าลืมใส่ axis ด้วยนะครับเพราะรอบนี้ pandas ไม่รู้ว่าเอา column หรือ row ไม่เหมือนตอนที่ใช้แค่กับ column เดียวนะครับ
เอาล่ะทีนี้ลองมาใช้ร่วมกับ condition บ้างดีกว่า!!
เริ่มง่ายๆก่อนสมมติผมอยากเปลี่ยนแถว active ให้ 0= ‘inactive’, 1 = ‘active’
df['active'] = df['active'].apply(lambda x: 'inactive' if x==0 else 'active')
df.head()
ทีนี้ลองกรณีที่มีหลาย condition นะครับ
สมมติผมจะให้จัดเกณฑ์ว่าใครน้ำหนักมากน้อยหรือกลางตามเกณฑ์ BMI < 18.5 = underweight, 18.5–25 = normal, >25 = overweight
ให้ nest ลงไปแบบนี้ได้เลยโดยใช้ () นะครับ เพราะใน lambda ยังใช้ elif ไม่ได้ครับ
df['Class'] = df['BMI'].apply(lambda x: 'Overweight' if x > 25 else ('Normal' if x > 18.5 else 'Underweight'))
df.head()
แค่นี้ก็ได้แล้วครับ หวังว่าทุกคนจะได้ประโยชน์อะไรบ้างนะครับ เชื่อว่ามี use case ให้ใช้แน่นอนครับ! ❤️❤️ ขอบคุณที่อ่านครับ