Pandas & NumPy Academy · บทเรียน

การเติมค่าที่หายไป

แทนที่ NaN ด้วยค่าคงที่ ค่าเฉลี่ยของคอลัมน์ การเติมค่าจากด้านหน้า หรือการเติมค่าจากด้านหลัง โดยใช้ fillna() และพารามิเตอร์ method

บทเรียน 3 จาก 413 ขั้นตอน

การเติมค่าที่หายไป เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

บทนำสู่ fillna()

การแทนค่าที่หายไป หมายถึงการแทนค่าที่หายไปด้วยค่าทดแทนที่สมเหตุสมผล แทนที่จะลบแถวนั้น Pandas มี fillna() เป็นเครื่องมือหลักสำหรับงานนี้ โดยจะแทนที่ NaN ทุกค่าใน Series หรือ DataFrame ด้วยค่าที่คุณระบุ ต่างจากการลบ การแทนค่าที่หายไปจะรักษาทุกแถวไว้ ซึ่งสำคัญเป็นพิเศษเมื่อข้อมูลมีจำกัด หรือรูปแบบของข้อมูลที่หายไปมีความหมาย

รูปแบบที่ง่ายที่สุดคือการส่งค่าคงที่เข้าไป: df['col'].fillna(0)

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'product': ['A', 'B', 'C', 'D'],
    'price': [10.0, np.nan, 30.0, np.nan]
})

# Fill all NaN in 'price' with 0
filled = df['price'].fillna(0)
print(filled)
# 0    10.0
# 1     0.0
# 2    30.0
# 3     0.0

การเติมค่าด้วยค่าเฉลี่ยหรือค่ามัธยฐานของคอลัมน์

การเติมค่าด้วย mean ของคอลัมน์ (สำหรับการแจกแจงแบบสมมาตร) หรือ median (สำหรับการแจกแจงที่เบ้) เป็นหนึ่งในกลยุทธ์การแทนค่าที่ใช้กันมากที่สุด สถิติเหล่านี้สะท้อนแนวโน้มเข้าสู่ส่วนกลางของข้อมูล จึงช่วยลดการบิดเบือนการแจกแจงของคอลัมน์ได้ ควรคำนวณสถิติดังกล่าวจากชุดฝึกเสมอ เพื่อป้องกันการรั่วไหลของข้อมูล

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'salary': [50000, np.nan, 70000, 80000, np.nan, 60000]
})

mean_salary = df['salary'].mean()
median_salary = df['salary'].median()

df['salary_mean_filled'] = df['salary'].fillna(mean_salary)
df['salary_median_filled'] = df['salary'].fillna(median_salary)
print(df)
#     salary  salary_mean_filled  salary_median_filled
# 0  50000.0             50000.0               50000.0
# 1      NaN             65000.0               65000.0
# 2  70000.0             70000.0               70000.0

การเติมค่าข้อมูลเชิงหมวดหมู่ด้วยฐานนิยม

สำหรับ คอลัมน์เชิงหมวดหมู่ การเติมค่าด้วยค่าเฉลี่ยหรือค่ามัธยฐานไม่สมเหตุสมผล ควรใช้ mode ซึ่งก็คือค่าที่ปรากฏบ่อยที่สุดแทน Series.mode()[0] จะคืนค่าที่พบบ่อยที่สุด (ส่วน [0] รองรับกรณีที่มีหลายฐานนิยม)

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'status': ['active', 'inactive', None, 'active', None, 'active']
})

most_common = df['status'].mode()[0]
print('Mode:', most_common)  # active

df['status'] = df['status'].fillna(most_common)
print(df['status'].tolist())
# ['active', 'inactive', 'active', 'active', 'active', 'active']

การเติมค่าไปข้างหน้าด้วย ffill()

การเติมค่าไปข้างหน้า (หรือเรียกว่า last-observation-carried-forward, LOCF) จะส่งต่อค่าล่าสุดที่ใช้ได้ (ไม่ใช่ NaN) ไปข้างหน้าเพื่อเติมตำแหน่ง NaN ถัดไป วิธีนี้เหมาะอย่างยิ่งกับข้อมูล อนุกรมเวลา ที่ค่าการวัดยังคงเดิมจนกว่าจะมีการอัปเดต เช่น สถานะอุปกรณ์ ระดับราคา หรือค่าที่อ่านได้จากเซนเซอร์ซึ่งเปลี่ยนเฉพาะเมื่อเกิดเหตุการณ์บางอย่าง

import pandas as pd
import numpy as np

price = pd.Series(
    [100, np.nan, np.nan, 105, np.nan, 110],
    index=pd.date_range('2024-01', periods=6, freq='ME')
)

filled = price.ffill()
print(filled)
# 2024-01-31    100.0
# 2024-02-29    100.0
# 2024-03-31    100.0
# 2024-04-30    105.0
# 2024-05-31    105.0
# 2024-06-30    110.0

การเติมค่าย้อนกลับด้วย bfill()

การเติมค่าย้อนกลับ (next-observation-carried-backward, NOCB) จะส่งต่อค่าถัดไปที่ใช้ได้ย้อนกลับมาเติมตำแหน่ง NaN ก่อนหน้า วิธีนี้มีประโยชน์เมื่อคุณทราบว่าข้อมูลในอนาคตสามารถเติมค่าที่หายไปในอดีตได้ เช่น เมื่อได้รับข้อมูลสิ้นเดือนและต้องเติมค่าย้อนกลับให้กับวันต่าง ๆ ในเดือนนั้นก่อนที่จะได้รับรายงาน

import pandas as pd
import numpy as np

df = pd.DataFrame({'value': [np.nan, np.nan, 3, np.nan, 5]})

print(df['value'].bfill())
# 0    3.0
# 1    3.0
# 2    3.0
# 3    5.0
# 4    5.0
# dtype: float64

พารามิเตอร์ limit สำหรับการเติมค่าไปข้างหน้าและย้อนกลับ

ทั้ง ffill() และ bfill() รองรับพารามิเตอร์ limit ซึ่งใช้จำกัดจำนวนค่า NaN ที่อยู่ติดกันและจะถูกเติม วิธีนี้สำคัญเมื่อคุณต้องการส่งต่อค่าไปข้างหน้าเพียงช่วงว่างสั้น ๆ เท่านั้น ส่วนช่วงว่างยาวควรคงเป็น NaN เพื่อสื่อว่าข้อมูลหายไปจริง ไม่ใช่เพียงมาถึงล่าช้า

import pandas as pd
import numpy as np

s = pd.Series([1.0, np.nan, np.nan, np.nan, 5.0])

# Fill only the first NaN gap, leave the rest
print(s.ffill(limit=1))
# 0    1.0
# 1    1.0   <- filled
# 2    NaN   <- still NaN (limit reached)
# 3    NaN
# 4    5.0

การเติมค่าในแต่ละคอลัมน์ด้วยวิธีที่แตกต่างกัน

ใน DataFrame จริง คอลัมน์แต่ละคอลัมน์อาจต้องใช้กลยุทธ์การเติมค่าที่แตกต่างกัน ให้ส่ง พจนานุกรมเข้าไปใน fillna() โดยคีย์คือชื่อคอลัมน์และค่าคือค่าที่จะใช้เติม วิธีนี้ใช้การแทนค่าเฉพาะคอลัมน์ได้ภายในการเรียกครั้งเดียว ซึ่งเป็นระเบียบกว่าการเรียก fillna แยกหลายครั้งต่อเนื่องกัน

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'age': [25, np.nan, 30],
    'income': [50000, np.nan, 70000],
    'country': ['USA', np.nan, 'UK']
})

fill_values = {
    'age': df['age'].median(),
    'income': df['income'].mean(),
    'country': 'Unknown'
}

filled = df.fillna(fill_values)
print(filled)
#     age   income  country
# 0  25.0  50000.0      USA
# 1  27.5  60000.0  Unknown
# 2  30.0  70000.0       UK

การแทนค่าที่คำนึงถึงกลุ่ม

กลยุทธ์ที่ซับซ้อนขึ้นคือการเติมค่า NaN ด้วย ค่าเฉลี่ยหรือค่ามัธยฐานของกลุ่ม แทนค่าเฉลี่ยของคอลัมน์ทั้งหมด ตัวอย่างเช่น เติมเงินเดือนที่หายไปด้วยค่ามัธยฐานของเงินเดือนในหมวดหมู่งานนั้น วิธีนี้รักษาโครงสร้างของกลุ่มย่อยไว้ และให้ค่าที่แทนได้สมจริงกว่าการใช้สถิติรวมทั้งคอลัมน์

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'dept': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
    'salary': [90000, np.nan, 50000, np.nan, 110000]
})

# Fill salary NaN with the median salary for each department
df['salary'] = df.groupby('dept')['salary'].transform(
    lambda x: x.fillna(x.median())
)
print(df)
#    dept   salary
# 0   Eng  90000.0
# 1   Eng  100000.0   <- group median (90k+110k)/2
# 2    HR  50000.0
# 3    HR  50000.0
# 4   Eng  110000.0

การเติมค่าคงที่สำหรับระบุค่าพิเศษ

บางครั้งค่าที่เหมาะสมสำหรับการแทนค่าคือ ค่าพิเศษสำหรับระบุสถานะ ซึ่งสื่อว่า “ไม่ทราบค่า” แทนที่จะเป็นค่าการวัดจริง เช่น -1 สำหรับอายุที่ไม่ทราบค่า, 'N/A' สำหรับหมวดหมู่ที่ไม่ทราบค่า หรือ False สำหรับแฟล็กบูลีนที่ไม่ทราบค่า ค่าพิเศษเหล่านี้เหมาะสมเมื่อโค้ดส่วนถัดไปตรวจสอบค่าเหล่านี้โดยเฉพาะ และจัดการต่างจากข้อมูลจริง

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'referral_source': ['email', np.nan, 'ad'],
    'trial_days': [14, np.nan, 7]
})

df['referral_source'] = df['referral_source'].fillna('unknown')
df['trial_days'] = df['trial_days'].fillna(-1).astype(int)
print(df)
#    user_id referral_source  trial_days
# 0        1           email          14
# 1        2         unknown          -1
# 2        3              ad           7

การเรียก fillna() ต่อเนื่องในกระบวนการประมวลผล

เช่นเดียวกับเมธอดทั้งหมดของ Pandas fillna() จะคืนค่า DataFrame ใหม่ และนำไปใช้ต่อใน สายโซ่เมธอดได้อย่างราบรื่น การเรียก .fillna() หลัง .dropna() จะใช้กลยุทธ์สองขั้นตอน ได้แก่ ลบแถวที่ไม่มีคอลัมน์สำคัญ แล้วเติมค่า NaN ที่เหลือในคอลัมน์ทางเลือกด้วยค่าเริ่มต้นที่สมเหตุสมผล ทั้งหมดนี้อยู่ในกระบวนการประมวลผลเดียวที่อ่านเข้าใจง่าย

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'user_id': [1, None, 3, 4],
    'score': [88, 95, np.nan, 76],
    'label': ['A', 'B', None, 'D']
})

cleaned = (
    df
    .dropna(subset=['user_id'])
    .fillna({'score': df['score'].mean(), 'label': 'Unknown'})
)
print(cleaned)
#    user_id  score    label
# 0      1.0   88.0        A
# 2      3.0   86.3  Unknown
# 3      4.0   76.0        D

การตรวจสอบว่าไม่มี NaN เหลืออยู่

หลังการแทนค่า ควร ตรวจสอบ เสมอว่าไม่มีค่า NaN เหลืออยู่ในคอลัมน์ที่คุณจัดการ เรียกใช้ df.isna().sum() หรือยืนยันว่าจำนวนค่าเป็นศูนย์ หากจำนวนที่ไม่ใช่ศูนย์เกิดขึ้นโดยไม่คาดคิด แสดงว่า fillna ของคุณอาจตกหล่นบางกรณี เช่น คอลัมน์มีชนิดข้อมูลที่ทำให้เติมค่าไม่ได้ หรือคุณลืมใส่คอลัมน์หนึ่งไว้ในพจนานุกรม

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [1.0, np.nan, 3.0], 'b': [np.nan, 2.0, 3.0]})
filled = df.fillna(0)

# Verify
assert filled.isna().sum().sum() == 0, 'Some NaN remain!'
print('All NaN filled successfully')
print(filled.isna().sum())
# a    0
# b    0
# dtype: int64

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับการเติมค่าที่หายไปใน Pandas

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า fillna(scalar) จะแทนที่ NaN ทั้งหมดด้วยค่าคงที่, fillna(mean/median) จะแทนค่าด้วยสถิติของคอลัมน์ และ ffill()/bfill() จะส่งต่อค่าที่อยู่ติดกันสำหรับข้อมูลอนุกรมเวลา ส่ง พจนานุกรมให้ fillna() เพื่อใช้กลยุทธ์เฉพาะคอลัมน์ และใช้ groupby().transform() สำหรับการแทนค่าที่คำนึงถึงกลุ่ม บทถัดไป เราจะพูดถึงการประมาณค่าแทรกและเวลาที่ควรเลือกใช้เทคนิคการแทนค่าขั้นสูง

เริ่มต้นได้ฟรี

เรียนรู้ Python ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
30
บทเรียน
120

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

บทเรียน “การเติมค่าที่หายไป” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การเติมค่าที่หายไป” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การเติมค่าที่หายไป”

แทนที่ NaN ด้วยค่าคงที่ ค่าเฉลี่ยของคอลัมน์ การเติมค่าจากด้านหน้า หรือการเติมค่าจากด้านหลัง โดยใช้ fillna() และพารามิเตอร์ method คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การเติมค่าที่หายไป” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม

ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การตรวจหาค่าที่หายไป
  2. การลบค่าที่หายไป
  3. การเติมค่าที่หายไป
  4. การประมาณค่าและการแทนค่าขั้นสูง
← กลับไปที่ Pandas & NumPy Academy