astype ใน pandas ผมใช้สำหรับแปลงประเภทข้อมูล (dtype) ของคอลัมน์หรือ DataFrame เช่น จาก object เป็น int หรือ float เป็น str ทำให้คำนวณได้ถูกต้องและประหยัด memory มากขึ้นครับ
df.astype(dtype, errors)
df.astype(dtype, errors)
Series
ถ้าเรียกบน Series (df['col'].astype(…)) จะได้ Series กลับมาครับ ถ้าเรียกบน DataFrame ทั้งตาราง (df.astype(…)) จะได้ DataFrame กลับมา — ใน verify นี้ใช้ Series-returning snippet
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| dtype | str | type | dict | Yes | dtype ที่อยากแปลงไป เช่น ‘int64’, float, str, ‘category’ หรือ dict {‘col1’: int, ‘col2’: float} สำหรับแปลงหลายคอลัมน์พร้อมกัน | |
| errors | str | Optional | 'raise' | ‘raise’ (default) จะ raise exception ถ้าแปลงไม่ได้ / ‘ignore’ จะคืนค่าเดิมถ้าแปลงไม่ได้โดยไม่ error |
df['age'].astype(int)df['age'].astype(int)
0 25
1 30
2 28
Name: age, dtype: int64
df['price'].astype(float)df['price'].astype(float)
0 100.0
1 250.0
2 399.0
Name: price, dtype: float64
df.astype({'age': int, 'score': float})df.astype({'age': int, 'score': float})
age score name
0 25 88.5 Alice
1 30 92.0 Bob
2 28 76.3 Carol
df['city'].astype('category')df['city'].astype('category')
0 Bangkok
1 Chiang Mai
2 Bangkok
3 Phuket
4 Bangkok
5 Chiang Mai
Name: city, dtype: category
Categories (3, str): ['Bangkok', 'Chiang Mai', 'Phuket']
ค่าเริ่มต้น errors=’raise’ จะ raise ValueError ทันทีครับ ถ้าอยากข้ามค่าที่แปลงไม่ได้แบบเงียบๆ ให้ใส่ errors=’ignore’ แต่ผมไม่ค่อยแนะนำ เพราะมันจะคืน Series เดิมโดยไม่แปลงเลย ทำให้งงว่าทำไม dtype ไม่เปลี่ยน ถ้าข้อมูลมีค่าสกปรก ผมชอบใช้ pd.to_numeric(col, errors=’coerce’) แล้วจัดการ NaN ที่ได้มามากกว่าครับ
ผลเหมือนกันในทางปฏิบัติครับ ทั้งคู่แปลงเป็น string หมด แต่เทคนิคแตกต่างกันนิดนึง — astype(str) ใช้ Python built-in str type ส่วน astype(‘str’) ใช้ pandas string alias ผมส่วนตัวชอบเขียน .astype(str) มากกว่า เพราะอ่านชัดกว่าว่าแปลงเป็น string ครับ
เพราะ pandas เก็บข้อมูลแบบ Lookup Table ครับ แทนที่จะเก็บ string ‘Bangkok’ ซ้ำ 10,000 ครั้ง มันเก็บแค่ครั้งเดียว แล้วใช้ตัวเลข integer เล็กๆ อ้างอิงแทนในทุกแถว ยิ่งคอลัมน์มีค่าซ้ำเยอะยิ่งประหยัดมาก ผมลองกับข้อมูล 500,000 แถวที่มีหมวดหมู่ 20 ค่า ลด memory ได้ประมาณ 5-8 เท่าเลยครับ
ปัญหาที่ผมเจอบ่อยมากตอนโหลดข้อมูลจาก CSV หรือ Excel คือคอลัมน์ตัวเลขดันเป็น object หรือ string ทำให้บวกลบไม่ได้ กราฟออกมาแปลกๆ หรือ groupby ให้ผลผิดพลาดครับ astype คือเครื่องมือที่แก้ปัญหานี้ได้ตรงๆ เลย — สั่งแปลง dtype ได้ทั้งทั้งคอลัมน์เดียว หลายคอลัมน์พร้อมกัน หรือทั้ง DataFrame
ที่เจ๋งคือ astype รับ dict เพื่อแปลงหลายคอลัมน์พร้อมกัน เช่น df.astype({‘age’: int, ‘score’: float}) ในบรรทัดเดียว ไม่ต้องวนเขียนทีละคอลัมน์ นอกจากนี้ยังแปลงเป็น ‘category’ ได้ ซึ่งช่วยประหยัด memory ได้มากในคอลัมน์ที่มีค่าซ้ำๆ เช่น จังหวัด แผนก หมวดหมู่สินค้า
ส่วนตัวผมแนะนำให้รัน df.dtypes ดูก่อนเสมอเลยครับ จะได้รู้ว่าคอลัมน์ไหนยังมี dtype ผิดอยู่ แล้วค่อยใช้ astype แก้ให้ถูกก่อนเริ่มวิเคราะห์จริงๆ 😎