ข้ามไปยังเนื้อหาหลัก

การเปลี่ยนชื่อคอลัมน์ใน Pandas: คู่มือฉบับสมบูรณ์พร้อมตัวอย่าง

เรียนรู้การเปลี่ยนชื่อคอลัมน์ใน pandas ด้วย .rename(), df.columns และ .set_axis() พร้อมฟังก์ชัน Python สำหรับ snake_case และวิธีแก้ KeyError และ ValueError.
อัปเดตแล้ว 17 ส.ค. 2569  · 13 นาที อ่าน

สำรวจด้วย AI

ChatGPTClaudePerplexity

ดึงไฟล์ CSV ใหม่จากฐานข้อมูลของบริษัท รัน df.head() แล้วเจอ CUST_ID_NBR, txn_amt_usd_2, Unnamed: 7 หรือคอลัมน์ชื่อ Customer Name (Full) ที่มีช่องว่างท้ายชื่อซึ่งจะไม่ทันสังเกตจนกว่า KeyError จะพังงานตอนบ่ายให้หมด ชื่อคอลัมน์ที่รกๆ เป็นความฝืดเล็กๆ ของงานข้อมูลจริง และขั้นตอนเปลี่ยนชื่อคอลัมน์ใน pandas มักเป็นอย่างแรกที่ทำก่อนเริ่มวิเคราะห์จริงจัง

ในบทช่วยสอนการเปลี่ยนชื่อคอลัมน์ใน pandas นี้ จะได้เรียนรู้:

  • การเปลี่ยนชื่อคอลัมน์หนึ่งหรือหลายคอลัมน์ด้วย .rename()

  • การแทนที่ชื่อคอลัมน์ทั้งหมดพร้อมกันด้วย df.columns หรือ .set_axis()

  • การใช้ฟังก์ชันเพื่อแปลงชื่อแบบคราวละมากๆ

  • การทำความสะอาดชื่อที่ยุ่งเหยิงด้วยตัวเข้าถึง .str

  • การเปลี่ยนชื่อคอลัมน์ตอนโหลดข้อมูลใน pd.read_csv()

  • การทำงานแบบเดียวกันใน Polars

  • การหลีกเลี่ยง KeyError และ ValueError: Length mismatch

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

ควรเลือกวิธีเปลี่ยนชื่อใน Pandas แบบไหน?

เลือกวิธีที่ตรงกับขอบเขตงาน: เปลี่ยนชื่อแบบเจาะจง แทนที่ทั้งหมด หรือใช้กฎกับทุกชื่อ

เป้าหมาย

วิธี

เหมาะเมื่อ

เปลี่ยนชื่อคอลัมน์หนึ่งหรือไม่กี่คอลัมน์ที่ระบุ

df.rename(columns={"old": "new"})

คอลัมน์อื่นไม่ถูกแตะต้อง; ปลอดภัยในเมธอดเชน

แทนที่ชื่อคอลัมน์ทุกคอลัมน์

df.columns = [...] หรือ df.set_axis([...], axis=1)

เร็วกว่าแมประบุทีละชื่อ; ใช้ .set_axis() เมื่อต้องเชน

เปลี่ยนชื่อด้วยกฎ (ตัวพิมพ์เล็ก, snake_case, ตัดช่องว่าง)

df.rename(columns=func) หรือ df.columns.str....

ระบุกฎครั้งเดียวแทนการไล่ชื่อทุกคอลัมน์

เปลี่ยนชื่อขณะโหลดข้อมูล

pd.read_csv(..., header=0, names=[...])

ควบคุมสคีมาเองและไม่ต้องการขั้นตอนแยกต่างหาก

ทำอย่างใดอย่างหนึ่งข้างต้นใน Polars

df.rename({"old": "new"}), .alias() ใน select

ไม่เปลี่ยนค่าเดิมและเน้นเชน จึงไม่มี inplace

จะเปลี่ยนชื่อคอลัมน์ด้วย .rename() อย่างไร?

เมธอด .rename() คือวิธีที่ยืดหยุ่นที่สุดในการเปลี่ยนชื่อคอลัมน์ของ pandas DataFrame และมักเป็นตัวเลือกแรกที่หยิบมาใช้ 

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

แพตเทิร์นของดิกชันนารีมีหน้าตาแบบนี้:

sales_data.rename(columns={"old_name": "new_name"})

หากเพิ่งเริ่มใช้ดิกชันนารี แนะนำให้ทบทวนบทช่วยสอน เมธอดของดิกชันนารีใน Python ก่อน

หมายเหตุเกี่ยวกับพารามิเตอร์ copy เดิม

ขอกล่าวถึงเรื่องหนึ่งก่อนยกตัวอย่าง Pandas 3.0 เลิกใช้พารามิเตอร์ copy และทำให้ Copy-on-Write เป็นพฤติกรรมเริ่มต้น ในทางปฏิบัติ หมายความว่าไม่ต้องกังวลอีกต่อไปว่า .rename() จะสร้างสำเนาข้อมูลที่เปลืองทรัพยากรหรือไม่ Pandas จะจัดการแบบขี้เกียจอยู่เบื้องหลัง พารามิเตอร์หลักที่ยังควรคิดคือ inplace ซึ่งจะกล่าวถึงในหัวข้อย่อยที่สาม

เปลี่ยนชื่อคอลัมน์เดี่ยว

นึกภาพว่าพึ่งโหลดระเบียนลูกค้าที่ส่งออกจาก CRM เก่า ชื่อคอลัมน์ถูกย่อแบบที่ผู้สร้างฐานข้อมูลในปี 2008 เข้าใจ แต่คุณไม่เข้าใจ นี่คือการเปลี่ยนชื่อที่ง่ายที่สุดใน pandas: ชื่อเก่าหนึ่ง ชื่อใหม่หนึ่ง ในดิกชันนารี:

import pandas as pd

customers = pd.DataFrame({
    "cust_id_nbr": [4521, 4522, 4523, 4524],
    "first_nm": ["Abe", "Rick", "Pat", "Kim"],
    "signup_dt": ["2008-03-12", "2008-03-15", "2008-03-18", "2008-03-21"]
})

print(customers)

Python DataFrame

จากนั้น เปลี่ยนชื่อ cust_id_nbr ให้เข้าใจง่ายขึ้น:

customers_renamed = customers.rename(columns={"cust_id_nbr": "customer_id"})
print(customers_renamed)

Python DataFrame

DataFrame ต้นฉบับ customers ไม่ถูกเปลี่ยน .rename() คืนค่า DataFrame ใหม่ซึ่งเราเก็บไว้ใน customers_renamed สองคอลัมน์ที่ไม่ได้ระบุ (first_nm, signup_dt) มากับมันโดยไม่เปลี่ยน

เปลี่ยนชื่อหลายคอลัมน์

ดิกชันนารีขยายได้ตามธรรมชาติ เพื่อจัดการงานเปลี่ยนชื่อหลายคอลัมน์ใน pandas ก็แค่เพิ่มคู่คีย์-ค่าเข้าไปในแมปปิง:

customers_clean = customers.rename(columns={
    "cust_id_nbr": "customer_id",
    "first_nm": "first_name",
    "signup_dt": "signup_date"
})

print(customers_clean)

Python DataFrame

ยังมีไวยากรณ์ทางเลือกที่ใช้พารามิเตอร์ mapper และ axis แทนคีย์เวิร์ด columns:

customers.rename(mapper={"cust_id_nbr": "customer_id"}, axis=1)

axis=1 บอก pandas ว่ากำลังเล็งไปที่คอลัมน์ (ต่างจาก axis=0 สำหรับป้ายกำกับแถว) ทั้งสองรูปแบบให้ผลลัพธ์เท่ากัน โค้ดที่พบในงานจริงส่วนใหญ่ใช้ columns={...} เพราะอ่านเข้าใจง่ายกว่า เราจะยึดรูปแบบนี้ตลอดบทช่วยสอน

รายละเอียดที่มีประโยชน์คือ ถ้าส่งคีย์ที่ไม่ตรงกับคอลัมน์ใดๆ อยู่แล้ว .rename() จะมองข้ามอย่างเงียบๆ ตามค่าเริ่มต้น สะดวกเมื่อเขียนฟังก์ชันนำกลับใช้ที่อาจเจอ DataFrame สคีมาแตกต่างเล็กน้อย แต่ก็อาจซ่อนตัวสะกดผิดได้ หากต้องการให้ pandas แจ้งข้อผิดพลาดเมื่อเจอชื่อคอลัมน์ที่ไม่รู้จัก ให้ส่ง errors='raise'

ใช้ inplace เทียบกับคืนค่า DataFrame ใหม่

โดยค่าเริ่มต้น .rename() จะคืนค่า DataFrame ใหม่และไม่แตะต้นฉบับ หากต้องการให้แก้ไข DataFrame ที่มีอยู่โดยตรง ให้ส่ง inplace=True:

# คืนค่า DataFrame ใหม่ (ค่าเริ่มต้น)
customers_v2 = customers.rename(columns={"first_nm": "first_name"})

# แก้ไข customers โดยตรง และคืนค่า None
customers.rename(columns={"first_nm": "first_name"}, inplace=True)

print(customers)

Python DataFrame

ควรใช้แบบไหน? ส่วนใหญ่แล้วการคืนค่า DataFrame ใหม่เป็นทางเลือกที่ดีกว่า ดีต่อการดีบัก เพราะยังมี DataFrame ต้นฉบับให้ตรวจเมื่อมีปัญหา และหลีกเลี่ยงปัญหา aliasing ที่ทำให้เกิด SettingWithCopyWarning ในโค้ดเก่า

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

จุดที่ inplace=True ยังรู้สึกเป็นธรรมชาติคือสคริปต์สำรวจสั้นๆ ที่ทำความสะอาด DataFrame เดียวทีละขั้นและไม่สนใจการเชน สำหรับโค้ดโปรดักชันหรือสิ่งที่จะกลับมาแก้ในภายหลัง ให้ใช้ค่าเริ่มต้นจะดีกว่า

จะเปลี่ยนชื่อคอลัมน์ทั้งหมดพร้อมกันใน Pandas ได้อย่างไร?

บางครั้งไม่ได้อยากแมปชื่อเก่าเป็นชื่อใหม่ แต่อยากแทนที่ชื่อคอลัมน์ทั้งหมดทันที เรื่องนี้เกิดขึ้นบ่อยกว่าที่คิด เช่น CSV ที่ไม่มีเฮดเดอร์ซึ่ง pandas ตั้งชื่อคอลัมน์เป็น 0, 1, 2 ชุดข้อมูลที่แถวเฮดเดอร์เป็นคนละภาษา หรือเอ็กซ์พอร์ตจากระบบที่สร้างชื่ออย่าง Field1, Field2, Field3

มีสองวิธีที่พบบ่อย ทำได้โดยกำหนดค่าให้ df.columns โดยตรง หรือใช้ .set_axis() ให้ผลลัพธ์เหมือนกัน แต่แลกกันระหว่างความสั้นกระชับกับความสามารถในการเชน

กำหนดลิสต์ให้ df.columns

วิธีตรงที่สุดคือกำหนดลิสต์ใหม่ให้แอตทริบิวต์ columns พิจารณา DataFrame นี้ที่สร้างจากลิสต์ของลิสต์ซึ่งไม่มีข้อมูลเฮดเดอร์ คล้ายกับตอนอ่าน CSV ที่ไม่มีเฮดเดอร์ Pandas จะตั้งชื่อคอลัมน์เป็นตัวเลข:

import pandas as pd

sensor_readings = pd.DataFrame([
    [1.2, 22.5, 1013],
    [1.5, 22.7, 1012],
    [1.3, 22.6, 1013]
])

print(sensor_readings)

Python DataFrame

ชื่อคอลัมน์ 0, 1, และ 2 ใช้ทำวิเคราะห์ไม่ได้ แทนที่ด้วยการกำหนดลิสต์ชื่อใหม่ให้แอตทริบิวต์ columns:

sensor_readings.columns = ["wind_speed", "temperature_c", "pressure_hpa"]
print(sensor_readings)

Python DataFrame

มีสองอย่างที่ควรรู้เกี่ยวกับวิธีนี้ 

  1. ความยาวของลิสต์ต้องตรงกันพอดี ส่งชื่อสามชื่อให้ DataFrame ที่มีสี่คอลัมน์แล้ว pandas จะแจ้ง ValueError: Length mismatch (จะกล่าวถึงข้อผิดพลาดนี้ในภายหลัง) 

  2. มันแก้ไข DataFrame แบบ inplace ที่นี่ไม่มีพารามิเตอร์ inplace เพราะการกำหนดค่านี่แหละคือการแก้ไข หากอยากได้สำเนาใหม่ ใช้ .copy() ก่อนหรือใช้ .set_axis() ด้านล่าง

ใช้ .set_axis() เพื่อเชนเมธอด

เมธอด .set_axis() ทำสิ่งเดียวกัน แต่คืนค่า DataFrame ใหม่เพื่อให้เชนกับการดำเนินการอื่นได้ ลองดู DataFrame ที่ไม่มีเฮดเดอร์ที่คล้ายกัน แต่คราวนี้มีข้อมูลรกๆ เช่น ตำแหน่งทศนิยมเกินและค่าที่หายไป:

raw_sensor = pd.DataFrame([
    [1.234, 22.567, 1013],
    [1.512, 22.789, 1012],
    [None,  22.601, 1013],
    [1.345, 22.612, 1013]
])

sensor_clean = (
    raw_sensor
    .set_axis(["wind_speed_mps", "temp_celsius", "pressure_hpa"], axis=1)
    .round(1)
    .dropna()
)

print(sensor_clean)

Python DataFrame

อาร์กิวเมนต์ axis=1 บอก pandas ว่ากำลังตั้งชื่อคอลัมน์ (ใช้ axis=0 เมื่อต้องตั้งดัชนีแถว) และเพราะ .set_axis() คืนค่า DataFrame ใหม่ มันจึงเข้ากับไปป์ไลน์การแปลงที่เชนกันในงาน ETL หรือการวิเคราะห์จริงได้อย่างเป็นธรรมชาติ นี่คือเหตุผลหลักที่ควรเลือกใช้เหนือการกำหนดค่าตรงๆ ในโค้ดโปรดักชัน

จะเปลี่ยนชื่อคอลัมน์ด้วยฟังก์ชันใน Pandas ได้อย่างไร?

แทนที่จะระบุชื่อเก่ากับชื่อใหม่ทีละรายการ สามารถส่งฟังก์ชันให้ .rename() แล้ว pandas จะนำไปใช้กับทุกชื่อคอลัมน์ เหมาะเมื่อมี “กฎ” มากกว่า “รายการชื่อ” เช่น “ทำให้ทั้งหมดเป็นตัวพิมพ์เล็ก” หรือ “แทนที่ช่องว่างทั้งหมดด้วยขีดล่าง”

ใช้ฟังก์ชันสตริงที่มีมาให้

กรณีง่ายที่สุดคือมาตรฐานตัวพิมพ์ ส่ง str.lower, str.upper หรือ str.title ตรงๆ ให้กับอาร์กิวเมนต์ columns:

import pandas as pd

orders = pd.DataFrame({
    "Order ID": [1001, 1002, 1003],
    "Customer Name": ["Abe", "Rick", "Pat"],
    "Total Amount": [49.99, 120.00, 75.50]
})

orders_lower = orders.rename(columns=str.lower)
print(orders_lower.columns.tolist())

Python column list

สังเกตว่าเราส่ง “ตัวฟังก์ชัน” (str.lower) ไม่ใช่เรียกมัน (str.lower()) Pandas จะประยุกต์กับแต่ละชื่อคอลัมน์ทีละชื่อ ทางลัดนี้สะอาดสำหรับมาตรฐานตัวพิมพ์ แต่ยังไม่จัดการช่องว่างหรืออักขระพิเศษ สำหรับกรณีนั้นควรใช้แลมบ์ดาหรือฟังก์ชันกำหนดเอง

ใช้ lambda และฟังก์ชันกำหนดเอง

สำหรับสิ่งที่เกินกว่าการเปลี่ยนตัวพิมพ์ แลมบ์ดาให้วิธีเขียนทรานส์ฟอร์เมชันแบบอินไลน์อย่างรวดเร็ว หากยังไม่คุ้นกับแลมบ์ดา คู่มือผู้เริ่มต้นเรื่องฟังก์ชัน lambda ใน Python เป็นจุดเริ่มต้นที่ดี

แพตเทิร์นที่พบบ่อยคือทำเป็นตัวพิมพ์เล็กและแทนที่ช่องว่างด้วยขีดล่างในขั้นตอนเดียว ใช้ตัวอย่างเดิม:

orders_snake = orders.rename(columns=lambda col: col.lower().replace(" ", "_"))
print(orders_snake.columns.tolist())

Python column list

เมื่อโลจิกซับซ้อนขึ้น ให้ยกออกไปเป็นฟังก์ชันที่มีชื่อ ลองดูตัวช่วยนี้ที่แปลงชื่อคอลัมน์แบบ camelCase หรือ PascalCase เป็น snake_case:

import re

def to_snake_case(name: str) -> str:
    """Convert camelCase or PascalCase to snake_case."""
    s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name)
    s2 = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1)
    return s2.lower()

api_response = pd.DataFrame({
    "userId": [1, 2, 3],
    "firstName": ["Abe", "Rick", "Pat"],
    "accountCreatedAt": ["2024-01-01", "2024-01-02", "2024-01-03"]
})

api_clean = api_response.rename(columns=to_snake_case)
print(api_clean.columns.tolist())

Python column list

ฟังก์ชันที่มีชื่อแบบนี้ทดสอบง่าย นำกลับใช้ข้ามโน้ตบุ๊กได้ และจัดทำเอกสารได้ดีกว่าบรรทัดเดียวที่ซับซ้อน ใช้แลมบ์ดาเมื่อโลจิกพอดีบรรทัดเดียว และใช้ฟังก์ชันกำหนดเองเมื่อไม่พอ

จะทำความสะอาดชื่อคอลัมน์ที่ยุ่งเหยิงแบบคราวละมากๆ ใน Pandas ได้อย่างไร?

เมื่อข้อมูลมาจากสเปรดชีต API ของบุคคลที่สาม หรือ CSV ที่แก้เอง ชื่อคอลัมน์มักมีปัญหาที่ .rename() เพียงอย่างเดียวจัดการอย่างสวยงามไม่ได้ ปัญหาเช่น:

  • ช่องว่างท้ายชื่อ
  • ตัวพิมพ์คละกัน
  • วงเล็บ
  • เครื่องหมายขีดกลาง
  • อักขระพิเศษ
  • อักขระยูนิโค้ดที่มองไม่เห็น

สำหรับสถานการณ์เหล่านี้ วิธีที่สะอาดที่สุดคือทำงานกับ df.columns โดยตรงด้วยตัวเข้าถึง .str ซึ่งเปิดใช้เมธอดสตริงแบบเวกเตอร์ (รวมทั้งเรกซ์) กับชื่อคอลัมน์ทั้งหมดพร้อมกัน นี่คือรากฐานของ การทำความสะอาดข้อมูลใน Python ที่ดี การทำความสะอาดชื่อคอลัมน์ทำให้ทุกขั้นตอนถัดไป (กรอง ผสาน พล็อต) ลดข้อผิดพลาด

ลบช่องว่างและอักขระพิเศษ

พิจารณา DataFrame นี้ที่มีชื่อแบบที่ได้จากการส่งออก Excel ที่ผ่านมือหลายคน:

import pandas as pd

raw_export = pd.DataFrame({
    "  Order ID ": [1001, 1002, 1003],
    "Customer Name (Full)": ["Abe", "Rick", "Pat"],
    "Total Amount ($)": [49.99, 120.00, 75.50],
    "Order-Date": ["2024-03-12", "2024-03-15", "2024-03-18"]
})

print(raw_export.columns.tolist())

Python column list

ช่องว่างหัว-ท้ายเป็นปัญหาที่พบบ่อยและน่าหงุดหงิดที่สุดเพราะมองไม่เห็น ลบได้ในบรรทัดเดียว:

raw_export.columns = raw_export.columns.str.strip()
print(raw_export.columns.tolist())

Python column list

สำหรับอักขระพิเศษ .str.replace() รับแพตเทิร์นเรกซ์ แพตเทิร์นด้านล่างเก็บเฉพาะตัวอักษร ตัวเลข ขีดล่าง และช่องว่าง แล้วตัดอย่างอื่นทิ้ง:

raw_export.columns = raw_export.columns.str.replace(r"[^a-zA-Z0-9_ ]", "", regex=True)
print(raw_export.columns.tolist())

Python column list

ขีดกลาง วงเล็บ และเครื่องหมายดอลลาร์หายไปแล้ว สังเกตว่า Total Amount มีช่องว่างท้ายชื่อ (จากตำแหน่ง ($) เดิม) และ OrderDate สูญเสียขีดกลางไปทั้งหมด ซึ่งเป็นเหตุผลว่าทำไมเราต้อง strip ซ้ำตอนท้ายไปป์ไลน์ทำความสะอาด

ทำมาตรฐานเป็น snake_case

แนวปฏิบัติที่พบบ่อยคือแปลงชื่อคอลัมน์ทั้งหมดเป็น snake_case ก่อนเริ่มวิเคราะห์ คือเป็นตัวพิมพ์เล็ก คั่นคำด้วยขีดล่าง ไม่มีอักขระพิเศษ เชนเมธอด .str เข้าด้วยกันเพื่อไปให้ถึงในนิพจน์เดียว:

raw_export = pd.DataFrame({
    "  Order ID ": [1001, 1002, 1003],
    "Customer Name (Full)": ["Abe", "Rick", "Pat"],
    "Total Amount ($)": [49.99, 120.00, 75.50],
    "Order-Date": ["2024-03-12", "2024-03-15", "2024-03-18"]
})

raw_export.columns = (
    raw_export.columns
    .str.strip()                                  # ลบช่องว่างหัว/ท้าย
    .str.lower()                                  # ทำเป็นตัวพิมพ์เล็กทั้งหมด
    .str.replace(r"[^a-z0-9]+", "_", regex=True)  # ยุบอักขระที่ไม่เป็นอักษร-ตัวเลขเป็นขีดล่าง
    .str.strip("_")                               # ลบขีดล่างหัว/ท้ายออก
)

print(raw_export.columns.tolist())

Python column list

สี่บรรทัด ชื่อคอลัมน์ของคุณก็กลายเป็นมาตรฐาน คาดเดาได้ ตัวพิมพ์เล็ก และคั่นด้วยขีดล่าง แพตเทิร์นนี้คุ้มที่จะบันทึกเป็นฟังก์ชันยูทิลิตี้ เมื่อมีแล้วก็โยนใส่ DataFrame ยุ่งๆ ได้ทุกราย

มักอยากรวมการเปลี่ยนชื่อเข้ากับการลบคอลัมน์ด้วย สำหรับเรื่องนั้น บทช่วยสอนการลบคอลัมน์ใน pandas คือขั้นถัดไป

จะเปลี่ยนชื่อคอลัมน์ตอนโหลดข้อมูลใน Pandas ได้อย่างไร?

หากรู้ล่วงหน้าอยู่แล้วว่าอยากได้ชื่อคอลัมน์ที่ต่างออกไป สามารถเปลี่ยนชื่อภายใน pd.read_csv() ได้เลย ส่งลิสต์ชื่อให้พารามิเตอร์ names และตั้ง header=0 เพื่อบอก pandas ให้ข้ามแถวเฮดเดอร์เดิมและใช้ชื่อของคุณแทน:

import pandas as pd
from io import StringIO

# Simulating a CSV file for demonstration
csv_data = """txnId,custId,amt,date
1001,C01,49.99,2024-01-15
1002,C02,125.00,2024-01-16
1003,C01,79.50,2024-01-17"""

# Renames columns at load time, skipping the original header
transactions = pd.read_csv(
    StringIO(csv_data),
    header=0,
    names=["transaction_id", "customer_id", "amount_usd", "transaction_date"]
)
print(transactions)

Python DataFrame

นี่เป็นทางลัดที่มีประโยชน์เมื่อควบคุมสคีมาเองและไม่อยากให้มีขั้น .rename() แยกมารกโค้ดโหลดข้อมูล หากไฟล์ไม่มีแถวเฮดเดอร์เลย ให้ละ header=0 และใช้แค่ names=[...] เพื่อกำหนดชื่อคอลัมน์ใหม่ตั้งแต่ต้น หากอยากเจาะลึกตัวเลือกการโหลดชุดข้อมูล แนะนำบทช่วยสอน pandas read_csv()

ข้อควรระวัง: วิธีนี้เป็นแบบทั้งหมดหรือไม่เลย พารามิเตอร์ names จะแทนที่ชื่อคอลัมน์ทุกคอลัมน์ ดังนั้นความยาวลิสต์ต้องตรงกับจำนวนคอลัมน์ในไฟล์พอดี หากอยากเปลี่ยนชื่อแค่บางคอลัมน์ ให้โหลดไฟล์ก่อนแล้วค่อยใช้ .rename() ภายหลัง

สำหรับการฝึกปฏิบัติรูปแบบเหล่านี้ร่วมกับงานทำความสะอาดทั่วไปอื่นๆ แนะนำให้เรียนคอร์ส Cleaning Data in Python

เปลี่ยนชื่อคอลัมน์ใน Polars เทียบกับ Pandas

หากทำงานทั้ง pandas และ Polars หรือคาดว่าจะทำ ควรรู้ว่าทั้งสองจัดการการเปลี่ยนชื่อคอลัมน์อย่างไร API ระดับสูงคล้ายกัน แต่รายละเอียดต่างกันในจุดที่อาจพลาดในครั้งแรกๆ Polars คือไลบรารี DataFrame ที่เร็วและสร้างบน Rust ซึ่งพบได้มากขึ้นในสแต็กข้อมูลยุคใหม่ และความคุ้นมือจาก pandas ไม่ได้ย้ายตามมาเสมอไป

แนวคิดหลักเหมือนกัน คือแมปชื่อเก่าเป็นชื่อใหม่ด้วยดิกชันนารี ความต่างอยู่ที่รายละเอียด Polars ออกแบบมาให้ไม่แก้ไขค่าเดิม (ไม่มี inplace) การเชนเมธอดคือสไตล์ที่เป็นธรรมชาติ และการเปลี่ยนชื่อระดับคอลัมน์ระหว่างการ select ใช้ .alias() แทนขั้นตอน rename แยก

เปรียบเทียบเคียงข้าง

งาน

Pandas

Polars

เปลี่ยนชื่อคอลัมน์ที่ระบุ

df.rename(columns={"old": "new"})

df.rename({"old": "new"})

แทนที่ชื่อคอลัมน์ทั้งหมด

df.columns = [...] หรือ df.set_axis([...], axis=1)

df.rename(dict(zip(df.columns, [...])))

เปลี่ยนชื่อระหว่าง select

เลือกก่อน แล้วค่อย .rename()

df.select(pl.col("old").alias("new"))

แก้ไขแบบ inplace

รองรับ inplace=True

ไม่รองรับ คืนค่าเป็น DataFrame ใหม่เสมอ

สไตล์ที่เป็นธรรมชาติ

inplace หรือเชน

เชนเสมอ

การเปลี่ยนชื่อเดียวกันในทั้งสองไลบรารี

เพื่อเปรียบเทียบ นี่คือตัวอย่างเปลี่ยนชื่ออย่างง่ายในแต่ละไลบรารี

Pandas:

# Pandas
import pandas as pd

orders_pd = pd.DataFrame({
    "ord_id": [1001, 1002, 1003],
    "cust_nm": ["Abe", "Rick", "Pat"]
})

orders_pd = orders_pd.rename(columns={"ord_id": "order_id", "cust_nm": "customer_name"})
print(orders_pd)

Python DataFrame

Polars:

# Polars
import polars as pl

orders_pl = pl.DataFrame({
    "ord_id": [1001, 1002, 1003],
    "cust_nm": ["Abe", "Rick", "Pat"]
})

orders_pl = orders_pl.rename({"ord_id": "order_id", "cust_nm": "customer_name"})
print(orders_pl)

Python DataFrame

ต่างกันเล็กน้อยสองอย่าง .rename() ของ Polars รับดิกชันนารีโดยตรง ไม่มีคีย์เวิร์ด columns= เพราะ Polars รองรับเฉพาะการเปลี่ยนชื่อคอลัมน์ (ไม่มีดัชนีแถว) และต้องกำหนดค่ากลับผลลัพธ์ ไม่มี inplace=True ใน Polars ทุกการดำเนินการคืนค่าเป็น DataFrame ใหม่

ผลลัพธ์ของ Polars ยังแสดง dtype แบบอินไลน์ (i64, str) และขนาดด้านบน ซึ่งเป็นสิ่งเล็กๆ ที่หลายคนชอบหลังจากเปลี่ยนมาใช้

เปลี่ยนชื่อคอลัมน์ระหว่าง select

สำหรับการเปลี่ยนชื่อระหว่างการแปลง Polars ใช้ .alias() ภายใน .select() หรือ .with_columns():

# Polars
import polars as pl

orders_pl = pl.DataFrame({
    "ord_id": [1001, 1002, 1003],
    "cust_nm": ["Abe", "Rick", "Pat"]
})

# Select and rename in one expression
renamed = orders_pl.select(
    pl.col("ord_id").alias("order_id"),
    pl.col("cust_nm").alias("customer_name")
)

print(renamed)

Python DataFrame

ใน pandas สิ่งที่คล้ายกันคือทำ .rename() หลังจากเลือกคอลัมน์ ทั้งสองแนวทางไม่มีอันไหนดีกว่า แค่สะท้อนปรัชญาการออกแบบของแต่ละไลบรารี

หากอยากเปรียบเทียบเชิงลึกของทั้งสอง แนะนำบทช่วยสอน ประสิทธิภาพ pandas เทียบกับ polars และถ้าอยากเพิ่ม polars เข้าเครื่องมือ แนะนำคอร์ส Introduction to Polars ด้วย

ข้อผิดพลาดที่พบบ่อยและวิธีแก้

มีข้อผิดพลาดสองอย่างที่มักเกิดขึ้นซ้ำเมื่อเปลี่ยนชื่อคอลัมน์ใน pandas นี่คือหน้าตา สาเหตุ และวิธีแก้

KeyError: ไม่พบชื่อคอลัมน์

โดยค่าเริ่มต้น .rename() จะมองข้ามคีย์ที่ไม่ตรงกับคอลัมน์ที่มีอย่างเงียบๆ แต่หากส่ง errors='raise' เพื่อจับตัวสะกดผิด คุณจะได้ KeyError เมื่อคีย์ไม่มีอยู่จริง:

import pandas as pd

orders = pd.DataFrame({
    "order_id": [1001, 1002, 1003],
    "customer_name": ["Abe", "Rick", "Pat"]
})

# This raises an error
orders.rename(columns={"Order_ID": "order_id"}, errors="raise")

KeyError

สาเหตุที่พบบ่อยที่สุดคือความผิดพลาดเรื่องตัวพิมพ์ (Order_ID เทียบกับ order_id) หรือช่องว่างท้ายชื่อที่มองไม่เห็น ("order_id " เทียบกับ "order_id") เมื่อเจอ KeyError ให้ตรวจสามอย่างตามลำดับ:

  1. การสะกดและตัวพิมพ์ที่ตรงกัน
  2. ช่องว่างที่ซ่อนอยู่
  3. คอลัมน์ถูกเปลี่ยนชื่อไปก่อนหน้านี้แล้วหรือไม่

เพื่อยืนยันชื่อคอลัมน์จริงๆ:

print(orders.columns.tolist())

# Use repr() as an alternative
print([repr(c) for c in orders.columns])

Python column list

เมื่อเห็นสตริงจริงๆ ที่ pandas เก็บไว้ ก็มักเห็นตัวสะกดผิดชัดเจน แล้วแก้ไขให้ถูกและรันใหม่:

orders = orders.rename(columns={"order_id": "Order_ID"}, errors="raise")
print(orders.columns.tolist())

Python column list

แล้วควรใช้ errors='raise' เมื่อไร เทียบกับค่าเริ่มต้น errors='ignore'?

  • ค่าเริ่มต้นยืดหยุ่น เหมาะในสคริปต์ที่ประมวลผล DataFrame หลายสคีมาที่คอลัมน์หายไม่ควรทำให้พังทั้งกระบวนการ 

  • สลับเป็น errors='raise' เมื่อต้องการให้ตัวสะกดผิดโผล่ชัดๆ ระหว่างพัฒนา โดยเฉพาะในโน้ตบุ๊กที่ความล้มเหลวเงียบๆ ทำให้เสียเวลางงทีหลังหลายชั่วโมง

ValueError: ความยาวไม่ตรงกับ df.columns

เมื่อกำหนดลิสต์ให้ df.columns หรือใช้ .set_axis() ความยาวลิสต์ต้องตรงกับจำนวนคอลัมน์พอดี หากไม่ตรง pandas จะโยน ValueError:

import pandas as pd

products = pd.DataFrame({
    "sku": ["A100", "A101", "A102"],
    "name": ["Widget", "Gadget", "Gizmo"],
    "price": [9.99, 14.99, 19.99]
})

# This raises an error
products.columns = ["product_sku", "product_name"]

ValueError

DataFrame มีสามคอลัมน์ แต่ระบุชื่อใหม่มาแค่สองชื่อ วิธีแก้คือเช็กจำนวนคอลัมน์ก่อนกำหนด:

print(len(products.columns))
products.columns = ["product_sku", "product_name", "product_price"]
print(products.columns.tolist())

Python column list

หากทำงานกับ DataFrame ที่จำนวนคอลัมน์อาจเปลี่ยนได้ ปลอดภัยกว่าหากใช้ .rename() กับดิกชันนารี มันจะเปลี่ยนเฉพาะคอลัมน์ที่คุณระบุ จึงไม่พังเมื่อมีคอลัมน์เกินหรือขาด

ท้ายที่สุด

การเปลี่ยนชื่อคอลัมน์ใน pandas สรุปคือเลือกวิธีให้ตรงกับขอบเขตงาน ไม่ว่าทำแบบใด สิ่งที่ได้จริงที่สุดคือกำหนดมาตรฐานการตั้งชื่อเดียวและใช้เป็นขั้นตอนแรกในทุกการวิเคราะห์ snake_case เป็นสิ่งที่โค้ด Python ส่วนใหญ่ใช้ ชื่อคอลัมน์ที่สะอาดใช้เวลาแค่ไม่กี่วินาทีตอนเริ่ม และช่วยกันเซอร์ไพรส์จาก KeyError ตลอดทั้งโปรเจ็กต์

ใช้ .rename() พร้อมดิกชันนารีสำหรับการเปลี่ยนชื่อแบบเจาะจง เมื่อทุกคอลัมน์ต้องมีชื่อใหม่ การกำหนดให้ df.columns หรือใช้ .set_axis() เร็วกว่าสร้างดิกชันนารีแมปชื่อเก่ากับชื่อใหม่ทั้งหมด และหากการตั้งชื่อตามกฎอย่างการตัดช่องว่าง ทำเป็นตัวพิมพ์เล็กทั้งหมด แปลงจาก camelCase ให้ส่งฟังก์ชันหรือใช้ตัวเข้าถึง .str เพื่อระบุกฎเพียงครั้งเดียวแทนการไล่กรณีทีละชื่อ Polars จัดการงานเดียวกันด้วย API คล้ายกัน แต่สไตล์ที่ไม่แก้ไขค่าเดิมและเน้นเชนจะปรับนิสัยการเขียนของคุณเล็กน้อย

เพื่อพัฒนาทักษะ DataFrame ต่อไป แนะนำคอร์ส Data Manipulation with pandas เป็นขั้นถัดไป หากอยากได้เส้นทางเรียนรู้แบบเป็นระบบ เส้นทางอาชีพ Data Analyst in Python ครอบคลุมการจัดการ DataFrame ควบคู่กับเครื่องมืออื่นๆ ของนักวิเคราะห์

FAQs สำหรับการเปลี่ยนชื่อคอลัมน์ใน Pandas

จะเปลี่ยนชื่อคอลัมน์ใน pandas ได้อย่างไร?

มีหลายวิธี แต่ตรงไปตรงมาที่สุดคือ ใช้ df = df.rename(columns={"old_name": "new_name"}) นอกจากนี้ยังสามารถส่งอาร์กิวเมนต์ inplace=True เพื่อแก้ไข DataFrame โดยตรงได้

จะเปลี่ยนชื่อหลายคอลัมน์ใน pandas ได้อย่างไร?

เพื่อเปลี่ยนชื่อหลายคอลัมน์ใน pandas ให้ส่งการเปลี่ยนชื่อทั้งหมดในดิกชันนารีเดียว: df.rename(columns={"old1": "new1", "old2": "new2"})

จะเปลี่ยนชื่อคอลัมน์ทั้งหมดใน pandas DataFrame ได้อย่างไร?

กำหนดลิสต์ชื่อใหม่ให้ df.columns ข้อควรระวัง: ความยาวลิสต์ต้องเท่ากับจำนวนคอลัมน์ ไม่เช่นนั้นจะได้ ValueError.

ทำไม df.rename() ไม่เปลี่ยน DataFrame ของฉัน?

โดยค่าเริ่มต้น .rename() จะคืนค่า DataFrame ใหม่ ให้กำหนดค่ากลับด้วย df = df.rename(...) หรือใช้ inplace=True.

จะเปลี่ยนชื่อคอลัมน์ให้เป็นตัวพิมพ์เล็กทั้งหมดใน pandas ได้อย่างไร?

ใช้ df.columns = df.columns.str.lower() เพื่อทำให้ชื่อคอลัมน์ทุกคอลัมน์เป็นตัวพิมพ์เล็กในขั้นตอนเดียว

หัวข้อ

เรียนรู้ Python กับ DataCamp!

Courses

การจัดการข้อมูลด้วย pandas

4 ชม.
559.2K
เรียนรู้วิธีนำเข้าและทำความสะอาดข้อมูล คำนวณสถิติ และสร้างภาพข้อมูลด้วย pandas
ดูรายละเอียดRight Arrow
เริ่มหลักสูตร
ดูเพิ่มเติมRight Arrow