10 เทคนิคเร่งความเร็ว pandas DataFrame ที่คุณต้องรู้ (2026)

รวม 10 เทคนิคเร่งความเร็ว pandas DataFrame ตั้งแต่ vectorization, dtype optimization ไปจนถึง parallel processing พร้อมโค้ดตัวอย่างและ benchmark อัปเดตสำหรับ pandas 3.0 (2026)

ทำไม pandas ถึงช้า? เข้าใจปัญหาก่อนจะไปแก้

ถ้าคุณเคยทำงานกับ pandas DataFrame ขนาดใหญ่ คุณน่าจะเคยนั่งรอหน้าจอโดยไม่รู้ว่าโค้ดจะรันเสร็จเมื่อไหร่ — บางทีหลายนาที บางทีเป็นชั่วโมง ผมเองก็เคยเป็นแบบนั้น ตอนที่ต้องประมวลผลข้อมูลหลายล้านแถวแล้วนั่งรอจนกาแฟหมดแก้ว

สาเหตุหลักก็คือ pandas ทำงานบน CPU แกนเดียว (single core) เป็นค่าเริ่มต้น แถมยังต้องคอยตรวจสอบ data type, จัดการ index, และดักจับข้อผิดพลาดอยู่ตลอดเวลา สิ่งเหล่านี้มีประโยชน์ แต่มันก็ทำให้ช้าลงไม่น้อยเลย

ในบทความนี้ เราจะมาดู 10 เทคนิคที่พิสูจน์แล้วว่าช่วยเร่งความเร็ว pandas ได้ตั้งแต่ 10 เท่าจนถึง 300 เท่า พร้อมโค้ดตัวอย่างที่ก็อปไปใช้ได้เลย อัปเดตสำหรับ pandas 3.0 ที่เพิ่งออกมาเมื่อมกราคม 2026 ด้วยนะ

1. ใช้ Vectorized Operations แทน Loop — เร็วขึ้น 300 เท่า

นี่คือกฎทองของ pandas เลย: อย่าวนลูป (loop) ผ่านแถวของ DataFrame ถ้าเป็นไปได้ ให้ใช้ vectorized operations แทนเสมอ

Vectorized operations คือการดำเนินการที่ทำกับทั้งคอลัมน์หรือทั้ง Series พร้อมกันในครั้งเดียว ภายในใช้โค้ด C/C++ ของ NumPy ซึ่งเร็วกว่าการวนทีละแถวแบบไม่เห็นฝุ่นเลย

import pandas as pd
import numpy as np

# สร้าง DataFrame ขนาด 1 ล้านแถว
df = pd.DataFrame({
    "price": np.random.uniform(10, 1000, 1_000_000),
    "quantity": np.random.randint(1, 100, 1_000_000)
})

# ❌ วิธีช้า: ใช้ for loop
total_slow = []
for i in range(len(df)):
    total_slow.append(df["price"].iloc[i] * df["quantity"].iloc[i])
df["total_slow"] = total_slow

# ✅ วิธีเร็ว: Vectorized operation
df["total_fast"] = df["price"] * df["quantity"]

จาก benchmark ที่ทดสอบดู วิธี vectorized เร็วกว่า for loop ประมาณ 315 เท่า และเร็วกว่า .apply() ประมาณ 27 เท่า ตัวเลขพวกนี้ไม่ได้โม้นะ — ลองรันดูเองได้เลย

2. เลิกใช้ iterrows() ซะ — ใช้ itertuples() แทน

ถ้าจำเป็นต้องวนลูปจริงๆ (ซึ่งบางทีก็หลีกเลี่ยงไม่ได้) อย่าใช้ iterrows() เด็ดขาด เพราะมันสร้าง Series object ใหม่ทุกรอบของลูป overhead สูงมาก

# ❌ ช้ามาก: iterrows()
for index, row in df.iterrows():
    result = row["price"] * row["quantity"]

# ✅ เร็วกว่า 60 เท่า: itertuples()
for row in df.itertuples():
    result = row.price * row.quantity

itertuples() คืนค่าเป็น namedtuple ซึ่งเบากว่า Series มาก ทำให้เร็วกว่า iterrows() ประมาณ 60 เท่า

แต่จำไว้ว่า — มันก็ยังช้ากว่า vectorization อยู่ดีนะ ใช้เป็นทางเลือกสุดท้ายเท่านั้น

3. ใช้ .apply() อย่างชาญฉลาด

.apply() อยู่ตรงกลางระหว่าง loop กับ vectorization พูดตรงๆ ก็คือมันเร็วกว่า iterrows() ประมาณ 2 เท่า แต่ก็ช้ากว่า vectorization อยู่มาก เหมาะกับกรณีที่ลอจิกซับซ้อนเกินกว่าจะ vectorize ได้

# ใช้ .apply() สำหรับลอจิกที่ซับซ้อน
def calculate_discount(row):
    if row["quantity"] > 50:
        return row["price"] * 0.9
    elif row["quantity"] > 20:
        return row["price"] * 0.95
    return row["price"]

df["discounted_price"] = df.apply(calculate_discount, axis=1)

# ✅ ดีกว่า: ใช้ np.select() แทน
conditions = [
    df["quantity"] > 50,
    df["quantity"] > 20,
]
choices = [
    df["price"] * 0.9,
    df["price"] * 0.95,
]
df["discounted_price"] = np.select(conditions, choices, default=df["price"])

เคล็ดลับ: ทุกครั้งที่คุณเขียน .apply() ให้หยุดคิดก่อนสักวินาทีว่ามีวิธี vectorize ได้ไหม — ฟังก์ชันอย่าง np.where(), np.select(), .clip(), .str accessor มักทดแทน .apply() ได้ (และเร็วกว่าเยอะ)

4. เลือก Data Type ให้ถูก — ประหยัดแรมและเร็วขึ้น

อันนี้หลายคนมองข้ามแต่สำคัญมาก หนึ่งในวิธีง่ายที่สุดที่จะเร่ง pandas คือการใช้ data type ที่ถูกต้อง

ปัญหาคือคนส่วนใหญ่ปล่อยให้ pandas เลือก float64 หรือ object เป็นค่าเริ่มต้น ซึ่งกินหน่วยความจำเยอะโดยไม่จำเป็น

# ตรวจสอบการใช้หน่วยความจำ
print(df.memory_usage(deep=True))

# ✅ ลดขนาด numeric columns
df["quantity"] = df["quantity"].astype("int16")       # จาก int64
df["price"] = df["price"].astype("float32")           # จาก float64

# ✅ ใช้ category สำหรับคอลัมน์ที่มีค่าซ้ำ
df["status"] = df["status"].astype("category")

# ตรวจสอบอีกครั้ง — จะเห็นว่าลดลงอย่างมาก
print(df.memory_usage(deep=True))

การใช้ category dtype ไม่ได้แค่ลดหน่วยความจำเท่านั้นนะ แต่ยังทำให้ groupby() และ string operations เร็วขึ้นอย่างเห็นได้ชัดด้วย

อัปเดต pandas 3.0: String dtype ใหม่

ตั้งแต่ pandas 3.0 คอลัมน์ข้อความจะถูก infer เป็น str dtype โดยอัตโนมัติ แทนที่จะเป็น object แบบเดิม ซึ่ง str dtype ใหม่ใช้ PyArrow เป็น backend — ประหยัดหน่วยความจำกว่าเดิมเยอะ

import pandas as pd

# pandas 3.0 — string จะเป็น str dtype อัตโนมัติ
ser = pd.Series(["สวัสดี", "โลก", "Python"])
print(ser.dtype)  # str (ไม่ใช่ object อีกต่อไป)

5. Copy-on-Write ใน pandas 3.0 — ลดการคัดลอกข้อมูลที่ไม่จำเป็น

Copy-on-Write (CoW) เป็นฟีเจอร์ที่กลายเป็นค่าเริ่มต้นใน pandas 3.0 แล้ว หลักการง่ายๆ ก็คือ: เมื่อคุณ slice หรือ index DataFrame pandas จะใช้ view (ชี้ไปที่ข้อมูลเดิม) แทนการก๊อปปี้ข้อมูล และจะก๊อปปี้จริงเมื่อมีการแก้ไขเท่านั้น

# pandas 3.0 — Copy-on-Write เป็นค่าเริ่มต้น
df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})

# การ slice ไม่คัดลอกข้อมูล — ใช้ view แทน (เร็วมาก)
subset = df[["a"]]

# จะคัดลอกเฉพาะเมื่อแก้ไข subset
subset.iloc[0, 0] = 999  # ตรงนี้จึงจะคัดลอก

# df ยังคงไม่เปลี่ยนแปลง
print(df)
#    a  b
# 0  1  4
# 1  2  5
# 2  3  6

CoW ช่วยให้ไม่ต้องเรียก .copy() เองอีกต่อไป ลด memory footprint ได้เยอะ แถมยังป้องกันบั๊กจาก chained assignment ที่เคยทำให้หลายคนปวดหัวอีกด้วย

6. แปลงเป็น NumPy เมื่อต้องการความเร็วสูงสุด

ตรงๆ เลย — บางครั้งวิธีที่เร็วที่สุดก็คือออกจาก pandas ไปใช้ NumPy โดยตรง เพราะ NumPy ไม่มี overhead ของ index, data type checking, และ alignment ที่ pandas ต้องทำทุกครั้ง

# แปลง DataFrame columns เป็น NumPy arrays
prices = df["price"].to_numpy()
quantities = df["quantity"].to_numpy()

# คำนวณด้วย NumPy — เร็วกว่า pandas Series operations
totals = prices * quantities

# ใส่กลับเข้า DataFrame
df["total"] = totals

วิธีนี้เร็วกว่า pandas vectorization ประมาณ 2-10 เท่า เหมาะกับงานคำนวณหนักๆ ที่ไม่ต้องใช้ index alignment ข้อเสียก็คือเราจะเสีย convenience ของ pandas ไป (ไม่มี column name, ไม่มี NaN handling อัตโนมัติ) ก็ต้องแลกกันหน่อย

7. ใช้ eval() และ query() สำหรับนิพจน์ซับซ้อน

pd.eval() และ df.query() ใช้ engine ชื่อ numexpr ในการประเมินนิพจน์ มันหลีกเลี่ยงการสร้าง intermediate arrays ทำให้ประหยัดหน่วยความจำและเร็วขึ้น โดยเฉพาะกับ DataFrame ขนาดใหญ่

# ❌ วิธีปกติ — สร้าง intermediate arrays
df["profit"] = (df["price"] - df["cost"]) * df["quantity"] * (1 - df["tax_rate"])

# ✅ ใช้ eval() — ประหยัดหน่วยความจำ เร็วกว่าสำหรับ DataFrame ใหญ่
df.eval("profit = (price - cost) * quantity * (1 - tax_rate)", inplace=True)

# ✅ ใช้ query() สำหรับ filtering
expensive_items = df.query("price > 500 and quantity > 10")

# แทนที่จะเขียนแบบนี้:
expensive_items = df[(df["price"] > 500) & (df["quantity"] > 10)]

มีจุดที่ต้องระวังก็คือ eval() จะเห็นผลชัดเจนกับ DataFrame ที่มีมากกว่า 10,000 แถว ถ้าข้อมูลเล็กกว่านั้น วิธีปกติอาจจะเร็วกว่าซะด้วยซ้ำ

อัปเดต pandas 3.0: pd.col() syntax ใหม่

pandas 3.0 เพิ่ม pd.col() syntax ใหม่สำหรับการอ้างอิงคอลัมน์แบบ lazy expression ซึ่งอ่านง่ายกว่า lambda มาก:

# pandas 3.0 — ใช้ pd.col() แทน lambda
df.assign(profit=pd.col("price") * pd.col("quantity") - pd.col("cost"))

# เทียบกับวิธีเดิม:
df.assign(profit=lambda x: x["price"] * x["quantity"] - x["cost"])

8. อ่านข้อมูลเป็นชิ้นๆ (Chunked Reading) สำหรับไฟล์ใหญ่

เคยเจอไหม? โหลดไฟล์ CSV ขนาดหลาย GB แล้ว Python crash ไปดื้อๆ

ปัญหาคือ pd.read_csv() จะพยายามดึงข้อมูลทั้งหมดเข้า memory ในครั้งเดียว ถ้าไฟล์ใหญ่เกินไปก็จบ วิธีแก้คือใช้ chunksize เพื่ออ่านทีละส่วน

# ❌ โหลดทั้งไฟล์ — อาจ memory ล้น
df = pd.read_csv("large_dataset.csv")

# ✅ อ่านทีละ 100,000 แถว
chunks = pd.read_csv("large_dataset.csv", chunksize=100_000)

results = []
for chunk in chunks:
    # ประมวลผลแต่ละ chunk
    processed = chunk.groupby("category")["sales"].sum()
    results.append(processed)

# รวมผลลัพธ์
final_result = pd.concat(results).groupby(level=0).sum()

อีกเทคนิคที่ช่วยได้มากคือใช้ usecols โหลดเฉพาะคอลัมน์ที่ต้องการ และกำหนด dtype ตั้งแต่ตอนอ่านเลย:

# ✅ โหลดเฉพาะคอลัมน์ที่ต้องการ + กำหนด dtype
df = pd.read_csv(
    "large_dataset.csv",
    usecols=["date", "category", "sales", "quantity"],
    dtype={"category": "category", "quantity": "int32", "sales": "float32"},
    parse_dates=["date"]
)

9. ใช้ Parquet แทน CSV — เร็วกว่าและเล็กกว่า

ถ้าคุณยังเก็บข้อมูลเป็น CSV อยู่ ลองเปลี่ยนมาใช้ Parquet ดู

Parquet เป็น columnar format ที่ถูกบีบอัดแล้ว อ่านเร็วกว่า CSV หลายเท่า ใช้พื้นที่น้อยกว่า และที่สำคัญคือมันเก็บ data type ไว้ด้วย ไม่ต้องมานั่ง infer type ใหม่ทุกครั้งที่อ่าน

# บันทึกเป็น Parquet
df.to_parquet("data.parquet", engine="pyarrow")

# อ่าน Parquet — เร็วกว่า CSV หลายเท่า
df = pd.read_parquet("data.parquet")

# อ่านเฉพาะบางคอลัมน์ — columnar format ทำให้เร็วมาก
df = pd.read_parquet("data.parquet", columns=["date", "sales"])

ให้ภาพชัดขึ้น: ไฟล์ CSV ขนาด 1 GB เมื่อบันทึกเป็น Parquet จะเหลือประมาณ 100-300 MB และอ่านเร็วกว่า 5-10 เท่า พอเจอตัวเลขแบบนี้แล้วก็ไม่มีเหตุผลที่จะไม่ลองเปลี่ยน

อัปเดต pandas 3.0: Arrow PyCapsule Interface

pandas 3.0 เพิ่ม Arrow PyCapsule Interface สำหรับแลกเปลี่ยนข้อมูลแบบ zero-copy กับไลบรารีอื่น ลดการก๊อปปี้ข้อมูลระหว่าง library ได้อีก:

# แลกเปลี่ยนข้อมูลแบบ zero-copy กับไลบรารีที่รองรับ Arrow
df = pd.DataFrame.from_arrow(arrow_table)

10. ใช้ Parallel Processing เมื่อข้อมูลใหญ่มาก

เมื่อเทคนิคข้างต้นทั้งหมดยังไม่เพียงพอ ก็ถึงเวลาดึงอาวุธหนักออกมา — parallel processing

Modin — เปลี่ยนบรรทัดเดียว เร็วขึ้นหลายเท่า

# ติดตั้ง: pip install modin[ray]

# เปลี่ยนแค่บรรทัดเดียว:
import modin.pandas as pd  # แทน import pandas as pd

# โค้ดที่เหลือเหมือนเดิมทั้งหมด!
df = pd.read_csv("large_dataset.csv")
result = df.groupby("category")["sales"].mean()

Modin แบ่ง DataFrame ออกเป็นส่วนย่อยและกระจายไปยัง CPU ทุกแกน ทำให้เร็วขึ้นประมาณ 4 เท่า โดยไม่ต้องเปลี่ยนโค้ดอะไรเลย แค่เปลี่ยน import บรรทัดเดียว ง่ายมาก

swifter — เร่ง .apply() อัตโนมัติ

# ติดตั้ง: pip install swifter
import swifter

# เพิ่ม .swifter ก่อน .apply()
df["result"] = df["col"].swifter.apply(my_complex_function)

swifter จะตัดสินใจเองว่าจะ vectorize, ใช้ Dask parallel, หรือใช้ pandas apply ปกติ ขึ้นอยู่กับขนาดข้อมูลและชนิดของฟังก์ชัน ค่อนข้าง "set it and forget it" เลย

ตารางเปรียบเทียบประสิทธิภาพ

สรุปความเร็วเปรียบเทียบจากการทดสอบกับ DataFrame ขนาด 1 ล้านแถว เพื่อให้เห็นภาพรวมทั้งหมด:

วิธีความเร็วเทียบกับ for loopความยากในการใช้งาน
for loop1x (baseline)ง่าย
iterrows()~1.5xง่าย
itertuples()~60xง่าย
.apply()~9xปานกลาง
Vectorization (pandas)~100-315xปานกลาง
NumPy vectorization~200-500xปานกลาง
Cython/Numba~200-1000xยาก
Modin (parallel)~4x ของ pandasง่ายมาก

สรุป: ตัดสินใจยังไงดี?

เมื่อต้องประมวลผล pandas DataFrame ให้คิดตามลำดับนี้:

  1. ใช้ vectorized operations ได้ไหม? — ถ้าได้ ใช้เลย เร็วที่สุด ไม่ต้องคิดมาก
  2. ลอจิกซับซ้อนแต่เป็น element-wise? — ลอง np.where(), np.select(), หรือ .map()
  3. ต้อง custom function จริงๆ? — ใช้ .apply() หรือ swifter.apply()
  4. ข้อมูลใหญ่มากยังช้าอยู่? — ลอง Modin, Dask, หรือ Numba
  5. จำเป็นต้อง loop? — ใช้ itertuples() เท่านั้น อย่าไปแตะ iterrows()

สุดท้ายแล้ว อย่าลืมว่าการเร่งความเร็วที่ดีที่สุดคือการเลือก data type ให้ถูกตั้งแต่แรก และใช้ Parquet แทน CSV เทคนิคพื้นฐานพวกนี้ช่วยได้เยอะมากโดยไม่ต้องเปลี่ยนโค้ดอะไรมาก

คำถามที่พบบ่อย (FAQ)

ทำไม pandas ถึงช้ากว่า Excel ในบางกรณี?

คำถามนี้เจอบ่อยมาก คำตอบก็คือ Excel ใช้การประมวลผลแบบ lazy (คำนวณเมื่อเซลล์ถูกแสดงเท่านั้น) ในขณะที่ pandas คำนวณทุกอย่างทันทีในหน่วยความจำ แถม pandas ยังมี overhead จาก Python interpreter ด้วย แต่พอคุณใช้เทคนิค vectorization อย่างถูกต้องแล้ว pandas จะทิ้ง Excel ห่างมากสำหรับข้อมูลขนาดใหญ่

ควรใช้ pandas หรือ Polars ในปี 2026?

Polars เขียนด้วย Rust ซึ่งเร็วกว่า pandas ในหลายกรณีก็จริง แต่ pandas 3.0 ก็ปรับปรุงมาเยอะแล้วด้วย Copy-on-Write และ Arrow backend สำหรับคนที่เพิ่งเริ่มต้น ผมแนะนำให้เริ่มจาก pandas ก่อน เพราะชุมชนใหญ่กว่าและหาคำตอบได้ง่ายกว่า แล้วค่อยลอง Polars เมื่อต้องการบีบประสิทธิภาพสูงสุด

.apply() กับ .map() ต่างกันอย่างไร?

.apply() ทำงานกับทั้งแถวหรือทั้งคอลัมน์ (axis=0 หรือ axis=1) ส่วน .map() ทำงานกับ Series ทีละ element เท่านั้น ถ้าจะแปลงค่าแบบ element-wise ง่ายๆ .map() มักเร็วกว่า .apply() นิดหน่อย

Numba คืออะไร และควรใช้เมื่อไหร่?

Numba เป็น JIT (Just-In-Time) compiler ที่แปลง Python function เป็น machine code ผ่าน LLVM ใช้เมื่อมีฟังก์ชันที่ทำงานกับตัวเลขเยอะๆ และ vectorize ด้วย pandas/NumPy ไม่ได้ แค่เพิ่ม @numba.jit decorator ก่อนฟังก์ชัน ก็เร่งได้ถึง 200 เท่า

ใช้ GPU เร่งความเร็ว pandas ได้ไหม?

ได้เลย ลองใช้ cuDF จาก NVIDIA RAPIDS ซึ่งมี API คล้าย pandas แต่ทำงานบน GPU แค่แปลง DataFrame จาก pandas เป็น cuDF ก็เร่งได้หลายสิบเท่าสำหรับข้อมูลขนาดใหญ่ ข้อจำกัดก็คือต้องมี GPU ที่รองรับ CUDA นั่นแหละ

เกี่ยวกับผู้เขียน Editorial Team

Our team of expert writers and editors.