apply() กับคอลัมน์และแถว
ใช้ DataFrame.apply() กับ axis=0 และ axis=1 เพื่อเรียกใช้ฟังก์ชันกำหนดเองกับแต่ละคอลัมน์หรือแต่ละแถว
apply() กับคอลัมน์และแถว เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน
เมื่อใดควรใช้ apply()
DataFrame.apply() เรียกใช้ฟังก์ชัน Python ที่กำหนดเองกับแต่ละคอลัมน์ (axis=0) หรือแต่ละแถว (axis=1) เครื่องมือนี้ควรใช้เป็นทางเลือกสุดท้าย เพราะช้ากว่าการดำเนินการแบบเวกเตอร์ในตัว แต่จำเป็นเมื่อไม่สามารถเขียนการคำนวณด้วยเลขคณิตของ NumPy การจัดทำดัชนีแบบบูลีน หรือฟังก์ชันรวมข้อมูลในตัวได้ ให้ใช้เมื่อจำเป็นต้องมีตรรกะเงื่อนไขที่ซับซ้อน การแยกวิเคราะห์สตริงแบบกำหนดเอง หรือการคำนวณหลายขั้นตอนที่ทำงานกับแถวหรือคอลัมน์ทีละรายการ
import pandas as pd
import numpy as np
df = pd.DataFrame({
'price': [10.5, 25.0, 8.3, 100.0],
'quantity': [3, 1, 5, 2],
'tax_rate': [0.05, 0.10, 0.05, 0.15]
})
print(df)apply() กับคอลัมน์ (axis=0)
เมื่อใช้ axis=0 (ค่าเริ่มต้น) apply() จะส่งแต่ละ คอลัมน์ เป็น Series ไปยังฟังก์ชัน ฟังก์ชันจะได้รับทีละคอลัมน์ และควรส่งคืนค่าสเกลาร์ (สำหรับการรวมข้อมูล) หรือ Series (สำหรับการแปลงข้อมูล) วิธีนี้เหมาะสำหรับใช้ขั้นตอนการปรับมาตรฐานหรือการทำความสะอาดแบบกำหนดเองกับคอลัมน์ตัวเลขทั้งหมดอย่างสม่ำเสมอภายในการเรียกครั้งเดียว
# Custom range normalisation (0 to 1) for each column
def min_max_scale(col):
return (col - col.min()) / (col.max() - col.min())
df_scaled = df[['price', 'quantity']].apply(min_max_scale, axis=0)
print(df_scaled)apply() กับแถว (axis=1)
เมื่อใช้ axis=1 apply() จะส่งแต่ละ แถว เป็น Series ไปยังฟังก์ชัน ดัชนีของแถวคือชื่อคอลัมน์ คุณจึงเข้าถึงค่าต่าง ๆ ตามชื่อได้ วิธีนี้เหมาะอย่างยิ่งสำหรับการคำนวณระดับแถวที่ขึ้นอยู่กับหลายคอลัมน์ เช่น การคำนวณรายได้รวมหลังหักภาษี โดยแต่ละแถวมีอัตราภาษีของตนเอง
def revenue_after_tax(row):
subtotal = row['price'] * row['quantity']
return subtotal * (1 + row['tax_rate'])
df['revenue_after_tax'] = df.apply(revenue_after_tax, axis=1)
print(df)การส่งคืนหลายค่าด้วย apply()
ฟังก์ชันที่ส่งให้ apply(axis=1) สามารถส่งคืน pd.Series ที่มีรายการระบุชื่อ ซึ่ง Pandas จะขยายเป็นคอลัมน์ใหม่หลายคอลัมน์ วิธีนี้สะอาดกว่าการเรียก apply() สองครั้งเพื่อสร้างสองคอลัมน์ใหม่ หรือฟังก์ชันอาจส่งคืน dict ซึ่ง Pandas จะขยายเป็นคอลัมน์เช่นกัน
def compute_totals(row):
subtotal = row['price'] * row['quantity']
tax = subtotal * row['tax_rate']
return pd.Series({'subtotal': subtotal, 'tax': tax, 'total': subtotal + tax})
result = df.apply(compute_totals, axis=1)
print(result)apply() สำหรับการรวมข้อมูลแบบกำหนดเองในคอลัมน์
ใช้ apply(func, axis=0) เพื่อคำนวณสถิติแบบกำหนดเองสำหรับแต่ละคอลัมน์และส่งคืน Series สรุป ตัวอย่างเช่น คำนวณสัมประสิทธิ์การแปรผัน (ส่วนเบี่ยงเบนมาตรฐานหารด้วยค่าเฉลี่ย) สำหรับคอลัมน์ตัวเลขทุกคอลัมน์ภายในการเรียกครั้งเดียว ผลลัพธ์คือ Series ที่มีชื่อคอลัมน์เป็นดัชนี เหมาะสำหรับการวินิจฉัยแต่ละคอลัมน์อย่างรวดเร็ว
def coeff_of_variation(col):
return col.std() / col.mean() if col.mean() != 0 else np.nan
cv = df[['price', 'quantity']].apply(coeff_of_variation, axis=0)
print('Coefficient of variation per column:')
print(cv)การเปรียบเทียบ apply() กับทางเลือกแบบเวกเตอร์
ก่อนใช้ apply() ให้ตรวจสอบเสมอว่ามีทางเลือกแบบเวกเตอร์หรือไม่ สำหรับการคำนวณรายได้หลังหักภาษี df['price'] * df['quantity'] * (1 + df['tax_rate']) ให้ผลเช่นเดียวกับเวอร์ชัน apply(axis=1) แต่ทำงานเร็วกว่า 10–100 เท่า เพราะใช้ลูประดับ C ของ NumPy ควรสงวน apply() ไว้สำหรับกรณีที่ตรรกะแบบเวกเตอร์จะซับซ้อนจนอ่านไม่รู้เรื่อง
import time
start = time.time()
df['vectorised'] = df['price'] * df['quantity'] * (1 + df['tax_rate'])
print('Vectorised:', time.time() - start, 's')
start = time.time()
df['apply_result'] = df.apply(revenue_after_tax, axis=1)
print('apply():', time.time() - start, 's')apply() กับ Lambda
สำหรับการแปลงข้อมูลสั้น ๆ ในบรรทัดเดียว ให้ส่ง lambda ไปยัง apply() โดยตรง แทนการกำหนดฟังก์ชันที่มีชื่อ Lambda กระชับและเหมาะกับการดำเนินการง่าย ๆ แต่ควรหลีกเลี่ยงเมื่อเป็นตรรกะซับซ้อน ซึ่งฟังก์ชันที่มีชื่อและมีคำอธิบายจะเข้าใจและทดสอบได้ง่ายกว่า ควรใช้ Lambda อย่างพอเหมาะ เพราะไม่สามารถทดสอบหน่วยหรือวิเคราะห์ประสิทธิภาพตามชื่อได้ง่าย
# Clip revenue between 0 and 200, then round to nearest 10
df['revenue_clean'] = df['revenue_after_tax'].apply(lambda x: round(min(max(x, 0), 200) / 10) * 10)
print(df[['revenue_after_tax', 'revenue_clean']])การส่งอาร์กิวเมนต์เพิ่มเติมไปยัง apply()
ส่งอาร์กิวเมนต์เพิ่มเติมไปยังฟังก์ชันโดยใช้ทูเพิล args หรืออาร์กิวเมนต์คีย์เวิร์ดใน apply(func, args=(val,), axis=1) วิธีนี้ช่วยหลีกเลี่ยงการใช้ตัวแปรส่วนกลางภายในฟังก์ชัน และทำให้ฟังก์ชันนำกลับมาใช้ใหม่กับค่าพารามิเตอร์ต่าง ๆ ได้ ใน Python 3.8 ขึ้นไป คุณยังสามารถใช้ functools.partial เพื่อสร้างฟังก์ชันเวอร์ชันที่กำหนดอาร์กิวเมนต์บางส่วนไว้แล้วได้
def discount_price(row, discount_pct, threshold):
if row['quantity'] >= threshold:
return row['price'] * (1 - discount_pct)
return row['price']
df['discounted_price'] = df.apply(
discount_price, axis=1,
args=(0.1, 3) # 10% discount for quantity >= 3
)
print(df[['price', 'quantity', 'discounted_price']])apply() สำหรับการแปลงชนิดข้อมูล
เมื่อคอลัมน์มีชนิดข้อมูลปะปนกัน เช่น มีทั้งจำนวนเต็ม จำนวนทศนิยม และสตริง astype() จะแสดงข้อผิดพลาด ให้ใช้ apply(pd.to_numeric, errors='coerce') เพื่อพยายามแปลงค่าทีละแถว และส่งคืน NaN สำหรับค่าที่แปลงไม่ได้ รูปแบบนี้ปลอดภัยสำหรับคอลัมน์ที่ควรเป็นตัวเลขแต่มีค่าที่ไม่ใช่ตัวเลขเป็นครั้งคราวจากข้อผิดพลาดในการป้อนข้อมูล
messy = pd.Series(['10', '20.5', 'N/A', '100', '--'])
clean = messy.apply(pd.to_numeric, errors='coerce')
print(clean)ประสิทธิภาพ: apply() เทียบกับ np.vectorize
เมื่อจำเป็นต้องใช้ฟังก์ชันที่ทำงานกับค่าสเกลาร์กับแต่ละสมาชิก np.vectorize(func)(array) มักเร็วกว่า Series.apply(func) เพราะ vectorize ของ NumPy เรียกใช้งานผ่าน C แทนที่จะมีต้นทุนการเรียกฟังก์ชันของ Python อย่างไรก็ตาม np.vectorize ยังช้ากว่าการกระจายการดำเนินการจริง จึงมีประโยชน์เฉพาะเมื่อไม่มีนิพจน์แบบกระจายที่สื่อถึงตรรกะนั้นได้
def classify_size(price):
if price < 15:
return 'small'
elif price < 50:
return 'medium'
return 'large'
# np.vectorize approach
classify_v = np.vectorize(classify_size)
df['size_class'] = classify_v(df['price'].values)
print(df[['price', 'size_class']])เมื่อ apply() เป็นตัวเลือกที่เหมาะสม
ควรใช้ apply เมื่อ: (1) ตรรกะต้องแยกแขนงโดยพิจารณาค่าจากหลายคอลัมน์พร้อมกัน (2) ฟังก์ชันเรียก API หรือฐานข้อมูลภายนอกต่อแถว ซึ่งหลีกเลี่ยงการทำงานตามลำดับไม่ได้ (3) ฟังก์ชันแยกวิเคราะห์สตริงซับซ้อน เช่น กลุ่มข้อมูล JSON ที่จัดเก็บในเซลล์ หรือ (4) ฟังก์ชันส่งคืนออบเจ็กต์ที่มีความยาวเปลี่ยนแปลงได้ เช่น รายการ ในกรณีอื่นทั้งหมด ควรเลือกการดำเนินการแบบเวกเตอร์เพื่อความเร็วและความอ่านง่าย
import json
# Parse a JSON metadata column row by row
df['metadata'] = ['{"color": "red"}', '{"color": "blue"}', '{}', '{"color": "green"}']
df['color'] = df['metadata'].apply(lambda s: json.loads(s).get('color', 'unknown'))
print(df[['metadata', 'color']])ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจแนวคิดการวิเคราะห์ข้อมูลจากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้เกี่ยวกับ การใช้ apply(axis=0) เพื่อคำนวณสถิติแบบกำหนดเองในระดับคอลัมน์ การใช้ apply(axis=1) เพื่อคำนวณในระดับแถวโดยใช้ข้อมูลจากหลายคอลัมน์ และ การพิจารณาว่าเมื่อใดควรเลือกใช้ทางเลือกแบบเวกเตอร์เพื่อประสิทธิภาพที่ดีกว่า ลำดับถัดไป เราจะสำรวจการใช้ apply() ร่วมกับ GroupBy เพื่อรวมข้อมูลในระดับกลุ่มที่ซับซ้อน
คำถามที่พบบ่อย
บทเรียน “apply() กับคอลัมน์และแถว” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “apply() กับคอลัมน์และแถว” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “apply() กับคอลัมน์และแถว”
ใช้ DataFrame.apply() กับ axis=0 และ axis=1 เพื่อเรียกใช้ฟังก์ชันกำหนดเองกับแต่ละคอลัมน์หรือแต่ละแถว คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “apply() กับคอลัมน์และแถว” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม
ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- apply() กับคอลัมน์และแถว
- apply() กับ GroupBy
- map() และ applymap() สำหรับการดำเนินการทีละองค์ประกอบ
- การต่อเมธอดด้วย pipe()