การประมาณค่าและการแทนค่าขั้นสูง
ใช้ interpolate() เพื่อเติมค่าตามเวลาอย่างราบรื่น และทำความเข้าใจว่าเมื่อใดควรใช้ค่าเฉลี่ยแทนค่ามัธยฐาน
การประมาณค่าและการแทนค่าขั้นสูง เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน
เมื่อการประมาณค่าแทรกดีกว่า fillna()
การเติมค่าไปข้างหน้าและย้อนกลับจะนำค่าที่ทราบล่าสุดหรือถัดไปมาใช้ โดยไม่พิจารณา แนวโน้มของข้อมูล การประมาณค่าแทรกจะประเมินค่าที่หายไปโดยสมมติว่าค่าระหว่างจุดที่ทราบมีการเปลี่ยนแปลงอย่างราบรื่น เช่น หากอุณหภูมิวันจันทร์อยู่ที่ 20°C และวันศุกร์อยู่ที่ 30°C การประมาณค่าแทรกจะประเมินว่าอุณหภูมิวันพุธอยู่ที่ 25°C วิธีนี้ให้ค่าที่แทนได้สมจริงกว่าสำหรับสัญญาณที่เปลี่ยนแปลงอย่างราบรื่น เช่น ข้อมูลจากเซนเซอร์ ราคา หรือจำนวนประชากร
import pandas as pd
import numpy as np
df = pd.DataFrame({
'day': [1, 2, 3, 4, 5],
'temp': [20.0, np.nan, np.nan, np.nan, 30.0]
})
# Linear interpolation fills gaps smoothly
df['temp_interp'] = df['temp'].interpolate(method='linear')
print(df)
# day temp temp_interp
# 0 1 20.0 20.0
# 1 2 NaN 22.5
# 2 3 NaN 25.0
# 3 4 NaN 27.5
# 4 5 30.0 30.0เมธอด interpolate()
Pandas รองรับ เมธอดหลายรูปแบบสำหรับ interpolate() รูปแบบที่ใช้บ่อยที่สุด ได้แก่ 'linear' (เว้นระยะเท่า ๆ กันระหว่างค่าที่ทราบ), 'time' (คำนึงถึงช่วงเวลาที่ห่างไม่เท่ากันเมื่อกำหนด DatetimeIndex), 'polynomial' (ปรับเส้นโค้งพหุนาม ซึ่งต้องระบุอาร์กิวเมนต์ order) และ 'spline' (พหุนามแบบเป็นช่วงที่มีความราบรื่น) แบบเชิงเส้นเป็นค่าเริ่มต้นที่ปลอดภัยที่สุด ส่วนเมธอดลำดับสูงอาจเกิดการปรับให้เข้ากับข้อมูลมากเกินไปในช่วงว่างขนาดเล็ก
import pandas as pd
import numpy as np
s = pd.Series([0, np.nan, np.nan, 8.0])
print('linear:', s.interpolate('linear').tolist())
# [0.0, 2.6666..., 5.3333..., 8.0]
print('polynomial(2):', s.interpolate('polynomial', order=2).tolist())
# [0.0, 2.222..., 5.111..., 8.0]การประมาณค่าแทรกแบบ time ด้วย DatetimeIndex
เมื่อ Series ของคุณมี DatetimeIndex ที่ช่วงเวลาห่างกันไม่เท่ากัน (เช่น มีเฉพาะวันทำงานและไม่มีวันหยุดสุดสัปดาห์) method='time' จะประมาณค่าแปรผันตามเวลาที่ผ่านไปจริง ไม่ใช่เพียงตามตำแหน่ง วิธีนี้แม่นยำกว่าการประมาณค่าแบบเชิงเส้น ซึ่งถือว่าแต่ละแถวมีระยะห่างเท่ากันโดยไม่สนใจช่องว่างตามปฏิทิน
import pandas as pd
import numpy as np
# Unequal gaps: Jan 1, Jan 3, Jan 10
idx = pd.to_datetime(['2024-01-01', '2024-01-03', '2024-01-10'])
s = pd.Series([100.0, np.nan, 170.0], index=idx)
# linear treats gaps as equal (position-based)
print(s.interpolate('linear').tolist()) # [100.0, 135.0, 170.0]
# time accounts for actual day count
# Jan 1 to Jan 3 = 2 days, Jan 1 to Jan 10 = 9 days
# fraction: 2/9 of the way from 100 to 170
print(s.interpolate('time').tolist()) # [100.0, 115.55..., 170.0]การจำกัดขอบเขตการประมาณค่าแทรก
เช่นเดียวกับ ffill() interpolate() รองรับพารามิเตอร์ limit เพื่อจำกัดจำนวนตำแหน่ง NaN ที่อยู่ติดกันและจะถูกเติม NaN ที่เกินขีดจำกัดจะยังคงเป็นค่าที่หายไป วิธีนี้ป้องกันไม่ให้การประมาณค่าทอดข้ามช่วงว่างที่ยาวมาก ซึ่งค่าจริงอาจเป็นอะไรก็ได้ โดยควรทำเครื่องหมายช่วงว่างยาวไว้เพื่อตรวจสอบด้วยตนเอง
import pandas as pd
import numpy as np
s = pd.Series([1.0, np.nan, np.nan, np.nan, np.nan, 10.0])
# Only fill the first 2 NaN positions
filled = s.interpolate('linear', limit=2)
print(filled.tolist())
# [1.0, 2.8, 4.6, NaN, NaN, 10.0]การเลือกใช้การแทนค่าด้วยค่าเฉลี่ยหรือค่ามัธยฐาน
การแทนค่าด้วยค่าเฉลี่ยและค่ามัธยฐานทำได้ง่าย แต่มีข้อแลกเปลี่ยนสำคัญ mean ไวต่อค่าผิดปกติ ค่าที่สูงมากเพียงไม่กี่ค่าจะดึงค่าเฉลี่ยให้สูงขึ้น ทำให้ไม่เหมาะสำหรับการเติมค่าในการแจกแจงที่เบ้ไปทางขวา เช่น รายได้หรือราคาบ้าน median ทนต่อค่าผิดปกติได้ดีกว่า และเป็นตัวเลือกที่เหมาะกว่าสำหรับคอลัมน์ที่มีการแจกแจงเบ้ ควรใช้ค่าเฉลี่ยเฉพาะเมื่อข้อมูลมีลักษณะสมมาตรโดยประมาณและไม่มีค่าผิดปกติที่รุนแรง
import pandas as pd
import numpy as np
# Skewed income data with an outlier
income = pd.Series([30000, 35000, 32000, 1_000_000, np.nan])
print('Mean: ', income.mean()) # ~274000 — pulled by outlier
print('Median:', income.median()) # ~33500 — robust choice
# Prefer median for skewed data
filled = income.fillna(income.median())
print(filled.tolist())
# [30000, 35000, 32000, 1000000, 33500.0]แนวคิดการแทนค่าด้วย KNN
การแทนค่าด้วยเพื่อนบ้านใกล้ที่สุด K (KNN) จะแทนค่าที่หายไปด้วยค่าเฉลี่ย (หรือค่าเฉลี่ยถ่วงน้ำหนัก) ของแถวที่มีความคล้ายกันมากที่สุดจำนวน k แถว โดยวัดจากระยะห่างของคุณลักษณะที่ไม่หายไป วิธีนี้เป็นกลยุทธ์หลายตัวแปร โดยใช้ข้อมูลจากคอลัมน์อื่นมาช่วยกำหนดค่าที่จะเติม จึงแม่นยำกว่าการแทนค่าด้วยค่าเฉลี่ยของคอลัมน์เดียวเมื่อคุณลักษณะมีความสัมพันธ์กัน
KNNImputer ของ Scikit-learn ทำงานร่วมกับอาร์เรย์ NumPy และ DataFrames ของ Pandas ได้โดยตรง
import pandas as pd
import numpy as np
from sklearn.impute import KNNImputer
df = pd.DataFrame({
'age': [25, 35, np.nan, 45],
'income': [50000, 70000, 60000, np.nan]
})
imputer = KNNImputer(n_neighbors=2)
df_imputed = pd.DataFrame(
imputer.fit_transform(df),
columns=df.columns
)
print(df_imputed.round(1))
# age income
# 0 25.0 50000.0
# 1 35.0 70000.0
# 2 30.0 60000.0 <- filled from neighbours
# 3 45.0 65000.0 <- filled from neighboursการแทนค่าหลายรูปแบบด้วย IterativeImputer
การแทนค่าหลายรูปแบบเป็นมาตรฐานสูงสุดสำหรับการจัดการข้อมูลที่หายไปในงานวิจัยทางสถิติ IterativeImputer ของ Scikit-learn ใช้แนวทาง MICE (Multiple Imputation by Chained Equations) โดยสร้างแบบจำลองให้แต่ละคอลัมน์ที่มีค่าหายไปเป็นฟังก์ชันของคอลัมน์อื่น ๆ แล้วทำการแทนค่าซ้ำจนกว่าค่าจะลู่เข้า วิธีนี้จับความสัมพันธ์ระหว่างคุณลักษณะได้ดีกว่ากลยุทธ์ที่พิจารณาทีละคอลัมน์
import pandas as pd
import numpy as np
from sklearn.experimental import enable_iterative_imputer # noqa
from sklearn.impute import IterativeImputer
df = pd.DataFrame({
'x1': [1, 2, np.nan, 4, 5],
'x2': [2, np.nan, 6, 8, 10],
'y': [3, 5, 7, np.nan, 11]
})
imp = IterativeImputer(max_iter=10, random_state=0)
df_filled = pd.DataFrame(imp.fit_transform(df), columns=df.columns)
print(df_filled.round(2))คอลัมน์ตัวบ่งชี้สำหรับข้อมูลที่หายไป
แทนที่จะปกปิดว่าค่าใดถูกแทนค่า แนวทางปฏิบัติที่ดีคือเพิ่ม คอลัมน์ตัวบ่งชี้แบบไบนารี เพื่อระบุว่าแถวใดมีค่าหายไปก่อนการแทนค่า วิธีนี้ทำให้แบบจำลองในขั้นถัดไปเรียนรู้จากรูปแบบการหายไปได้โดยตรง เพราะบางครั้งการที่ค่าหายไปก็ช่วยทำนายได้พอ ๆ กับตัวค่าดังกล่าวเอง
import pandas as pd
import numpy as np
df = pd.DataFrame({'salary': [50000, np.nan, 70000, np.nan, 90000]})
# Add indicator before filling
df['salary_was_missing'] = df['salary'].isna().astype(int)
# Then fill
df['salary'] = df['salary'].fillna(df['salary'].median())
print(df)
# salary salary_was_missing
# 0 50000.0 0
# 1 70000.0 1
# 2 70000.0 0
# 3 70000.0 1
# 4 90000.0 0การแทนค่าและการรั่วไหลของข้อมูล
กฎสำคัญในกระบวนการประมวลผลของการเรียนรู้ของเครื่องคือ ให้คำนวณสถิติสำหรับการแทนค่า (ค่าเฉลี่ย ค่ามัธยฐาน ฐานนิยม) จาก ชุดฝึกเท่านั้น แล้วใช้ค่าเดียวกันกับชุดทดสอบ การคำนวณสถิติจากชุดข้อมูลทั้งหมดก่อนแบ่งชุดจะทำให้เกิด การรั่วไหลของข้อมูล เพราะแบบจำลองจะเห็นข้อมูลทดสอบทางอ้อมระหว่างการฝึก ส่งผลให้ค่าประมาณประสิทธิภาพสูงเกินจริง ควรปรับตัวแทนค่าด้วยข้อมูลฝึกเสมอ แล้วแปลงทั้งข้อมูลฝึกและข้อมูลทดสอบ
import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
df = pd.DataFrame({'feature': [1, 2, np.nan, 4, np.nan, 6, 7, 8]})
train, test = train_test_split(df, test_size=0.25, random_state=0)
# Fit ONLY on training data
imp = SimpleImputer(strategy='mean')
train['feature'] = imp.fit_transform(train[['feature']])
# Transform test using training statistics
test['feature'] = imp.transform(test[['feature']])
print('Train mean used:', imp.statistics_[0])การเปรียบเทียบกลยุทธ์การแทนค่าด้วยภาพ
หลังใช้วิธีการแทนค่าหลายรูปแบบแล้ว ให้เปรียบเทียบผลกระทบด้วยการพล็อตการแจกแจงของคอลัมน์ดั้งเดิมและคอลัมน์ที่แทนค่าไว้เคียงข้างกัน การแทนค่าที่ดีควรรักษารูปร่างของการแจกแจงเดิม (ค่าเฉลี่ย ความแปรปรวน ความเบ้) ให้ใกล้เคียงที่สุด การแทนค่าด้วยค่าเฉลี่ยจะทำให้การแจกแจงแคบลง ส่วน KNN และ MICE มักรักษารูปร่างไว้ได้ดีกว่า
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
original = np.random.exponential(scale=5, size=200)
with_nan = original.copy()
with_nan[np.random.choice(200, 40, replace=False)] = np.nan
s = pd.Series(with_nan)
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
s.dropna().hist(ax=axes[0], bins=20, title='Original (no NaN)')
s.fillna(s.mean()).hist(ax=axes[1], bins=20, title='Mean-imputed')
plt.tight_layout()
plt.savefig('imputation_comparison.png')
print('Saved comparison chart')การเลือกกลยุทธ์การแทนค่าที่เหมาะสม
ไม่มีกลยุทธ์การแทนค่าใดดีที่สุดสำหรับทุกกรณี ตัวเลือกที่เหมาะสมขึ้นอยู่กับบริบท ใช้ mean/median สำหรับกรณีตัวแปรเดียวที่เรียบง่ายและมีค่าหายไปน้อย ใช้ ffill/bfill สำหรับอนุกรมเวลาที่มีแนวโน้มคงที่ ใช้ KNN หรือ IterativeImputer เมื่อคุณลักษณะมีความสัมพันธ์กันและต้องการใช้ประโยชน์จากความสัมพันธ์เหล่านั้น ใช้ ค่าคงที่ตามบริบทของงาน (เช่น 0 สำหรับไม่มีข้อมูล, -1 สำหรับไม่ทราบค่า) เมื่อค่าที่หายไปมีความหมายทางธุรกิจที่ชัดเจน ควรบันทึกเหตุผลของตัวเลือกไว้เสมอ
# Decision guide (no runnable code)
#
# Missing < 5% AND data is MCAR? -> Mean/median fill is fine
# Time series with stable trend? -> ffill() with limit
# Features are correlated? -> KNNImputer or IterativeImputer
# Categorical column? -> Mode fill or 'Unknown' sentinel
# Going into ML model? -> Add indicator column + fill
# Research / publication quality? -> Multiple imputation (MICE)
print('Strategy selected based on context')ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับการประมาณค่าแทรกและการแทนค่าขั้นสูง
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า interpolate() จะประเมินค่าที่หายไปโดยสมมติว่ามีแนวโน้มที่ราบรื่นระหว่างค่าที่ทราบ, method='time' รองรับช่วงว่างที่ไม่เท่ากันใน DatetimeIndex และกลยุทธ์ขั้นสูงอย่าง KNNImputer และ IterativeImputer จะใช้ข้อมูลจากคอลัมน์อื่นเพื่อช่วยกำหนดค่าที่เติม ควรเพิ่ม คอลัมน์ตัวบ่งชี้ ก่อนการแทนค่าเสมอ และคำนวณสถิติจากชุดฝึกเท่านั้นเพื่อป้องกันการรั่วไหลของข้อมูล บทถัดไป เราจะตรวจสอบและแปลงชนิดข้อมูลของคอลัมน์ใน DataFrame
เรียนรู้ Python ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การประมาณค่าและการแทนค่าขั้นสูง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การประมาณค่าและการแทนค่าขั้นสูง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การประมาณค่าและการแทนค่าขั้นสูง”
ใช้ interpolate() เพื่อเติมค่าตามเวลาอย่างราบรื่น และทำความเข้าใจว่าเมื่อใดควรใช้ค่าเฉลี่ยแทนค่ามัธยฐาน คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การประมาณค่าและการแทนค่าขั้นสูง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม
ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การตรวจหาค่าที่หายไป
- การลบค่าที่หายไป
- การเติมค่าที่หายไป
- การประมาณค่าและการแทนค่าขั้นสูง