<think>嗯,用户想处理泰坦尼克数据集,进行特征工程和预处理,用到的库包括pandas、sklearn和pgmpy。首先,我需要回忆一下泰坦尼克数据集的常见处理步骤。通常,数据预处理包括处理缺失值、特征编码、特征提取和特征选择等。
首先,数据加载肯定是第一步,用pandas读取CSV文件。然后检查缺失值,比如Age、Cabin、Embarked这些字段通常会有缺失。Age可以用中位数或均值填充,Cabin可能因为缺失太多而直接删除或者用某种标志代替,Embarked可以用众数填充。
接下来是特征工程部分。比如,从姓名中提取称呼,像Mr、Mrs、Miss这些,可能作为新的特征。然后,家庭人数可能由SibSp和Parch相加得到,再进一步创建是否独自一人的特征。年龄分箱也是一个常见步骤,把连续年龄分成几个区间。票价可能做对数变换,使其分布更平滑。
然后,分类变量需要进行编码,比如Sex和Embarked可以用OneHot编码,而称呼可能需要标签编码,因为可能有顺序关系。Cabin的特征可能需要简化,比如只取首字母或者是否缺失。
特征选择方面,可能需要删除不相关的列,比如PassengerId、Name、Ticket这些。然后使用方差阈值或卡方检验来选择重要特征。
最后,数据标准化或归一化,特别是对数值型特征如Age和Fare,可以用StandardScaler处理。
用户提到的pgmpy库可能用于概率图模型,可能在特征关系分析或者建立贝叶斯网络时用到。不过常规预处理可能不需要这个库,除非有特定需求。需要确认用户是否需要在预处理阶段使用pgmpy,或者是在后续建模中使用。
在代码实现时,可能需要分步骤展示,每个处理阶段对应的代码块。比如填充缺失值、创建新特征、编码分类变量、特征选择和标准化等。同时,要提醒用户注意数据泄漏问题,比如在训练集上拟合的scaler要应用到测试集,而不是重新拟合。
可能用户对某些步骤不熟悉,比如如何使用pgmpy进行特征分析,这时候可能需要补充相关代码示例,或者建议参考相关文档。另外,需要检查是否有版本兼容性问题,比如不同库的版本是否支持某些函数。
总结步骤应该是:加载数据→处理缺失值→特征提取→编码→特征选择→标准化。每个步骤用pandas和sklearn的函数实现。pgmpy可能用在后续分析中,比如构建网络结构,但预处理阶段可能用不上,除非用户有特殊需求。</think>### 泰坦尼克数据集特征工程与预处理实现
#### 1. 数据加载与基础分析
```python
import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# 加载数据
train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')
# 合并数据集便于统一处理
full_df = pd.concat([train_df, test_df], ignore_index=True)
```
#### 2. 缺失值处理
```python
# 年龄用中位数填充
full_df['Age'].fillna(full_df['Age'].median(), inplace=True)
# 船票费用用同舱位中位数填充
full_df['Fare'] = full_df.groupby('Pclass')['Fare'].transform(lambda x: x.fillna(x.median()))
# 登船港口用众数填充
full_df['Embarked'].fillna(full_df['Embarked'].mode()[0], inplace=True)
# 删除高缺失率特征
full_df.drop(['Cabin'], axis=1, inplace=True)
```
#### 3. 特征工程
```python
# 提取姓名中的称呼
full_df['Title'] = full_df['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)
# 合并罕见称呼
title_replacements = {
'Mlle': 'Miss', 'Ms': 'Miss', 'Mme': 'Mrs',
'Col': 'Rare', 'Major': 'Rare', 'Dr': 'Rare',
'Rev': 'Rare', 'Lady': 'Rare', 'Countess': 'Rare',
'Jonkheer': 'Rare', 'Sir': 'Rare', 'Don': 'Rare',
'Dona': 'Rare', 'Capt': 'Rare'
}
full_df['Title'] = full_df['Title'].replace(title_replacements)
# 创建家庭人数特征
full_df['FamilySize'] = full_df['SibSp'] + full_df['Parch'] + 1
full_df['IsAlone'] = (full_df['FamilySize'] == 1).astype(int)
# 年龄分箱
full_df['AgeBin'] = pd.cut(full_df['Age'], bins=[0,12,20,40,120], labels=['Child','Teen','Adult','Elder'])
# 票价对数变换
full_df['FareLog'] = np.log1p(full_df['Fare'])
```
#### 4. 特征编码
```python
# 定义预处理管道
numeric_features = ['Age', 'FareLog']
categorical_features = ['Sex', 'Embarked', 'Title', 'Pclass']
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numeric_features),
('cat', OneHotEncoder(drop='first'), categorical_features)
])
# 应用预处理
X_processed = preprocessor.fit_transform(full_df)
```
#### 5. 特征选择(使用pgmpy)
```python
from pgmpy.estimators import HillClimbSearch, BicScore
# 创建特征关系网络
hc = HillClimbSearch(full_df[['Survived', 'Sex', 'AgeBin', 'Pclass', 'FareLog']])
best_model = hc.estimate(scoring_method=BicScore(full_df))
print(best_model.edges())
```
[^1]: 特征分箱方法参考《特征工程实战》第5章
[^2]: 对数变换处理偏态分布见《Python数据科学手册》第3.5节
[^3]: pgmpy的贝叶斯网络应用参考官方文档示例