Pandas-特征工程詳解
- 一、特征工程的核心目標
- 二、數據類型與基礎轉換
- 1. 數值型特征:類型優化與異常處理
- 2. 分類型特征:編碼與規范化
- (1)標簽編碼(Label Encoding)
- (2)獨熱編碼(One-Hot Encoding)
- 3. 時間型特征:提取時間信息
- 三、特征創建:從原始數據中挖掘新特征
- 1. 數值型特征組合
- 2. 分組統計特征
- 3. 文本特征提取
- 四、特征轉換:優化特征分布
- 1. 標準化與歸一化
- 2. 對數與冪轉換
- 3. 交互特征
- 五、特征選擇:保留關鍵信息
- 1. 相關性分析
- 2. 方差過濾
- 3. 基于樹模型的特征重要性
- 六、實戰案例:完整特征工程流程
特征工程其質量直接決定模型性能,優質的特征能讓簡單模型達到復雜模型的效果,而劣質特征則可能導致模型失效,Pandas提供了豐富的函數用于特征提取、轉換和選擇。本文我將系統講解如何利用Pandas進行特征工程,從數據類型轉換到高級特征創建,覆蓋特征工程的全流程關鍵技術。
一、特征工程的核心目標
特征工程的本質是將原始數據轉化為模型可理解的特征,核心目標包括:
- 信息保留:最大限度保留原始數據中的有用信息
- 噪聲去除:減少冗余和干擾信息
- 分布優化:調整特征分布以適應模型假設(如線性模型偏好正態分布)
- 維度控制:在信息損失最小化的前提下降低特征維度
Pandas在特征工程中的核心作用是高效處理結構化數據,支持數值型、分類型、時間型等多種數據的特征轉化。
二、數據類型與基礎轉換
原始數據的類型往往不符合建模要求,需先進行基礎轉換,為后續特征工程鋪路。
1. 數值型特征:類型優化與異常處理
數值型特征(int/float)是模型最易處理的類型,但需確保數據范圍合理:
import pandas as pd
import numpy as np# 示例數據
data = pd.DataFrame({'age': [25, 30, 35, 150, -5], # 包含異常值'income': ['5000', '8000', '12000', '7500', 'NaN'], # 字符串型數值'score': [85.5, 92.0, 78.3, 90.1, 88.7]
})# 1. 將字符串型數值轉換為float
data['income'] = pd.to_numeric(data['income'], errors='coerce') # 'NaN'轉為NaN# 2. 處理異常值(年齡不可能超過120或為負)
data['age'] = data['age'].clip(lower=0, upper=120) # 截斷異常值# 3. 類型優化(減少內存占用)
data['age'] = data['age'].astype('int8') # 年齡范圍小,用int8足夠
2. 分類型特征:編碼與規范化
分類型特征(object/category)需轉換為數值形式才能輸入模型,常見方法包括:
(1)標簽編碼(Label Encoding)
適用于有序分類特征(如學歷:小學<初中<高中):
# 定義有序類別
education_order = ['小學', '初中', '高中', '本科', '碩士', '博士']
data['education'] = pd.Categorical(data['education'], categories=education_order, ordered=True
)
# 轉換為數值(0到n-1)
data['education_code'] = data['education'].cat.codes
(2)獨熱編碼(One-Hot Encoding)
適用于無序分類特征(如顏色、城市):
# 對城市進行獨熱編碼
city_dummies = pd.get_dummies(data['city'], prefix='city', drop_first=True)
# 合并到原數據
data = pd.concat([data, city_dummies], axis=1)
prefix
:為新列名添加前綴(如city_北京
)drop_first=True
:刪除第一列以避免多重共線性
3. 時間型特征:提取時間信息
時間特征(datetime)蘊含豐富的模式(如季節性、周期性),需提取關鍵信息:
# 轉換為datetime類型
data['order_time'] = pd.to_datetime(data['order_time'])# 提取時間組件
data['hour'] = data['order_time'].dt.hour # 小時(0-23)
data['dayofweek'] = data['order_time'].dt.dayofweek # 星期幾(0=周一)
data['is_weekend'] = data['dayofweek'].isin([5, 6]).astype(int) # 是否周末
data['month'] = data['order_time'].dt.month # 月份(1-12)
data['is_holiday'] = data['order_time'].dt.date.isin(holiday_list).astype(int) # 是否節假日
三、特征創建:從原始數據中挖掘新特征
基于業務邏輯創建新特征,是提升模型性能的關鍵。Pandas的apply()
和transform()
函數是特征創建的利器。
1. 數值型特征組合
通過算術運算生成新特征(如比率、總和):
# 示例:電商數據
data['total_price'] = data['quantity'] * data['unit_price'] # 總價=數量×單價
data['price_per_weight'] = data['total_price'] / data['weight'] # 單位重量價格
data['discount_rate'] = data['actual_price'] / data['original_price'] # 折扣率
2. 分組統計特征
通過分組聚合創建統計特征(如用戶平均消費):
# 按用戶ID分組,計算每個用戶的消費統計量
user_stats = data.groupby('user_id')['total_price'].agg(['mean', 'sum', 'max', 'count']
).rename(columns={'mean': 'user_avg_spend','sum': 'user_total_spend','max': 'user_max_spend','count': 'user_purchase_count'
})
# 合并回原數據(每個用戶的統計量廣播到其所有訂單)
data = data.merge(user_stats, on='user_id', how='left')
3. 文本特征提取
對文本字段(如商品描述)提取關鍵詞或長度特征:
# 商品標題長度
data['title_length'] = data['product_title'].str.len()# 標題是否包含特定關鍵詞(如"促銷")
data['has_promotion'] = data['product_title'].str.contains('促銷', na=False).astype(int)# 分割并提取類別(如"男裝-T恤"→提取"T恤")
data['sub_category'] = data['category'].str.split('-', expand=True)[1]
四、特征轉換:優化特征分布
原始特征的分布可能不符合模型要求(如偏態分布),需通過轉換使其更接近理想分布。
1. 標準化與歸一化
-
標準化(Standardization):將特征轉換為均值0、標準差1,適用于正態分布特征:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() data['amount_standardized'] = scaler.fit_transform(data[['amount']])
-
歸一化(Normalization):將特征縮放到[0,1]區間,適用于均勻分布特征:
data['amount_normalized'] = (data['amount'] - data['amount'].min()) / (data['amount'].max() - data['amount'].min() )
2. 對數與冪轉換
適用于右偏分布特征(如收入、消費金額):
# 對數轉換(處理右偏分布)
data['income_log'] = np.log1p(data['income']) # log1p = log(1+x),避免x=0時出錯# 平方根轉換(輕度偏態)
data['price_sqrt'] = np.sqrt(data['price'])
3. 交互特征
通過特征間的乘法/加法創建交互項,捕捉變量間的協同效應:
# 價格×數量=總價(已在特征創建中體現)
# 年齡×消費金額:捕捉不同年齡的消費能力差異
data['age_spend_interaction'] = data['age'] * data['total_price']
五、特征選擇:保留關鍵信息
過多的特征會導致維度災難,需篩選出與目標變量相關性高的特征。
1. 相關性分析
通過皮爾遜相關系數篩選數值特征:
# 計算特征與目標變量的相關性
corr = data.corr()['target'].abs().sort_values(ascending=False)
# 選擇相關性Top20的特征
top_features = corr[1:21].index # 排除目標變量自身
data_selected = data[top_features]
2. 方差過濾
刪除方差接近0的特征(幾乎無變化,無預測價值):
from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold(threshold=0.01) # 方差低于0.01的特征將被刪除
data_high_variance = selector.fit_transform(data)
3. 基于樹模型的特征重要性
利用隨機森林等模型評估特征重要性:
from sklearn.ensemble import RandomForestClassifier
# 假設X是特征,y是目標變量
rf = RandomForestClassifier()
rf.fit(X, y)
# 提取特征重要性
importance = pd.Series(rf.feature_importances_, index=X.columns)
# 選擇重要性Top10的特征
top10_features = importance.sort_values(ascending=False).head(10).index
X_selected = X[top10_features]
六、實戰案例:完整特征工程流程
def build_features(raw_data):"""特征工程流水線函數"""data = raw_data.copy()# 1. 數據類型轉換data['order_date'] = pd.to_datetime(data['order_date'])data['price'] = pd.to_numeric(data['price'], errors='coerce')# 2. 異常值處理data['price'] = data['price'].clip(lower=0)# 3. 時間特征data['order_hour'] = data['order_date'].dt.hourdata['is_weekend'] = data['order_date'].dt.dayofweek.isin([5,6]).astype(int)# 4. 分類型特征編碼data = pd.get_dummies(data, columns=['category'], drop_first=True)# 5. 分組統計特征user_stats = data.groupby('user_id')['price'].agg(['mean', 'sum']).rename(columns={'mean': 'user_avg_price', 'sum': 'user_total_spend'})data = data.merge(user_stats, on='user_id', how='left')# 6. 特征轉換data['price_log'] = np.log1p(data['price'])# 7. 特征選擇(刪除低方差和冗余特征)data = data.drop(columns=['order_id', 'user_id', 'order_date']) # 非特征列return data# 加載原始數據并執行特征工程
raw_data = pd.read_csv('raw_orders.csv')
features = build_features(raw_data)
總結:特征工程的核心原則
好的特征往往比復雜模型更重要
- 業務驅動:特征創建需基于對業務的理解(如電商的復購率、金融的還款能力)。
- 迭代優化:先構建基礎特征,結合模型反饋逐步添加復雜特征。
- 避免信息泄露:特征工程需在訓練集上擬合,再應用到驗證集/測試集(如分組統計不能用測試集數據)。
- 平衡復雜度:并非特征越多越好,過多特征會導致過擬合和計算成本上升。
That’s all, thanks for reading~~
覺得有用就點個贊
、收進收藏
夾吧!關注
我,獲取更多干貨~