Series
ผลลัพธ์เป็น Series ถ้าฟังก์ชันคืนค่า scalar ต่อแถว/คอลัมน์ หรือเป็น DataFrame ถ้าฟังก์ชันคืน Series (axis=1) ครับ ส่วนใหญ่ตอน apply บน Series หรือ axis=1 แบบง่ายจะได้ Series กลับมา
| อาร์กิวเมนต์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| func | callable | ฟังก์ชันที่จะรัน รับได้ทั้ง lambda, def function, หรือ numpy function เช่น np.sqrt | |
| [axis]ไม่บังคับ | int | str | 0 | 0 หรือ ‘index’ = รันต่อคอลัมน์ (ค่า default), 1 หรือ ‘columns’ = รันต่อแถว ผมใช้ axis=1 บ่อยกว่าครับตอนอยากคำนวณข้ามคอลัมน์ |
| [raw]ไม่บังคับ | bool | False | False = ส่ง Series เข้าฟังก์ชัน, True = ส่ง ndarray แทน เร็วกว่าถ้าใช้ numpy functions ที่รับ array โดยตรง |
| [result_type]ไม่บังคับ | str | None | None | ใช้ได้เฉพาะ axis=1: ‘expand’ แปลง list เป็นหลายคอลัมน์, ‘reduce’ บีบเป็น Series, ‘broadcast’ คงรูปต้นฉบับ |
| [args]ไม่บังคับ | tuple | () | arguments เพิ่มเติมที่จะส่งเข้าฟังก์ชัน ตามหลัง argument หลักที่ apply ส่งให้อัตโนมัติ |
[ ] = อาร์กิวเมนต์ที่ไม่บังคับ
apply เป็นเหมือนคำสั่ง “วิ่งทีละแถว” ของ pandas ครับ ทำงานในโหมด Split-Apply-Combine คล้ายกับ groupby เลย แต่แทนที่จะแบ่งกลุ่มก่อน มันจะส่งแต่ละแถว (axis=1) หรือแต่ละคอลัมน์ (axis=0) เป็น Series เข้าไปหาฟังก์ชันที่เราเขียน แล้วรวมผลลัพธ์กลับมา ถ้าใช้กับ Series ธรรมดา (ไม่ใช่ DataFrame) มันจะส่งแต่ละค่าทีละตัวเข้าไปเลย
ที่เจ๋งคือ apply รับฟังก์ชันอะไรก็ได้ ทั้ง lambda แบบสั้น, ฟังก์ชันที่เราเขียนเอง หรือฟังก์ชันจาก library อื่นก็ได้ ทำให้มัน flexible มากครับ อยากทำ logic อะไรที่แปลกๆ ก็ทำได้หมด ✨
ส่วนตัวผมใช้ apply เป็น “ทางเลือกสุดท้าย” ครับ 😎 เพราะมัน loop ทีละแถวใน Python ซึ่งช้ากว่า vectorized operations อย่าง `df[‘col’] * 2` หรือ `np.sqrt(df[‘col’])` เยอะมาก ถ้า logic ง่ายๆ ให้ใช้ arithmetic operators หรือ numpy ก่อน apply ค่อยเข้ามาตอนที่ logic ซับซ้อนจริงๆ
ผมรัน lambda กับแต่ละค่าใน Series ครับ แต่ละตัวจะถูก *2 ทีละค่า ได้ Series ใหม่ออกมา 20, 40, 60, 80 โน้ต: ตัวอย่างนี้ vectorized เร็วกว่า (`s * 2`) แต่เป็นจุดเริ่มต้นที่ดีเพื่อเข้าใจว่า apply ทำอะไรครับ
คราวนี้ผมใช้ฟังก์ชันที่ตั้งชื่อไว้แล้ว (named function) แทน lambda ครับ มีประโยชน์ตอน logic ซับซ้อนเกิน 1 บรรทัด เช่น จัดหมวดหมู่ราคา ผลลัพธ์เป็น Series ของ string 'ราคาถูก' / 'ราคากลาง' / 'ราคาแพง' แต่ละตัวตรงกับค่าตั้นต้น
นี่คือกรณีที่ผมใช้ apply บ่อยที่สุดครับ ตอนต้องคำนวณข้ามหลายคอลัมน์ในแถวเดียว ด้วย axis=1 แต่ละ row จะถูกส่งเข้า lambda เป็น Series และเรา access คอลัมน์ได้ด้วย row['ชื่อ'] ได้ราคาหลังหักส่วนลดออกมาเป็น Series ครับ
ตอน axis=0 (ค่า default) แต่ละ "คอลัมน์" จะถูกส่งเข้าฟังก์ชันเป็น Series ครับ ผมใช้หา range (ค่าสูงสุด – ต่ำสุด) ของแต่ละคอลัมน์คะแนน ได้ผลออกมาเป็น Series ที่ index คือชื่อคอลัมน์
ช้ากว่าเยอะมากครับ 😅 apply วน loop ใน Python ทีละแถว ถ้าข้อมูล 1 ล้านแถว vectorized operations เสร็จในหลัก milliseconds แต่ apply อาจใช้เวลาหลายวินาทีเลย ผมเลยใช้ apply เฉพาะตอนที่ logic ซับซ้อนจริงๆ เช่น ต้องเงื่อนไข if-else หลายชั้น หรือ call ฟังก์ชัน external ที่ไม่รับ array ครับ
apply ส่ง Series เข้าฟังก์ชัน (ทั้งแถวหรือทั้งคอลัมน์) ครับ ส่วน map ใน Series และ applymap (เปลี่ยนชื่อเป็น map ใน pandas 2.1+) ส่งค่าแต่ละ cell เข้าทีละค่าเลย ผมใช้ .map() ตอนอยากเปลี่ยนค่าแต่ละ cell อย่างเดียวโดยไม่ต้องเห็นแถวรอบข้าง และใช้ apply ตอนต้องคำนวณข้ามคอลัมน์ในแถวเดียวกันครับ
ได้เลยครับ ใช้ parameter args=(val1, val2) เพื่อส่ง positional args เพิ่ม หรือส่งเป็น **kwargs ก็ได้ เช่น df['price'].apply(add_tax, args=(0.07,)) ถ้าเขียนฟังก์ชัน add_tax(price, tax_rate) ไว้ครับ
ฟังก์ชันที่ผู้เขียนโยงไว้กับ pandas apply จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง
astype ใน pandas ผมใช้สำหรับแปลงประเภทข้อมูล (dtype) ของคอลัมน์หรือ DataFrame เช่น จาก object เป็น int หรือ float เป็น str ทำให้คำนวณได้ถูกต้องและประหยัด memory มากขึ้นครับ
pandas .dt accessor ผมใช้สำหรับดึงส่วนต่างๆ ของวันที่ออกจาก datetime Series เช่น ปี เดือน วัน ชื่อวัน หรือไตรมาส เหมือนกับที่ Excel มีฟังก์ชัน YEAR() MONTH() DAY() WEEKDAY() แต่ทำได้กับทั้งคอลัมน์พร้อมกันในคำสั่งเดียวเลยครับ
pandas .str accessor ทำให้ผมใช้ text functions อย่าง upper, replace, contains กับทุกแถวในคอลัมน์พร้อมกันบรรทัดเดียว เหมือนได้ UPPER/SUBSTITUTE/SEARCH ของ Excel แต่ไม่ต้องลากสูตรทีละเซลล์ครับ
pd.to_datetime() ใช้แปลงข้อมูลวันที่ที่อยู่ในรูป string หรือตัวเลขให้กลายเป็น datetime ที่ pandas จัดการได้ครับ พอแปลงแล้วก็เรียงลำดับ คำนวณระยะเวลา และดึงเดือน-ปี-วันออกมาได้ทันที
groupby ใน pandas ผมใช้สำหรับจัดกลุ่มข้อมูลใน DataFrame แล้วคำนวณค่าสรุปในแต่ละกลุ่ม เช่น หาผลรวม ค่าเฉลี่ย หรือค่าสถิติต่างๆ ตามหมวดหมู่ที่กำหนด ถ้าใครเคยใช้ PivotTable ใน Excel มาก่อน บอกเลยว่าตัวนี้คือเครื่องมือสายเดียวกันเลยครับ
ยังไม่มีบทความที่เกี่ยวข้องกับฟังก์ชันนี้
Comments
อีเมลของคุณจะไม่ถูกเผยแพร่