การทำงานกับข้อมูลด้วย Pandas เริ่มต้นจากการนำเข้าข้อมูลจากแหล่งต่างๆ และการสำรวจข้อมูลเบื้องต้นเพื่อทำความเข้าใจโครงสร้าง คุณภาพ และลักษณะของข้อมูล ขั้นตอนนี้เปรียบเสมือนการเปิดประตูสู่โลกของข้อมูล ที่เราจะต้องเข้าใจก่อนเริ่มวิเคราะห์
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#458588','primaryTextColor':'#ebdbb2','primaryBorderColor':'#83a598','lineColor':'#fabd2f','secondaryColor':'#b16286','tertiaryColor':'#689d6a','background':'#282828','mainBkg':'#3c3836','secondBkg':'#504945','textColor':'#ebdbb2','fontSize':'16px'}}}%%
flowchart TD
A["🗂️ แหล่งข้อมูล
(Data Sources)"] --> B["📥 การนำเข้า
(Data Loading)"]
B --> C["👀 การสำรวจเบื้องต้น
(Initial Inspection)"]
C --> D["📊 การดูภาพรวม
(Overview Analysis)"]
D --> E["✅ พร้อมวิเคราะห์
(Ready for Analysis)"]
B -.->|CSV| B1["read_csv()"]
B -.->|Excel| B2["read_excel()"]
B -.->|JSON| B3["read_json()"]
B -.->|SQL| B4["read_sql()"]
C -.->|ตัวอย่างข้อมูล| C1["head() / tail()"]
C -.->|สุ่มข้อมูล| C2["sample()"]
D -.->|โครงสร้าง| D1["info() / dtypes"]
D -.->|สถิติ| D2["describe()"]
D -.->|มิติข้อมูล| D3["shape / columns"]
style A fill:#458588,stroke:#83a598,stroke-width:3px,color:#ebdbb2
style B fill:#b16286,stroke:#d3869b,stroke-width:3px,color:#ebdbb2
style C fill:#689d6a,stroke:#8ec07c,stroke-width:3px,color:#ebdbb2
style D fill:#d79921,stroke:#fabd2f,stroke-width:3px,color:#282828
style E fill:#98971a,stroke:#b8bb26,stroke-width:3px,color:#282828
Pandas รองรับการอ่านข้อมูลจากหลากหลายรูปแบบไฟล์ โดยแต่ละรูปแบบมีฟังก์ชันเฉพาะและพารามิเตอร์ที่ช่วยให้การนำเข้าข้อมูลมีความยืดหยุ่นสูง
CSV เป็นรูปแบบไฟล์ที่นิยมใช้มากที่สุดในการจัดเก็บข้อมูลแบบตาราง เนื่องจากมีขนาดเล็ก อ่านง่าย และรองรับได้ทุกแพลตฟอร์ม
import pandas as pd
def read_csv_basic():
"""
ฟังก์ชันสำหรับอ่านไฟล์ CSV แบบพื้นฐาน
Returns:
DataFrame: ข้อมูลที่อ่านจากไฟล์ CSV
"""
# การอ่านไฟล์ CSV แบบธรรมดา
df = pd.read_csv('data.csv')
# การระบุ encoding สำหรับภาษาไทย
df_thai = pd.read_csv('data_thai.csv', encoding='utf-8-sig')
# การระบุ separator อื่นๆ (เช่น tab-separated)
df_tsv = pd.read_csv('data.tsv', sep='\t')
# การกำหนด column เป็น index
df_indexed = pd.read_csv('data.csv', index_col=0)
# การข้ามบรรทัดแรก (ถ้ามี header หลายบรรทัด)
df_skip = pd.read_csv('data.csv', skiprows=2)
# การอ่านเฉพาะบาง columns
df_selected = pd.read_csv('data.csv', usecols=['name', 'age', 'salary'])
# การกำหนดประเภทข้อมูลตั้งแต่ตอนอ่าน
dtype_dict = {
'id': int,
'name': str,
'score': float
}
df_typed = pd.read_csv('data.csv', dtype=dtype_dict)
return df
# ตัวอย่างการใช้งานขั้นสูง
def read_large_csv():
"""
อ่านไฟล์ CSV ขนาดใหญ่แบบมีประสิทธิภาพ
Tips:
- ใช้ chunksize สำหรับไฟล์ใหญ่มาก
- ระบุ dtype เพื่อประหยัด memory
"""
# อ่านทีละ chunk สำหรับไฟล์ขนาดใหญ่
chunk_size = 10000
chunks = []
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
# ประมวลผลแต่ละ chunk
processed_chunk = chunk[chunk['value'] > 0]
chunks.append(processed_chunk)
# รวม chunks ทั้งหมด
df_final = pd.concat(chunks, ignore_index=True)
return df_final
พารามิเตอร์สำคัญของ read_csv():
| พารามิเตอร์ | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| filepath | ตำแหน่งไฟล์ (path หรือ URL) | 'data.csv', 'https://example.com/data.csv' |
| sep | ตัวคั่นข้อมูล (delimiter) | ',', '\t', ';' |
| header | แถวที่เป็น column names | 0 (default), None, [0,1] |
| index_col | column ที่จะใช้เป็น index | 0, 'id', ['year', 'month'] |
| usecols | เลือกเฉพาะ columns ที่ต้องการ | ['name', 'age'], [0, 2, 5] |
| dtype | กำหนดประเภทข้อมูล | {'age': int, 'name': str} |
| na_values | ค่าที่ถือว่าเป็น NaN | ['NA', 'null', ''] |
| encoding | รูปแบบการเข้ารหัสอักขระ | 'utf-8', 'utf-8-sig', 'cp874' |
| skiprows | จำนวนแถวที่ต้องการข้าม | 1, [0, 2, 5] |
| nrows | จำนวนแถวที่ต้องการอ่าน | 1000 |
Excel เป็นรูปแบบไฟล์ที่นิยมใช้ในองค์กร โดยเฉพาะสำหรับการจัดการข้อมูลที่มีหลาย sheets
def read_excel_files():
"""
ฟังก์ชันสำหรับอ่านไฟล์ Excel ในรูปแบบต่างๆ
Note:
ต้องติดตั้ง openpyxl หรือ xlrd: pip install openpyxl
"""
# อ่าน sheet แรก (default)
df = pd.read_excel('data.xlsx')
# อ่าน sheet ที่ระบุชื่อ
df_sales = pd.read_excel('report.xlsx', sheet_name='Sales')
# อ่านหลาย sheets พร้อมกัน
df_dict = pd.read_excel('report.xlsx', sheet_name=['Sales', 'Expenses', 'Summary'])
# ผลลัพธ์เป็น dictionary: {'Sales': df1, 'Expenses': df2, 'Summary': df3}
# อ่านทุก sheets
df_all = pd.read_excel('report.xlsx', sheet_name=None)
# ระบุ engine สำหรับไฟล์ Excel เวอร์ชันเก่า (.xls)
df_old = pd.read_excel('old_data.xls', engine='xlrd')
# ระบุ range ของข้อมูล (เหมือนใน Excel)
df_range = pd.read_excel('data.xlsx', usecols='A:E', skiprows=3, nrows=100)
return df, df_dict
# ตัวอย่างการประมวลผลหลาย sheets
def process_multiple_sheets():
"""
อ่านและประมวลผลข้อมูลจากหลาย sheets
"""
# อ่านทุก sheets
all_sheets = pd.read_excel('monthly_report.xlsx', sheet_name=None)
# รวมข้อมูลจากทุก sheets
combined_df = pd.concat(all_sheets.values(), ignore_index=True)
# หรือประมวลผลแต่ละ sheet แยกกัน
results = {}
for sheet_name, df in all_sheets.items():
# คำนวณผลรวมของแต่ละ sheet
results[sheet_name] = df['sales'].sum()
return combined_df, results
การเปรียบเทียบ Excel Engines:
| Engine | ไฟล์ที่รองรับ | ความเร็ว | ข้อดี | ข้อจำกัด |
|---|---|---|---|---|
| openpyxl | .xlsx, .xlsm | ปานกลาง | รองรับ Excel 2010+, อ่าน-เขียนได้ | ช้ากว่า xlrd |
| xlrd | .xls, .xlsx | เร็ว | เร็วมาก, เสถียร | อ่านอย่างเดียว, ไม่รองรับ .xlsx ใหม่ |
| pyxlsb | .xlsb | เร็วที่สุด | สำหรับไฟล์ binary Excel | รองรับเฉพาะ .xlsb |
JSON เป็นรูปแบบข้อมูลที่นิยมใช้ใน Web APIs และ NoSQL databases มีโครงสร้างแบบ hierarchical
def read_json_formats():
"""
ฟังก์ชันสำหรับอ่านไฟล์ JSON ในรูปแบบต่างๆ
JSON สามารถมีโครงสร้างได้หลายแบบ:
- Records: [{col1: val1, col2: val2}, {...}]
- Index: {index1: {col1: val1, col2: val2}, index2: {...}}
- Columns: {col1: {index1: val1, index2: val2}, col2: {...}}
"""
# อ่าน JSON แบบ records (array of objects)
df_records = pd.read_json('data.json', orient='records')
# อ่าน JSON แบบ index
df_index = pd.read_json('data.json', orient='index')
# อ่าน JSON แบบ columns
df_columns = pd.read_json('data.json', orient='columns')
# อ่านจาก JSON string
json_string = '[{"name": "John", "age": 30}, {"name": "Jane", "age": 25}]'
df_from_string = pd.read_json(json_string)
# อ่านจาก API endpoint
url = 'https://api.example.com/data'
df_api = pd.read_json(url)
# อ่าน nested JSON (JSON ซ้อน JSON)
df_nested = pd.read_json('nested_data.json')
df_normalized = pd.json_normalize(df_nested['data']) # แปลง nested เป็น flat
return df_records, df_normalized
# ตัวอย่างการจัดการ nested JSON
def handle_nested_json():
"""
จัดการกับ JSON ที่มีโครงสร้างซับซ้อน
"""
# ตัวอย่าง nested JSON
data = {
'users': [
{
'name': 'John',
'age': 30,
'address': {
'city': 'Bangkok',
'country': 'Thailand'
},
'hobbies': ['reading', 'coding']
},
{
'name': 'Jane',
'age': 25,
'address': {
'city': 'Chiang Mai',
'country': 'Thailand'
},
'hobbies': ['traveling', 'photography']
}
]
}
# แปลงเป็น DataFrame แบบ flat
df = pd.json_normalize(
data['users'],
sep='_', # ตัวคั่นระหว่าง nested keys
max_level=2 # ระดับความลึกสูงสุด
)
return df
def read_other_sources():
"""
ตัวอย่างการอ่านข้อมูลจากแหล่งอื่นๆ
"""
# 1. อ่านจาก SQL Database
import sqlite3
conn = sqlite3.connect('database.db')
df_sql = pd.read_sql('SELECT * FROM users WHERE age > 25', conn)
conn.close()
# 2. อ่านจาก Clipboard
# คัดลอกข้อมูลจาก Excel ก่อน แล้วรันคำสั่งนี้
df_clipboard = pd.read_clipboard()
# 3. อ่านจาก HTML table
url = 'https://example.com/table_page.html'
df_html_list = pd.read_html(url) # ส่งคืน list ของ DataFrames
df_html = df_html_list[0] # เลือกตารางแรก
# 4. อ่านจาก Parquet (ไฟล์แบบ columnar storage)
df_parquet = pd.read_parquet('data.parquet')
# 5. อ่านจาก Pickle (Python object serialization)
df_pickle = pd.read_pickle('data.pkl')
# 6. อ่านจาก Feather (รูปแบบที่เร็วมาก)
df_feather = pd.read_feather('data.feather')
return df_sql, df_html, df_parquet
# เปรียบเทียบรูปแบบไฟล์
def compare_file_formats():
"""
สร้างและบันทึกข้อมูลในรูปแบบต่างๆ เพื่อเปรียบเทียบ
"""
import numpy as np
import time
# สร้างข้อมูลตัวอย่าง
df = pd.DataFrame({
'id': range(100000),
'value': np.random.randn(100000),
'category': np.random.choice(['A', 'B', 'C'], 100000)
})
formats = {
'CSV': lambda: df.to_csv('test.csv', index=False),
'Excel': lambda: df.to_excel('test.xlsx', index=False),
'Parquet': lambda: df.to_parquet('test.parquet'),
'Pickle': lambda: df.to_pickle('test.pkl'),
'Feather': lambda: df.to_feather('test.feather')
}
results = {}
for name, save_func in formats.items():
start = time.time()
save_func()
elapsed = time.time() - start
results[name] = elapsed
print(f"{name}: {elapsed:.4f} seconds")
return results
เปรียบเทียบรูปแบบไฟล์:
| รูปแบบ | ขนาดไฟล์ | ความเร็วอ่าน | ความเร็วเขียน | Use Case |
|---|---|---|---|---|
| CSV | ใหญ่ | ช้า | ช้า | ข้อมูลทั่วไป, แชร์ง่าย |
| Excel | ใหญ่มาก | ช้ามาก | ช้ามาก | รายงาน, visualization ใน Excel |
| Parquet | เล็กมาก | เร็วมาก | เร็ว | Big Data, columnar analysis |
| Pickle | ปานกลาง | เร็วมาก | เร็วมาก | Python-specific, temporary storage |
| Feather | เล็ก | เร็วที่สุด | เร็วที่สุด | แชร์ระหว่าง Python-R |
| JSON | ใหญ่ | ช้า | ช้า | Web APIs, nested data |
หลังจากนำเข้าข้อมูลแล้ว ขั้นตอนถัดไปคือการมองดูข้อมูลเบื้องต้น เพื่อทำความเข้าใจว่าข้อมูลมีหน้าตาอย่างไร มีกี่แถว มีคอลัมน์อะไรบ้าง
head() และ tail() เป็นเมธอดพื้นฐานที่ช่วยให้เราดูข้อมูลส่วนบนและส่วนล่างของ DataFrame
def inspect_data_samples():
"""
ฟังก์ชันสำหรับการดูข้อมูลตัวอย่าง
Returns:
tuple: ข้อมูลส่วนบนและส่วนล่าง
"""
# สร้างข้อมูลตัวอย่าง
df = pd.DataFrame({
'student_id': range(1, 101),
'name': [f'Student_{i}' for i in range(1, 101)],
'score': pd.np.random.randint(50, 100, 100),
'grade': pd.np.random.choice(['A', 'B', 'C', 'D'], 100)
})
# ดู 5 แถวแรก (default)
print("=== 5 แถวแรก ===")
print(df.head())
# ดู 10 แถวแรก
print("\n=== 10 แถวแรก ===")
print(df.head(10))
# ดู 5 แถวสุดท้าย (default)
print("\n=== 5 แถวสุดท้าย ===")
print(df.tail())
# ดู 3 แถวสุดท้าย
print("\n=== 3 แถวสุดท้าย ===")
print(df.tail(3))
# เทคนิค: ดูทั้งต้นและท้ายพร้อมกัน
print("\n=== ดูทั้งต้นและท้าย ===")
print(pd.concat([df.head(3), df.tail(3)]))
return df.head(), df.tail()
เมื่อไหร่ควรใช้ head() และ tail():
sample() ช่วยให้เราสุ่มดูข้อมูลแบบสุ่มจากทั้งหมด ซึ่งมีประโยชน์มากกว่า head/tail เพราะได้เห็นข้อมูลที่หลากหลาย
def random_sampling():
"""
ฟังก์ชันสำหรับการสุ่มตัวอย่างข้อมูล
Note:
sample() มีประโยชน์มากในการ:
- ตรวจสอบข้อมูลแบบสุ่ม
- สร้าง training/testing datasets
- ดูความหลากหลายของข้อมูล
"""
# สร้างข้อมูลตัวอย่าง
df = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=1000),
'sales': np.random.randint(1000, 5000, 1000),
'region': np.random.choice(['North', 'South', 'East', 'West'], 1000)
})
# สุ่ม 5 แถว (default)
print("=== สุ่ม 5 แถว ===")
print(df.sample())
# สุ่มจำนวนที่กำหนด
print("\n=== สุ่ม 10 แถว ===")
print(df.sample(n=10))
# สุ่มตามเปอร์เซ็นต์
print("\n=== สุ่ม 10% ของข้อมูลทั้งหมด ===")
print(df.sample(frac=0.1))
# สุ่มแบบ replacement (สุ่มซ้ำได้)
print("\n=== สุ่มแบบคืนกลับ ===")
print(df.sample(n=20, replace=True))
# สุ่มแบบกำหนด random_state (เพื่อให้ได้ผลลัพธ์เดิมทุกครั้ง)
print("\n=== สุ่มแบบ reproducible ===")
print(df.sample(n=5, random_state=42))
print(df.sample(n=5, random_state=42)) # ได้ผลลัพธ์เดิม
# สุ่มแบบมี weights (ความน่าจะเป็นไม่เท่ากัน)
weights = [1 if region == 'North' else 0.1 for region in df['region']]
print("\n=== สุ่มโดยให้น้ำหนัก North มากกว่า ===")
print(df.sample(n=10, weights=weights))
return df.sample(frac=0.1)
# ตัวอย่างการใช้ sample() ในการแบ่งข้อมูล
def train_test_split_example():
"""
ใช้ sample() เพื่อแบ่งข้อมูลเป็น training และ testing sets
"""
df = pd.DataFrame({
'feature1': np.random.randn(1000),
'feature2': np.random.randn(1000),
'target': np.random.randint(0, 2, 1000)
})
# แบ่งข้อมูล 80% train, 20% test
train = df.sample(frac=0.8, random_state=42)
test = df.drop(train.index)
print(f"Training set: {len(train)} rows")
print(f"Testing set: {len(test)} rows")
return train, test
พารามิเตอร์สำคัญของ sample():
| พารามิเตอร์ | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| n | จำนวนแถวที่ต้องการสุ่ม | n=10 |
| frac | เปอร์เซ็นต์ของข้อมูลทั้งหมด | frac=0.1 (10%) |
| replace | สุ่มแบบคืนกลับหรือไม่ | replace=True |
| random_state | seed สำหรับ random | random_state=42 |
| weights | ความน่าจะเป็นของแต่ละแถว | weights=column_name |
| axis | สุ่ม rows (0) หรือ columns (1) | axis=1 |
def interactive_viewing():
"""
เทคนิคการดูข้อมูลแบบโต้ตอบและยืดหยุ่น
"""
df = pd.DataFrame({
'id': range(1, 1001),
'category': np.random.choice(['Electronics', 'Clothing', 'Food'], 1000),
'price': np.random.uniform(10, 1000, 1000),
'quantity': np.random.randint(1, 100, 1000)
})
# แสดงทุกคอลัมน์ (ไม่ตัดทอน)
with pd.option_context('display.max_columns', None):
print(df.head())
# แสดงทุกแถว (ระวัง: อาจช้าถ้าข้อมูลเยอะ)
with pd.option_context('display.max_rows', None):
print(df)
# ตั้งค่าการแสดงผลแบบกว้างขึ้น
pd.set_option('display.width', 200)
pd.set_option('display.max_colwidth', 50)
# แสดงข้อมูลแบบ transpose (สลับแถว-คอลัมน์)
print("\n=== แสดงแบบ Transpose ===")
print(df.head().T)
return df
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#458588','primaryTextColor':'#ebdbb2','primaryBorderColor':'#83a598','lineColor':'#fabd2f','secondaryColor':'#b16286','tertiaryColor':'#689d6a','background':'#282828','mainBkg':'#3c3836','secondBkg':'#504945','textColor':'#ebdbb2','fontSize':'14px'}}}%%
graph LR
A["📊 DataFrame"] --> B["head()"]
A --> C["tail()"]
A --> D["sample()"]
B --> B1["ดู n แถวแรก
(View first n rows)"]
C --> C1["ดู n แถวสุดท้าย
(View last n rows)"]
D --> D1["สุ่มตัวอย่าง
(Random sampling)"]
B1 --> E["✅ เข้าใจโครงสร้างข้อมูล"]
C1 --> E
D1 --> E
style A fill:#458588,stroke:#83a598,stroke-width:3px,color:#ebdbb2
style B fill:#b16286,stroke:#d3869b,stroke-width:2px,color:#ebdbb2
style C fill:#b16286,stroke:#d3869b,stroke-width:2px,color:#ebdbb2
style D fill:#b16286,stroke:#d3869b,stroke-width:2px,color:#ebdbb2
style E fill:#98971a,stroke:#b8bb26,stroke-width:3px,color:#282828
การทำความเข้าใจภาพรวมของข้อมูล เป็นขั้นตอนสำคัญที่จะช่วยให้เรารู้ว่าข้อมูลมีลักษณะอย่างไร มีปัญหาอะไรบ้าง และควรทำความสะอาดอย่างไร
info() เป็นเมธอดที่ให้ข้อมูลสรุปที่สำคัญที่สุดของ DataFrame ในคำสั่งเดียว
def data_info_analysis():
"""
ฟังก์ชันสำหรับการวิเคราะห์ข้อมูลด้วย info()
info() จะแสดง:
1. จำนวนแถวและคอลัมน์
2. ชื่อคอลัมน์ทั้งหมด
3. จำนวน non-null values ในแต่ละคอลัมน์
4. ประเภทข้อมูล (dtype) ของแต่ละคอลัมน์
5. การใช้ memory
"""
# สร้างข้อมูลตัวอย่างที่มี missing values
df = pd.DataFrame({
'student_id': range(1, 101),
'name': [f'Student_{i}' if i % 10 != 0 else None for i in range(1, 101)],
'age': [np.random.randint(18, 25) if i % 15 != 0 else None for i in range(1, 101)],
'score': np.random.uniform(50, 100, 100),
'grade': np.random.choice(['A', 'B', 'C', 'D', 'F'], 100),
'enrollment_date': pd.date_range('2024-01-01', periods=100)
})
print("=== ข้อมูลทั่วไป (General Information) ===")
df.info()
print("\n=== ข้อมูลละเอียด (Detailed Information) ===")
df.info(verbose=True)
print("\n=== การใช้ memory แบบละเอียด ===")
df.info(memory_usage='deep')
# การตรวจสอบประเภทข้อมูล
print("\n=== ประเภทข้อมูลของแต่ละคอลัมน์ ===")
print(df.dtypes)
# นับจำนวนแต่ละประเภทข้อมูล
print("\n=== จำนวนคอลัมน์แต่ละประเภท ===")
print(df.dtypes.value_counts())
return df
# ตัวอย่างการใช้ info() ในการตรวจสอบปัญหา
def detect_data_issues():
"""
ใช้ info() ในการตรวจหาปัญหาข้อมูล
"""
df = pd.DataFrame({
'id': range(1, 1001),
'amount': [str(x) if x % 100 == 0 else x for x in np.random.uniform(100, 1000, 1000)],
'date': ['2024-01-0' + str(i % 9 + 1) if i % 50 != 0 else '2024/01/01'
for i in range(1, 1001)],
'status': np.random.choice(['Active', 'Inactive', None], 1000)
})
print("=== ตรวจสอบประเภทข้อมูลที่ไม่ถูกต้อง ===")
df.info()
# ตรวจสอบ missing values
missing_counts = df.isnull().sum()
print("\n=== จำนวน Missing Values ===")
print(missing_counts[missing_counts > 0])
# ตรวจสอบการใช้ memory
memory_usage = df.memory_usage(deep=True)
print(f"\n=== การใช้ Memory รวม: {memory_usage.sum() / 1024**2:.2f} MB ===")
return df
ข้อมูลที่ได้จาก info():
| ข้อมูล | คำอธิบาย | ประโยชน์ |
|---|---|---|
| RangeIndex | จำนวนแถวและ index range | รู้ขนาดข้อมูล |
| Data columns | จำนวนคอลัมน์ทั้งหมด | เห็นภาพรวมโครงสร้าง |
| Non-Null Count | จำนวนค่าที่ไม่ใช่ null | ตรวจหา missing data |
| Dtype | ประเภทข้อมูล | ตรวจสอบความถูกต้อง |
| Memory usage | การใช้หน่วยความจำ | วางแผนการประมวลผล |
describe() คำนวณสถิติเชิงพรรณนา (Descriptive Statistics) ให้โดยอัตโนมัติ
def descriptive_statistics():
"""
ฟังก์ชันสำหรับการวิเคราะห์สถิติเชิงพรรณนา
describe() แสดงค่าสถิติ:
- count: จำนวนค่าที่ไม่ใช่ null
- mean: ค่าเฉลี่ย
- std: ส่วนเบี่ยงเบนมาตรฐาน
- min: ค่าต่ำสุด
- 25%, 50%, 75%: percentiles
- max: ค่าสูงสุด
"""
# สร้างข้อมูลตัวอย่าง
np.random.seed(42)
df = pd.DataFrame({
'age': np.random.randint(18, 65, 1000),
'salary': np.random.normal(50000, 15000, 1000),
'experience_years': np.random.randint(0, 30, 1000),
'satisfaction_score': np.random.uniform(1, 5, 1000),
'department': np.random.choice(['IT', 'Sales', 'HR', 'Marketing'], 1000),
'is_manager': np.random.choice([True, False], 1000)
})
# สถิติเบื้องต้น (เฉพาะตัวเลข)
print("=== สถิติพื้นฐาน (Numeric columns only) ===")
print(df.describe())
# สถิติรวมทุกประเภทข้อมูล
print("\n=== สถิติทุกประเภทข้อมูล ===")
print(df.describe(include='all'))
# สถิติเฉพาะข้อมูลประเภท object (string)
print("\n=== สถิติข้อมูล Categorical ===")
print(df.describe(include=['object', 'bool']))
# กำหนด percentiles เอง
print("\n=== สถิติ Custom Percentiles ===")
print(df.describe(percentiles=[.1, .25, .5, .75, .9, .95, .99]))
# สถิติของคอลัมน์เฉพาะ
print("\n=== สถิติคอลัมน์ salary ===")
print(df['salary'].describe())
return df
# ตัวอย่างการคำนวณสถิติเพิ่มเติม
def advanced_statistics():
"""
คำนวณสถิติเพิ่มเติมที่ describe() ไม่มี
"""
df = pd.DataFrame({
'values': np.random.randn(1000)
})
stats_dict = {
'count': df['values'].count(),
'mean': df['values'].mean(),
'median': df['values'].median(),
'mode': df['values'].mode()[0],
'std': df['values'].std(),
'var': df['values'].var(),
'min': df['values'].min(),
'max': df['values'].max(),
'range': df['values'].max() - df['values'].min(),
'skewness': df['values'].skew(), # ความเบ้
'kurtosis': df['values'].kurtosis(), # ความโด่ง
'q25': df['values'].quantile(0.25),
'q75': df['values'].quantile(0.75),
'iqr': df['values'].quantile(0.75) - df['values'].quantile(0.25) # IQR
}
print("=== สถิติเพิ่มเติม ===")
for stat_name, value in stats_dict.items():
print(f"{stat_name:12s}: {value:10.4f}")
return pd.Series(stats_dict)
สูตรสถิติพื้นฐาน:
ค่าเฉลี่ย (Mean):
โดยที่:
ส่วนเบี่ยงเบนมาตรฐาน (Standard Deviation):
โดยที่:
def data_dimensions_structure():
"""
ฟังก์ชันสำหรับการตรวจสอบมิติและโครงสร้างข้อมูล
ตรวจสอบ:
- shape: มีกี่แถว กี่คอลัมน์
- columns: ชื่อคอลัมน์ทั้งหมด
- index: ข้อมูล index
- ndim: จำนวนมิติ
- size: จำนวนค่าทั้งหมด
"""
# สร้างข้อมูลตัวอย่าง
df = pd.DataFrame({
'product_id': range(1, 51),
'product_name': [f'Product_{i}' for i in range(1, 51)],
'category': np.random.choice(['Electronics', 'Clothing', 'Food', 'Books'], 50),
'price': np.random.uniform(10, 500, 50),
'stock': np.random.randint(0, 100, 50),
'rating': np.random.uniform(1, 5, 50)
})
print("=== รูปร่างของข้อมูล (Shape) ===")
print(f"Shape: {df.shape}")
print(f"จำนวนแถว (Rows): {df.shape[0]}")
print(f"จำนวนคอลัมน์ (Columns): {df.shape[1]}")
print("\n=== ชื่อคอลัมน์ทั้งหมด (Column Names) ===")
print(df.columns)
print(f"ประเภท: {type(df.columns)}")
print(f"คอลัมน์ทั้งหมด: {df.columns.tolist()}")
print("\n=== ข้อมูล Index ===")
print(f"Index: {df.index}")
print(f"Index name: {df.index.name}")
print(f"Index values: {df.index.tolist()[:5]}...") # แสดง 5 ตัวแรก
print("\n=== ข้อมูลเพิ่มเติม ===")
print(f"จำนวนมิติ (Dimensions): {df.ndim}")
print(f"จำนวนค่าทั้งหมด (Size): {df.size}")
print(f"ว่างเปล่าหรือไม่ (Is empty): {df.empty}")
print(f"จำนวนค่า non-null: {df.count().sum()}")
print(f"จำนวนค่า null: {df.isnull().sum().sum()}")
# สรุปโครงสร้างแบบกระชับ
print("\n=== สรุปโครงสร้าง ===")
structure_summary = {
'Total Rows': df.shape[0],
'Total Columns': df.shape[1],
'Total Values': df.size,
'Memory Usage (MB)': df.memory_usage(deep=True).sum() / 1024**2,
'Column Names': ', '.join(df.columns.tolist()),
'Numeric Columns': df.select_dtypes(include=[np.number]).shape[1],
'Object Columns': df.select_dtypes(include=['object']).shape[1]
}
for key, value in structure_summary.items():
if isinstance(value, float):
print(f"{key:20s}: {value:.4f}")
else:
print(f"{key:20s}: {value}")
return df
# ตัวอย่างการใช้งานขั้นสูง
def column_analysis():
"""
วิเคราะห์คอลัมน์แบบละเอียด
"""
df = pd.DataFrame({
'int_col': range(100),
'float_col': np.random.randn(100),
'str_col': ['text'] * 100,
'bool_col': [True, False] * 50,
'datetime_col': pd.date_range('2024-01-01', periods=100),
'category_col': pd.Categorical(['A', 'B', 'C'] * 33 + ['A'])
})
print("=== การวิเคราะห์คอลัมน์ตามประเภท ===")
# แบ่งคอลัมน์ตามประเภท
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
object_cols = df.select_dtypes(include=['object']).columns.tolist()
datetime_cols = df.select_dtypes(include=['datetime64']).columns.tolist()
bool_cols = df.select_dtypes(include=['bool']).columns.tolist()
category_cols = df.select_dtypes(include=['category']).columns.tolist()
print(f"Numeric columns ({len(numeric_cols)}): {numeric_cols}")
print(f"Object columns ({len(object_cols)}): {object_cols}")
print(f"Datetime columns ({len(datetime_cols)}): {datetime_cols}")
print(f"Boolean columns ({len(bool_cols)}): {bool_cols}")
print(f"Category columns ({len(category_cols)}): {category_cols}")
# วิเคราะห์การใช้ memory ต่อคอลัมน์
print("\n=== การใช้ Memory แต่ละคอลัมน์ ===")
memory_per_col = df.memory_usage(deep=True)
for col, mem in memory_per_col.items():
if col != 'Index':
print(f"{col:20s}: {mem/1024:8.2f} KB")
return df
def uniqueness_frequency_analysis():
"""
ฟังก์ชันสำหรับการวิเคราะห์ค่าที่ไม่ซ้ำและความถี่
เทคนิคที่ใช้:
- nunique(): จำนวนค่าที่ไม่ซ้ำ
- unique(): ค่าที่ไม่ซ้ำทั้งหมด
- value_counts(): นับความถี่แต่ละค่า
"""
# สร้างข้อมูลตัวอย่าง
df = pd.DataFrame({
'customer_id': np.random.randint(1, 100, 500),
'product': np.random.choice(['Laptop', 'Phone', 'Tablet', 'Monitor', 'Keyboard'], 500),
'region': np.random.choice(['North', 'South', 'East', 'West'], 500),
'payment_method': np.random.choice(['Credit Card', 'PayPal', 'Cash'], 500),
'amount': np.random.uniform(100, 5000, 500)
})
print("=== จำนวนค่าที่ไม่ซ้ำในแต่ละคอลัมน์ ===")
print(df.nunique())
print("\n=== ค่าที่ไม่ซ้ำใน Product column ===")
print(df['product'].unique())
print("\n=== ความถี่ของแต่ละ Product ===")
print(df['product'].value_counts())
print("\n=== ความถี่แบบเปอร์เซ็นต์ ===")
print(df['product'].value_counts(normalize=True) * 100)
print("\n=== ความถี่พร้อมเรียงลำดับตามค่า ===")
print(df['product'].value_counts(sort=False))
# สร้างตารางสรุป
print("\n=== ตารางสรุปค่าที่ไม่ซ้ำ ===")
summary = pd.DataFrame({
'Column': df.columns,
'Unique_Count': df.nunique().values,
'Most_Common': [df[col].mode()[0] if len(df[col].mode()) > 0 else None
for col in df.columns],
'Most_Common_Freq': [df[col].value_counts().iloc[0] if df[col].dtype == 'object'
else None for col in df.columns]
})
print(summary)
# ตรวจหาคอลัมน์ที่อาจเป็น Primary Key
print("\n=== คอลัมน์ที่อาจเป็น Primary Key ===")
potential_keys = df.columns[df.nunique() == len(df)]
if len(potential_keys) > 0:
print(f"Potential primary keys: {potential_keys.tolist()}")
else:
print("ไม่มีคอลัมน์ที่ค่าไม่ซ้ำกันทั้งหมด")
# ตรวจหาคอลัมน์ที่มีค่าเดียว (constant)
print("\n=== คอลัมน์ที่มีค่าเดียว (Constant) ===")
constant_cols = df.columns[df.nunique() == 1]
if len(constant_cols) > 0:
print(f"Constant columns: {constant_cols.tolist()}")
else:
print("ไม่มีคอลัมน์ที่มีค่าเดียว")
return df
# ตัวอย่างการวิเคราะห์ Categorical Data
def categorical_analysis():
"""
วิเคราะห์ข้อมูลประเภท Categorical อย่างละเอียด
"""
df = pd.DataFrame({
'department': np.random.choice(['IT', 'Sales', 'HR', 'Marketing', 'Finance'], 1000),
'position': np.random.choice(['Junior', 'Senior', 'Manager', 'Director'], 1000),
'education': np.random.choice(['Bachelor', 'Master', 'PhD'], 1000)
})
for col in df.columns:
print(f"\n{'='*50}")
print(f"Analysis of: {col}")
print(f"{'='*50}")
# จำนวนค่าที่ไม่ซ้ำ
print(f"Number of unique values: {df[col].nunique()}")
# ค่าที่พบบ่อยที่สุด
mode_value = df[col].mode()[0]
mode_count = df[col].value_counts().iloc[0]
mode_pct = (mode_count / len(df)) * 100
print(f"Most frequent: '{mode_value}' ({mode_count} times, {mode_pct:.1f}%)")
# ค่าที่พบน้อยที่สุด
least_value = df[col].value_counts().index[-1]
least_count = df[col].value_counts().iloc[-1]
least_pct = (least_count / len(df)) * 100
print(f"Least frequent: '{least_value}' ({least_count} times, {least_pct:.1f}%)")
# แสดงตารางความถี่
print("\nFrequency table:")
freq_table = pd.DataFrame({
'Count': df[col].value_counts(),
'Percentage': df[col].value_counts(normalize=True) * 100
})
print(freq_table)
return df
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#458588','primaryTextColor':'#ebdbb2','primaryBorderColor':'#83a598','lineColor':'#fabd2f','secondaryColor':'#b16286','tertiaryColor':'#689d6a','background':'#282828','mainBkg':'#3c3836','secondBkg':'#504945','textColor':'#ebdbb2','fontSize':'14px'}}}%%
graph TB
subgraph Overview["📊 ภาพรวมข้อมูล (Data Overview)"]
A["info()"] --> A1["ดูโครงสร้างและประเภทข้อมูล
(Structure & Data Types)"]
B["describe()"] --> B1["ดูสถิติเชิงพรรณนา
(Descriptive Statistics)"]
C["shape"] --> C1["ดูมิติข้อมูล
(Dimensions)"]
D["columns"] --> D1["ดูชื่อคอลัมน์
(Column Names)"]
end
subgraph Uniqueness["🔍 ความไม่ซ้ำ (Uniqueness)"]
E["nunique()"] --> E1["นับค่าที่ไม่ซ้ำ
(Count Unique)"]
F["unique()"] --> F1["ดูค่าที่ไม่ซ้ำ
(View Unique)"]
G["value_counts()"] --> G1["นับความถี่
(Frequency Count)"]
end
A1 --> H["✅ เข้าใจข้อมูลครบถ้วน"]
B1 --> H
C1 --> H
D1 --> H
E1 --> H
F1 --> H
G1 --> H
style A fill:#b16286,stroke:#d3869b,stroke-width:2px,color:#ebdbb2
style B fill:#b16286,stroke:#d3869b,stroke-width:2px,color:#ebdbb2
style C fill:#689d6a,stroke:#8ec07c,stroke-width:2px,color:#ebdbb2
style D fill:#689d6a,stroke:#8ec07c,stroke-width:2px,color:#ebdbb2
style E fill:#d79921,stroke:#fabd2f,stroke-width:2px,color:#282828
style F fill:#d79921,stroke:#fabd2f,stroke-width:2px,color:#282828
style G fill:#d79921,stroke:#fabd2f,stroke-width:2px,color:#282828
style H fill:#98971a,stroke:#b8bb26,stroke-width:3px,color:#282828
def automated_data_report(df):
"""
สร้างรายงานสรุปข้อมูลอัตโนมัติแบบครบถ้วน
Parameters:
df (DataFrame): DataFrame ที่ต้องการวิเคราะห์
Returns:
dict: รายงานสรุปในรูปแบบ dictionary
"""
report = {}
# 1. ข้อมูลพื้นฐาน
report['basic_info'] = {
'rows': df.shape[0],
'columns': df.shape[1],
'total_values': df.size,
'memory_mb': df.memory_usage(deep=True).sum() / 1024**2,
'duplicated_rows': df.duplicated().sum(),
'duplicated_pct': (df.duplicated().sum() / len(df)) * 100
}
# 2. ข้อมูล Missing Values
missing_data = df.isnull().sum()
report['missing_values'] = {
'total_missing': missing_data.sum(),
'missing_pct': (missing_data.sum() / df.size) * 100,
'columns_with_missing': missing_data[missing_data > 0].to_dict()
}
# 3. ข้อมูลประเภทคอลัมน์
report['column_types'] = {
'numeric': df.select_dtypes(include=[np.number]).columns.tolist(),
'object': df.select_dtypes(include=['object']).columns.tolist(),
'datetime': df.select_dtypes(include=['datetime64']).columns.tolist(),
'boolean': df.select_dtypes(include=['bool']).columns.tolist(),
'category': df.select_dtypes(include=['category']).columns.tolist()
}
# 4. สถิติเชิงพรรณนา (เฉพาะตัวเลข)
if len(report['column_types']['numeric']) > 0:
report['numeric_statistics'] = df[report['column_types']['numeric']].describe().to_dict()
# 5. ข้อมูล Categorical (เฉพาะ object)
if len(report['column_types']['object']) > 0:
categorical_summary = {}
for col in report['column_types']['object']:
categorical_summary[col] = {
'unique_count': df[col].nunique(),
'most_common': df[col].mode()[0] if len(df[col].mode()) > 0 else None,
'most_common_freq': df[col].value_counts().iloc[0] if len(df[col]) > 0 else 0
}
report['categorical_summary'] = categorical_summary
# 6. คำแนะนำ
recommendations = []
if report['missing_values']['missing_pct'] > 5:
recommendations.append("⚠️ ข้อมูลมี Missing Values มากกว่า 5% ควรทำความสะอาด")
if report['basic_info']['duplicated_pct'] > 1:
recommendations.append("⚠️ ข้อมูลมีแถวซ้ำ ควรตรวจสอบและลบออก")
if report['basic_info']['memory_mb'] > 100:
recommendations.append("💡 ข้อมูลใช้ memory มาก ควรพิจารณาใช้ dtype ที่เหมาะสม")
potential_keys = [col for col in df.columns if df[col].nunique() == len(df)]
if potential_keys:
recommendations.append(f"🔑 คอลัมน์ที่อาจเป็น Primary Key: {', '.join(potential_keys)}")
report['recommendations'] = recommendations
# แสดงรายงาน
print("="*70)
print("📊 DATA INSPECTION REPORT")
print("="*70)
print("\n1️⃣ BASIC INFORMATION")
print(f" Rows: {report['basic_info']['rows']:,}")
print(f" Columns: {report['basic_info']['columns']:,}")
print(f" Total Values: {report['basic_info']['total_values']:,}")
print(f" Memory Usage: {report['basic_info']['memory_mb']:.2f} MB")
print(f" Duplicated Rows: {report['basic_info']['duplicated_rows']:,} ({report['basic_info']['duplicated_pct']:.2f}%)")
print("\n2️⃣ MISSING VALUES")
print(f" Total Missing: {report['missing_values']['total_missing']:,} ({report['missing_values']['missing_pct']:.2f}%)")
if report['missing_values']['columns_with_missing']:
print(" Columns with missing:")
for col, count in report['missing_values']['columns_with_missing'].items():
pct = (count / len(df)) * 100
print(f" - {col}: {count:,} ({pct:.2f}%)")
print("\n3️⃣ COLUMN TYPES")
for dtype, cols in report['column_types'].items():
if cols:
print(f" {dtype.capitalize()} ({len(cols)}): {', '.join(cols)}")
print("\n4️⃣ RECOMMENDATIONS")
if recommendations:
for rec in recommendations:
print(f" {rec}")
else:
print(" ✅ ข้อมูลดูดี ไม่มีปัญหาที่ต้องแก้ไขเร่งด่วน")
print("\n" + "="*70)
return report
# ตัวอย่างการใช้งาน
def example_usage():
"""
ตัวอย่างการใช้งานฟังก์ชันรายงานอัตโนมัติ
"""
# สร้างข้อมูลตัวอย่างที่มีปัญหา
df = pd.DataFrame({
'id': list(range(1, 101)) + [50], # มีข้อมูลซ้ำ
'name': [f'Person_{i}' for i in range(1, 101)] + ['Person_50'],
'age': [np.random.randint(18, 65) if i % 10 != 0 else None for i in range(101)],
'salary': np.random.uniform(30000, 100000, 101),
'department': np.random.choice(['IT', 'Sales', 'HR', None], 101),
'join_date': pd.date_range('2020-01-01', periods=101)
})
# สร้างรายงาน
report = automated_data_report(df)
return report
def data_quality_dashboard(df):
"""
สร้าง dashboard แสดงคุณภาพข้อมูล
แสดงผลใน ASCII art สำหรับการนำเสนอเบื้องต้น
"""
print("╔" + "═"*68 + "╗")
print("║" + " "*20 + "DATA QUALITY DASHBOARD" + " "*25 + "║")
print("╠" + "═"*68 + "╣")
# Completeness Score
completeness = (1 - df.isnull().sum().sum() / df.size) * 100
print(f"║ 📊 COMPLETENESS SCORE: {completeness:5.1f}% " + "█" * int(completeness/2) + " "*50 + "║"[:70])
# Uniqueness Score
uniqueness = (df.nunique().sum() / df.size) * 100
print(f"║ 🔑 UNIQUENESS SCORE: {uniqueness:5.1f}% " + "█" * int(uniqueness/2) + " "*50 + "║"[:70])
# Consistency Score (no duplicates)
consistency = (1 - df.duplicated().sum() / len(df)) * 100
print(f"║ ✓ CONSISTENCY SCORE: {consistency:5.1f}% " + "█" * int(consistency/2) + " "*50 + "║"[:70])
print("╠" + "═"*68 + "╣")
# Column Quality
print("║ COLUMN QUALITY SUMMARY:" + " "*44 + "║")
print("╠" + "═"*68 + "╣")
for col in df.columns[:5]: # แสดงแค่ 5 คอลัมน์แรก
missing_pct = (df[col].isnull().sum() / len(df)) * 100
quality = 100 - missing_pct
quality_bar = "█" * int(quality/10)
quality_indicator = "✓" if quality >= 95 else "⚠" if quality >= 80 else "✗"
col_display = col[:20].ljust(20)
print(f"║ {quality_indicator} {col_display}: {quality:5.1f}% [{quality_bar:<10}]" + " "*20 + "║"[:70])
print("╚" + "═"*68 + "╝")
# ตัวอย่างการใช้งาน
if __name__ == "__main__":
# สร้างข้อมูลตัวอย่าง
sample_df = pd.DataFrame({
'customer_id': range(1, 201),
'name': [f'Customer_{i}' if i % 15 != 0 else None for i in range(1, 201)],
'email': [f'user{i}@example.com' if i % 20 != 0 else None for i in range(1, 201)],
'age': [np.random.randint(18, 70) if i % 10 != 0 else None for i in range(1, 201)],
'purchase_amount': np.random.uniform(100, 10000, 200)
})
data_quality_dashboard(sample_df)
การนำเข้าและสำรวจข้อมูลเป็นขั้นตอนแรกและสำคัญที่สุด ในกระบวนการวิเคราะห์ข้อมูลด้วย Pandas โดยในบทนี้เราได้เรียนรู้:
การนำเข้าข้อมูล (Data Loading)
read_csv() สำหรับไฟล์ CSV ซึ่งเป็นรูปแบบที่นิยมมากที่สุดread_excel() สำหรับไฟล์ Excel โดยสามารถอ่านหลาย sheets ได้read_json() สำหรับข้อมูลจาก Web APIsการสำรวจเบื้องต้น (Initial Inspection)
head() และ tail() เพื่อดูข้อมูลตัวอย่างเบื้องต้นsample() เพื่อสุ่มดูข้อมูลแบบสุ่มและตรวจสอบความหลากหลายการวิเคราะห์ภาพรวม (Overview Analysis)
info() เพื่อดูโครงสร้าง ประเภทข้อมูล และ missing valuesdescribe() เพื่อดูสถิติเชิงพรรณนาของข้อมูลตัวเลขshape, columns, dtypes เพื่อเข้าใจมิติและโครงสร้างnunique(), unique(), value_counts() เพื่อวิเคราะห์ความไม่ซ้ำและความถี่info() และ head() เพื่อยืนยันว่าข้อมูลถูกต้องsample() แทน head() เมื่อต้องการเห็นข้อมูลที่หลากหลายdtype ตั้งแต่ตอนอ่านข้อมูล เพื่อประหยัด memory และป้องกันข้อผิดพลาด⚠️ Missing Values - ต้องตรวจสอบและจัดการก่อนเริ่มวิเคราะห์
⚠️ Data Types - ตรวจสอบว่าแต่ละคอลัมน์มี dtype ที่ถูกต้อง
⚠️ Duplicates - อาจทำให้ผลวิเคราะห์ผิดเพี้ยน
⚠️ Memory Usage - ไฟล์ขนาดใหญ่ต้องใช้เทคนิคพิเศษ เช่น chunking หรือ sampling
⚠️ Encoding - ระบุ encoding ที่ถูกต้องสำหรับภาษาไทย (utf-8-sig หรือ cp874)
หลังจากสำรวจข้อมูลเบื้องต้นแล้ว ขั้นตอนต่อไปคือ:
Pandas Official Documentation
Books
Online Resources
Best Practices
หมายเหตุ: เอกสารนี้สร้างขึ้นเพื่อการศึกษาและเป็นแนวทางในการใช้งาน Pandas Library สำหรับการนำเข้าและสำรวจข้อมูล ผู้อ่านสามารถนำไปปรับใช้กับโปรเจกต์จริงได้ โดยควรปรับแต่งให้เหมาะสมกับบริบทและความต้องการเฉพาะของแต่ละโปรเจกต์