from sklearn.datasets import fetch_openml
boston = fetch_openml(name='boston', version=1, as_frame=True)
df = boston.frame
我們常用 Pandas DataFrame 來處理結構化的資料。
載入 CSV 檔案: 使用 pd.read_csv()
。
載入 scikit-learn 內建資料集: scikit-learn 提供了一些範例資料集 (如波士頓房價資料集),這些資料集載入後通常是 dictionary 格式。
.keys()
查看包含哪些內容 (如 data, target, feature_names, description)。
# 載入必要的套件
import pandas as pd
from sklearn.datasets import fetch_openml
boston = fetch_openml(name='boston', version=1, as_frame=True)
df = boston.frame
df['target'] = boston.target # 加入目標變數
df.head()
/ df.tail()
(預設顯示前/後 5 筆,可指定數字)。df.shape
(回傳 (列數, 欄位數))。df.info()
。df.describe()
。df['欄位名稱'].value_counts()
.如何偵測遺失值?
df.info()
可以快速查看每個欄位非空值的數量,從而推算遺失值.df.isnull()
或 df.isna()
:回傳一個與 DataFrame 形狀相同的 boolean DataFrame,True 表示該位置是遺失值 (NaN),False 表示非遺失值..sum()
:df.isnull().sum()
可以快速計算每個欄位的遺失值數量..any()
:df.isnull().any()
可以快速判斷哪些欄位包含遺失值.
# 假設使用 NullPractive.csv 資料集,因為波士頓房價資料集沒有遺失值
weather_df = pd.read_csv('NullPractive.csv')
# 偵測每個欄位的遺失值數量
print(weather_df.isnull().sum())
# 判斷哪些欄位有遺失值
print(weather_df.isnull().any())
df.dropna()
:刪除任何包含一個或多個遺失值的列 (預設 axis=0
).df.dropna(axis=1)
:刪除任何包含一個或多個遺失值的欄.df.dropna(thresh=N)
:刪除遺失值數量超過 N 的列.任務: 創建一個新的 DataFrame,其中包含幾列和幾行,並手動將一些值設為 np.nan
。然後嘗試使用 df.dropna()
刪除包含遺失值的列。觀察刪除前後 DataFrame 的形狀 (.shape
) 變化。
# 創建範例Dataframe
data = {'col1': [1, 2, np.nan, 4], 'col2': [5, np.nan, np.nan, 8], 'col3':}
test_df = pd.DataFrame(data)
# 觀察原始Dataframe
print("原始 DataFrame:\n", test_df)
print("原始形狀:", test_df.shape)
# 處理缺失值後再次觀察
test_df_dropped = test_df.dropna() # 刪除包含 NaN 的列
print("\n刪除遺失值後的 DataFrame:\n", test_df_dropped)
print("刪除遺失值後的形狀:", test_df_dropped.shape)
df.fillna(value)
:用指定的值填補 (如 df.fillna(0)
用 0 填補).df.fillna(df.mean())
:用該欄位的平均值填補.df.fillna(df.median())
:用該欄位的中位數填補.df.fillna(df.mode())
:用該欄位的眾數填補.method='ffill'
) 或向後填補 (method='bfill'
).import pandas as pd
import numpy as np
# 建立模擬資料
data = {
'CRIM': [0.1, np.nan, 0.3, 0.2],
'RM': [6.5, 7.1, np.nan, 5.9],
'AGE': [65, 72, np.nan, 65]
}
df = pd.DataFrame(data)
print("原始資料:")
print(df)
# 平均值填補 CRIM 欄位
df['CRIM'] = df['CRIM'].fillna(df['CRIM'].mean())
# 中位數填補 RM 欄位
df['RM'] = df['RM'].fillna(df['RM'].median())
# 眾數填補 AGE 欄位
df['AGE'] = df['AGE'].fillna(df['AGE'].mode()[0])
print("\n填補後的資料:")
print(df)
**課堂示範: 處理異常值(接續波士頓房價資料集) **
# 使用 IQR 方法偵測異常值 (以波士頓房價資料集的 'CRIM' 欄位為例)
# 首先使用 describe() 獲取四分位數
desc = df['CRIM'].describe()
Q1 = desc['25%']
Q3 = desc['75%']
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 找出異常值
outliers = df[(df['CRIM'] < lower_bound) | (df['CRIM'] > upper_bound)]
print("CRIM 欄位的異常值數量:", len(outliers))
# 任務 1 & 2
selected_column = 'TAX' # 或其他欄位
col_desc = df[selected_column].describe() #
Q1 = col_desc['25%']
Q3 = col_desc['75%']
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
print(f"{selected_column} 欄位的 IQR 上限: {upper_bound}, 下限: {lower_bound}")
# 任務 3
outliers = df[(df[selected_column] < lower_bound) | (df[selected_column] > upper_bound)] #
print(f"{selected_column} 欄位的異常值數量: {len(outliers)}")
print("部分異常值資料點:\n", outliers.head())
DataFrame.duplicated()
:回傳一個 Series,標示每一列是否為重複(基於所有欄位)。第一次出現的標示為 False,後續重複的標示為 True.subset
參數,只檢查特定欄位是否重複.DataFrame.drop_duplicates()
:移除重複的列.keep='first'
),可以設定 keep='last'
保留最後一次出現的,或 keep=False
刪除所有重複的列.subset
參數,只根據特定欄位來判斷是否重複.
# 建立含重複資料的範例
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Bob', 'Alice', 'Eve'],
'Score': [90, 85, 78, 85, 90, 95]
}
df = pd.DataFrame(data)
print("原始資料:")
print(df)
# 偵測重複資料
print("重複資料筆數:", df.duplicated().sum())
print("重複資料:")
print(df[df.duplicated()])
# 移除重複資料(保留第一次出現)
df_cleaned = df.drop_duplicates()
print("移除重複後的資料:")
print(df_cleaned)
StandardScaler
實現.MinMaxScaler
實現.
# 使用 Scikit-learn 進行標準化範例 (以波士頓房價資料集的 'DIS' 欄位為例)
# 注意:標準化通常是對特徵 (X) 進行,不對目標變數 (Y) 進行
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 變異數標準化 (Z-score)
scaler_z = StandardScaler()
df['DIS_z'] = scaler_z.fit_transform(df[['DIS']]) # fit_transform 會 fit 然後 transform
# 最小-最大標準化 (Min-Max)
scaler_mm = MinMaxScaler()
df['DIS_mm'] = scaler_mm.fit_transform(df[['DIS']]) # fit_transform 會 fit 然後 transform
print(df[['DIS', 'DIS_z', 'DIS_mm']].head())
print(df[['DIS_z', 'DIS_mm']].describe()) # 查看標準化後的統計量
StandardScaler
) 和最小-最大標準化 (MinMaxScaler
)。.describe()
結果有何不同。pd.get_dummies()
對 'City' 欄位進行 One-hot Encoding。
# 任務 1 & 2
from sklearn.preprocessing import StandardScaler, MinMaxScaler #
selected_column = 'LSTAT'
scaler_z = StandardScaler()
df[f'{selected_column}_z'] = scaler_z.fit_transform(df[[selected_column]])
scaler_mm = MinMaxScaler()
df[f'{selected_column}_mm'] = scaler_mm.fit_transform(df[[selected_column]])
print(f"{selected_column} 欄位標準化後的敘述性統計:\n")
print("Z-score:\n", df[f'{selected_column}_z'].describe())
print("\nMin-Max:\n", df[f'{selected_column}_mm'].describe())
# 任務 3
data_city = {'City': ['Taipei', 'Taichung', 'Kaohsiung', 'Taipei', 'Kaohsiung']}
df_city = pd.DataFrame(data_city)
df_city_encoded = pd.get_dummies(df_city['City']) #
print("\nOne-hot Encoding 結果:\n", df_city_encoded)
.map()
方法或替換功能實現.pd.get_dummies()
函數或 Scikit-learn 的 OneHotEncoder
實現.
# 順序尺度編碼範例 (假設有一個 'size' 欄位: S, M, L)
data_size = {'size': ['S', 'M', 'L', 'S', 'M', 'L']}
df_size = pd.DataFrame(data_size)
size_mapping = {'S': 1, 'M': 2, 'L': 3}
df_size['size_encoded'] = df_size['size'].map(size_mapping)
print(df_size)
# 名目尺度 One-hot Encoding 範例 (假設有一個 'color' 欄位: Red, Blue, Green)
data_color = {'color': ['Red', 'Blue', 'Green', 'Red', 'Green']}
df_color = pd.DataFrame(data_color)
df_color_encoded = pd.get_dummies(df_color['color'])
print(df_color_encoded)
# 將 One-hot Encoding 結果與原 DataFrame 合併
df_combined = pd.concat([df_color, df_color_encoded], axis=1)
print(df_combined)
使用相關係數進行特徵選取範例 (波士頓房價資料集):
df.corr()
:計算 DataFrame 中所有數值欄位之間的皮爾森相關係數矩陣.
# 計算相關係數矩陣並查看與目標變數的相關性
correlation_matrix = df.corr()
print("特徵與目標變數的相關係數:\n", correlation_matrix['target'].sort_values(ascending=False))
# 可以考慮移除與目標變數相關性低的特徵,或特徵之間相關性高的特徵 (擇一保留)
train_test_split
函數.stratify
參數確保訓練集和測試集中的類別分佈與原始資料相似.
# 切割資料集範例 (波士頓房價資料集)
from sklearn.model_selection import train_test_split
# 將特徵 (X) 和目標變數 (Y) 分開
# 在進行資料前處理時,通常只對特徵 (X) 進行處理,目標變數 (Y) 不處理標準化等
X = df.drop('target', axis=1) # 移除 target 欄位作為特徵
Y = df['target'] # target 欄位作為目標變數
將資料分割為訓練集和測試集,測試集佔 33%
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.33, random_state=42) # random_state 確保每次分割結果相同
# 學生自行練習: 查看分割後的資料形狀
print("原始資料形狀:", df.shape)
print("訓練集特徵形狀:", X_train.shape)
print("測試集特徵形狀:", X_test.shape)
print("訓練集目標形狀:", Y_train.shape)
print("測試集目標形狀:", Y_test.shape)