Day18 推断聚类后簇的类型

@浙大疏锦行

聚类后的分析:推断簇的类型
知识点回顾:
  1. 推断簇含义的2个思路:先选特征和后选特征
  2. 通过可视化图形借助ai定义簇的含义
  3. 科研逻辑闭环:通过精度判断特征工程价值

作业:参考示例代码对心脏病数据集采取类似操作,并且评估特征工程后模型效果有无提升。

如何通过聚类构造有价值的特征工程:

现在需要给这个簇赋予实际的含义,一般当你赋予实际含义的时候,你需要根据某几个特征来赋予,但是源数据特征很多,如何选择特征呢?有2种思路:

        1. 你最开始聚类的时候,就选择了你想最后用来确定簇含义的特征,那么你需要选择一些特征来进行聚类,那么你最后确定簇含义的特征就是这几个特征,而非全部。如你想聚类消费者购买习惯,那么他过去的消费记录、购买记录、购买金额等等,这些特征都与消费者购买习惯有关,你可以使用这些特征来确定簇含义,一些其他的特征,如消费者年龄,工作行业则不考虑。----适用于你本身就有构造某些明确含义的特征的情况。

        2. 最开始用全部特征来聚类,把其余特征作为 x,聚类得到的簇类别作为标签构建监督模型,进而根据重要性筛选特征,来确定要根据哪些特征赋予含义。---使用于你想构造什么,目前还不清楚。

昨天进行的心脏病的聚类两种思路都可以,但是因为昨天是全部特征来聚类的,所以今天先尝试第二种思路。

print(X.columns)

Index(['age', 'trestbps', 'chol', 'thalach', 'oldpeak', 'sex_1', 'cp_1',
       'cp_2', 'cp_3', 'fbs_1', 'restecg_1', 'restecg_2', 'exang_1', 'slope_1',   
       'slope_2', 'ca_1', 'ca_2', 'ca_3', 'ca_4', 'thal_1', 'thal_2', 'thal_3',   
       'thalach_age_ratio', 'bp_chol_risk', 'st_depression_ratio',
       'KMeans_Cluster'],
      dtype='object')
x1= X.drop('KMeans_Cluster',axis=1) # 删除聚类标签列
y1 = X['KMeans_Cluster']
# 构建随机森林,用shap重要性来筛选重要性
import shap
from sklearn.ensemble import RandomForestClassifier  # 随机森林分类器
model = RandomForestClassifier(n_estimators=100, random_state=42)  # 随机森林模型
model.fit(x1, y1)  # 训练模型,此时无需在意准确率 直接全部数据用来训练了
shap.initjs()
# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(x1) # 这个计算耗时
print(shap_values.shape) # 第一维是样本数,第二维是特征数,第三维是类别数

在运行上述代码时会发生报错,因为在使用随机森林分类器时,通过 explainer.shap_values(x1) 获取的 shap_values 是一个 列表 (而非数组),每个元素对应一个类别的 SHAP 值数组。由于列表没有 shape 属性,直接调用 shap_values.shape 导致报错 'list' object has no attribute 'shape' 。

关键知识点补充 :
   SHAP 值的返回格式 :
   - 对于 分类模型 (如 RandomForestClassifier), shap_values 是 列表 ,长度等于类别数,每个元素是形状为 (样本数, 特征数) 的数组。
   - 对于 回归模型 (如 RandomForestRegressor), shap_values 直接是 二维数组 ,形状为 (样本数, 特征数) ,可直接访问 shape 。
   正确访问分类模型的 SHAP 值形状 :
   - 访问特定类别: shap_values[0].shape (查看第一个类别的形状)。
   - 转换为三维数组: np.array(shap_values).shape (输出 (类别数, 样本数, 特征数) )。
   应用场景 :
   随机森林 + SHAP 常用于 特征重要性分析 ,通过 SHAP 值可直观理解每个特征对不同类别预测的影响方向和程度。
   扩展提示 :
   使用 explainer(x1) 可返回 Explanation 对象,其 values 属性在分类任务中也是列表,但提供了更多可视化功能(如 shap.summary_plot() )。


x1= X.drop('KMeans_Cluster',axis=1) # 删除聚类标签列
y1 = X['KMeans_Cluster']
# 构建随机森林,用shap重要性来筛选重要性
import shap
from sklearn.ensemble import RandomForestClassifier  # 随机森林分类器
model = RandomForestClassifier(n_estimators=100, random_state=42)  # 随机森林模型
model.fit(x1, y1)  # 训练模型,此时无需在意准确率 直接全部数据用来训练了
shap.initjs()
# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(x1) # 这个计算耗时
# 转换为三维数组并查看形状
shap_values_array = np.array(shap_values)
print(shap_values_array.shape)  # 输出 (类别数, 样本数, 特征数)

修改代码运行结果如下,需要注意的是,输出的第一类是类别数,第二类是样本数,第三类是特征数

(3, 303, 25)
# --- 1. SHAP 特征重要性条形图 (Summary Plot - Bar) --- 
print("--- 1. SHAP 特征重要性条形图 ---") 
# 设置图表大小,增加宽度以显示完整特征名称
plt.figure(figsize=(12, 8))
# 使用转换后的三维数组并选择第一个类别
shap.summary_plot(shap_values_array[0], x1, plot_type="bar", show=False)  
plt.title("SHAP Feature Importance (Bar Plot)") 
# 旋转x轴标签以避免重叠
plt.xticks(rotation=45, ha='right')
# 调整布局,确保所有元素都能正确显示
plt.tight_layout()
plt.show()

通过shap条形图来观察特征的重要性,选择前五个特征进行判断离散和连续,考虑后续的特征工程

# --- 判断前5个重要特征的类型 --- 
print("\n--- 判断前5个重要特征的类型 --- ")

# 假设前5个重要特征名称(根据SHAP条形图)
# 注意:请根据您实际的SHAP条形图结果修改这些特征名称
selected_features = ['slope_2', 'thalach', 'slope_1', 'oldpeak', 'thal_2']

print("前5个重要特征的类型判断:")
for feature in selected_features:
    # 检查特征是否存在于x1中
    if feature in x1.columns:
        unique_count = x1[feature].nunique()
        print(f'{feature} 的唯一值数量: {unique_count}')
        if unique_count < 10:  # 经验阈值,可以调整
            print(f'{feature} 可能是离散型变量')
        else:
            print(f'{feature} 可能是连续型变量')
    else:
        print(f'警告: 特征 {feature} 不存在于数据中')


--- 判断前5个重要特征的类型 ---
前5个重要特征的类型判断:
slope_2 的唯一值数量: 2
slope_2 可能是离散型变量
thalach 的唯一值数量: 91
thalach 可能是连续型变量
slope_1 的唯一值数量: 2
slope_1 可能是离散型变量
oldpeak 的唯一值数量: 5
oldpeak 可能是离散型变量
thal_2 的唯一值数量: 2
thal_2 可能是离散型变量
# --- 总样本中的前五个重要性特征分布图 --- 
print("\n--- 总样本中的前五个重要性特征分布图 --- ")
import matplotlib.pyplot as plt

# 定义前五个重要特征(根据SHAP条形图结果)
top5_feature_names = ['slope_2', 'thalach', 'slope_1', 'oldpeak', 'thal_2']

# 创建2行3列的子图网格(足够容纳5个特征)
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
axes = axes.flatten()  # 将2D数组展平为1D数组以便迭代

# 绘制前五个重要特征的直方图
for i, feature in enumerate(top5_feature_names[:5]):  # 确保只取前5个特征
    if feature in x1.columns:
        # 绘制直方图
        axes[i].hist(x1[feature], bins=20)
        axes[i].set_title(f'{feature} 分布图')
        axes[i].set_xlabel(feature)
        axes[i].set_ylabel('频率')
    else:
        print(f'警告: 特征 {feature} 不存在于数据中')
        axes[i].axis('off')  # 关闭不存在特征的子图

# 隐藏第6个子图(如果有)
if len(axes) > 5:
    for i in range(5, len(axes)):
        axes[i].axis('off')

plt.tight_layout()
plt.show()

了解一下每个聚类的分布情况,查看是否均衡,为后续分析提供信息。

print(X[['KMeans_Cluster']].value_counts())

KMeans_Cluster
0                 159
1                 126
2                  18
Name: count, dtype: int64
# 分别筛选出每个簇的数据
X_cluster0 = X[X['KMeans_Cluster'] == 0]
X_cluster1 = X[X['KMeans_Cluster'] == 1]
X_cluster2 = X[X['KMeans_Cluster'] == 2]


# 创建画布,3行5列的子图(每行代表一个簇,每列代表一个特征)
fig, axes = plt.subplots(3, 5, figsize=(20, 12))

# 绘制簇0的特征分布图
for i, feature in enumerate(top5_feature_names):
    axes[0, i].hist(X_cluster0[feature], bins=20, color='skyblue', alpha=0.7)
    axes[0, i].set_title(f'簇0 - {feature}分布图')
    axes[0, i].set_xlabel(feature)
    axes[0, i].set_ylabel('频率')

# 绘制簇1的特征分布图
for i, feature in enumerate(top5_feature_names):
    axes[1, i].hist(X_cluster1[feature], bins=20, color='lightgreen', alpha=0.7)
    axes[1, i].set_title(f'簇1 - {feature}分布图')
    axes[1, i].set_xlabel(feature)
    axes[1, i].set_ylabel('频率')

# 绘制簇2的特征分布图
for i, feature in enumerate(top5_feature_names):
    axes[2, i].hist(X_cluster2[feature], bins=20, color='salmon', alpha=0.7)
    axes[2, i].set_title(f'簇2 - {feature}分布图')
    axes[2, i].set_xlabel(feature)
    axes[2, i].set_ylabel('频率')

plt.tight_layout()
plt.show()

做出每一个簇的前五个重要性的特征分布图,通过ai来分析如何进行特征总结,来进行后续的特征工程。

  1. 第一个簇 - 心脏健康稳定型

    • 特征总结slope_2呈双峰分布,thalach取值范围广,slope_1多为小值,oldpeak普遍小,thal_2呈双峰分布 。整体心脏相关生理指标分布有特点,无明显集中风险特征,心脏健康基础表现稳定。各指标分布差异体现人群在心脏功能相关特征上有一定多样性,但无突出风险集中趋势,反映心脏健康状态相对均衡。
    • 定义依据:从slope(斜率,反映心脏功能相关)、thalach(最大心率 )等关键心脏指标看,分布虽有特点但无突出风险集中趋势,故定义为 “心脏健康稳定型”。
  2. 第二个簇 - 心脏指标集中型

    • 特征总结slope_2多为小值,thalach取值集中(呈现较为明显的单峰分布),slope_1小值情况更普遍,oldpeak分布相对分散,thal_2多为小值 。心脏相关指标在部分维度呈现集中化表现,指标特征相对一致。thalach等核心指标取值集中,反映该簇人群在心脏应激能力(以最大心率为体现)等方面相似性高,生理特征一致性强,疾病风险相对稳定且可预测。
    • 定义依据thalach等核心指标取值集中,slope类指标小值占比高,指标一致性强于其他簇。因指标集中体现生理特征一致、疾病风险易评估,因此定义为 “心脏指标集中型”。
  3. 第三个簇 - 心脏指标多峰分散型

    • 特征总结slope_2多为小值,thalach呈多峰分布(在几个特定值区间内频率较高,取值相对分散 ),slope_1有分散性,oldpeak集中分布,thal_2多为小值 。心脏指标在不同维度呈现多峰、分散等复杂分布,指标特征多样。多峰分散的thalach等指标,反映人群心脏应激能力差异大,涵盖不同健康状况、生活习惯或遗传背景个体,疾病风险复杂难概括。
    • 定义依据thalach等指标多峰分散,与前两个簇指标分布模式差异明显。基于复杂多样的指标分布特征(体现生理特征异质性、疾病风险难预测),定义为 “心脏指标多峰分散型”。

这样算完成了自己的一次特征工程,要注意不是簇有几类就有几个新特征,进行聚类后只得到了一个新的特征就是“KMeans_Cluster”,是KMeans聚类(k=3)生成的簇标签特征,取值0/1/2,代表样本在特征空间中的相似性分组。

下面代码为什么运行到“corrmat = train_data.corr() ”时报错,报错信息为“ValueError: could not convert string to float: '2010-01-02'” import pandas as pd import seaborn as sns # seaborn就是在matplotlib基础上面的封装,方便直接传参数调用 import matplotlib.pyplot as plt import numpy as np import warnings # 所有警告类别类的基类 warnings.filterwarnings('ignore') # 读入数据 train_csv = 'trainOX.csv' train_data = pd.read_csv(train_csv) test_csv = 'test_noLabelOX.csv' test_data = pd.read_csv(test_csv) train_data.head(10) # 训练前10行 train_data.isnull().sum() # 处理缺失值 # 数据规范化 import time # 对时间的处理 # 定义了获取年份的函数,参数dt,返回值t.tm_year def getYear(dt): t = time.strptime(dt,'%Y-%m-%d') return t.tm_year # 定义了获取月份的函数,参数dt,返回值t.tm_mon def getMonth(dt): t = time.strptime(dt,'%Y-%m-%d') return t.tm_mon # 定义了获取日期的函数,参数dt,返回值t.tm_mday def getDay(dt): t = time.strptime(dt,'%Y-%m-%d') return t.tm_mday # 定义了获取星期的函数,参数dt,返回值t.tm_wday def getWeek(dt): t = time.strptime(dt, '%Y-%m-%d') return t.tm_wday # 一周的周几 # 利用train_data函数对日期数据进行处理 train_data['year']=train_data['date'].apply(getYear) train_data['month']=train_data['date'].apply(getMonth) train_data['day']=train_data['date'].apply(getDay) train_data['week']=train_data['date'].apply(getWeek) # 利用test_data函数对日期数据进行处理 test_data['year']=test_data['date'].apply(getYear) test_data['month']=test_data['date'].apply(getMonth) test_data['day']=test_data['date'].apply(getDay) test_data['week']=test_data['date'].apply(getWeek) # 拟合标准正态分布 from scipy.stats import norm sns.distplot(train_data['Label'],fit=norm) print("Skewness: %f"% train_data['Label'].skew()) # 返回峰值的不对称程度 print("Kurtosis: %f"% train_data['Label'].kurt()) # 返回数据的峰度 # 检验样本数据概率分布(例如正态分布) # 预测Label(pm2.5)值线性分布可能性检测,probplot函数计算一个当前样本最可能的线性分布 # 并用plt展示出来,我们可以直观的看到线性拟合程度并不好。 from scipy import stats fig = plt.figure() res = stats.probplot(train_data['Label'],plot=plt) # 默认检测是正态分布 train_data[train_data['Label']==0].head(10) # 做 log 转换。虽然值做 log 转换会出错,但是0值只有2条,可以去掉。 train_data = train_data.drop(train_data[train_data['Label'] == 0].index) # 删除某几列 train_data['Label_log']= np.log(train_data['Label']) sns.distplot(train_data['Label_log'],fit=norm) # 再次拟合标准正态分布 print("Skewness: %f" % train_data['Label_log'].skew()) print("Kurtosis: %f" % train_data['Label_log'].kurt()) res = stats.probplot(train_data['Label_log'], plot=plt) var = 'DEWP' # 沿着指定的轴将train_data['Label_log’]和train_data[var]]拼接到一起,axis=1表示左右拼接。 data = pd.concat([train_data['Label_log'], train_data[var]], axis=1) # scatter绘制散点数据,x,y为坐标数据,ylim=(0,10)限制范围 data.plot.scatter(x=var,y='Label_log',ylim=(0,10)) # 下面的程序同理 var = 'TEMP' data = pd.concat([train_data['Label_log'], train_data[var]], axis=1) data.plot.scatter(x=var,y='Label_log',ylim=(0,10)) var = 'Iws' data = pd.concat([train_data['Label_log'], train_data[var]], axis=1) data.plot.scatter(x=var,y='Label_log',ylim=(0,10)) var ='Ir' data = pd.concat([train_data['Label_log'], train_data[var]], axis=1) data.plot.scatter(x=var, y='Label_log',ylim=(0, 10)) var ='DEWP' data = pd.concat([train_data['Label_log'], train_data[var]], axis=1) f, ax = plt.subplots(figsize=(20,16)) fig = sns.boxplot(x=var,y='Label_log', data=data) fig.axis(ymin=0,ymax=10) # 相关性分析 # correlation matrix相关矩阵 corrmat = train_data.corr() # corrmat是相关性矩阵 f,ax = plt.subplots(figsize=(12,8)) # 绘制画布 sns.heatmap(corrmat,vmax=0.8,square=True) # 得到各特征图的热力图 k = 5 # 关系矩阵中将显示10个特征 cols_large = corrmat.nlargest(k,'Label_log')['Label_log'].index # 显示和Label_1og相关性最大的K项 cols_small = corrmat.nsmallest(k,'Label_log')['Label_log'].index # 显示机Label_log相关性最小的K项 cols =cols_large.append(cols_small) cols cm = np.corrcoef(train_data[cols].values.T) sns.set(rc = {"figure.figsize":(12,10)}) sns.set(font_scale=1.25) hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size':10}, yticklabels=cols.values, xticklabels=cols.values) plt.show() train_data['hour']=train_data['hour'].astype('float32') train_data['DEWP']=train_data['DEWP'].astype('float32') train_data['TEMp']=train_data['TEMp'].astype('float32') train_data['PREs']=train_data['PREs'].astype('float32') train_data['Iws']=train_data['Iws'].astype('float32') train_data['Is']=train_data['Is'].astype('float32') train_data['Ir']=train_data['Ir'].astype('float32') train_data['cbwd_NE']=train_data['cbwd_NE'].astype('float32') train_data['cbwd_NW']=train_data['cbwd_NW'].astype('float32') train_data['cbwd_SE']=train_data['cbwd_SE'].astype('float32') train_data['cbwd_cv']=train_data['cbwd_cv'].astype('float32') train_data['year']=train_data['year'].astype('float32') train_data['month']=train_data['month'].astype('float32') train_data['day']=train_data['day'].astype('float32') train_data['week']=train_data['week'].astype('float32') train_data['Label log']=train_data['Label log'].astype('float32') test_data['hour']=test_data['hour'].astype('float32') test_data['DEWP']=test_data['DEWP'].astype('float32') test_data['TEMP']=test_data['TEMP'].astype('float32') test_data['PRES']=test_data['PREs'].astype('float32') test_data['Iws']=test_data['Iws'].astype('float32') test_data['Is']=test_data['Is'].astype('float32') test_data['Ir']=test_data['Ir'].astype('float32') test_data['cbwd_NE']=test_data['cbwd_NE'].astype('float32') test_data['cbwd_NW']=test_data['cbwd_Nw'].astype('float32') test_data['cbwd_SE']=test_data['cbwd_SE'].astype('float32') test_data['cbwd_cv']=test_data['cbwd_cv'].astype('float32') test_data['year']=test_data['year'].astype('float32') test_data['month']=test_data['month'].astype('float32') test_data['day']=test_data['day'].astype('float32') test_data['week']=test_data['week'].astype('float32') train_data.columns from sklearn.linear_model import LinearRegression # 线性回归 from sklearn.model_selection import train_test_split # 拆分工具 from sklearn.metrics import mean_squared_error # 均方根误差 # train_data.drop(['date'],axis=1,inplace=True) # 删除无关属性 y=train_data['Label log'] # 类标签的转换 var =['hour','DEWP','TEMP','PRES','IWS','IS','Ir', 'cbwd_NE','cbwd_NW','cbwd_SE','cbwd_cv','year', 'month', 'day','week'] X=train_data[var] # 新的训练数据 X_train, X_val, y_train, y_val = train_test_split(X,y,test_size=0.2,random_state=42) # 对数据的拆分 reg = LinearRegression().fit(X_train,y_train) # 回归分析 y_val_pre=reg.predict(X_val) # 回归预测 y_val1 = y_val.reset_index(drop=True) print("Mean squared error:%.2f"% mean_squared_error(y_val1,y_val_pre)) df1 = pd.DataFrame(y_val_pre,columns =['p']) # 建立检验数据框 df1['r'] = y_val df1.to_csv("test1.csv",encoding = "utf-8",header=1,index=0) X_test = test_data[var] # 训练数据 y_test = reg.predict(X_test) # predict:数据预测 y_rel = np.round(np.exp(y_test)) # 对浮点数取整 df = pd.DataFrame(y_rel,columns =['pm2.5']) # DataFrame()创建一个DataFrame对象 df.to_csv("sample.csv",encoding = "utf-8",header=1,index=0) # to_csv保存csv文件
10-31
<think>我们遇到了一个错误:在运行 `corrmat = train_data.corr()` 时出现 `ValueError: could not convert string to float: '2010-01-02'`。这个错误表明在计算相关系数矩阵时,pandas试图将字符串(如'2010-01-02')转换为浮点数,但失败了。这是因为 `corr()` 方法只能计算数值列之间的相关系数,如果DataFrame中包含非数值列(比如字符串、日期等),就会出错。 根据错误信息,日期字符串出现在数据中,因此我们需要检查数据集中是否包含非数值列。通常,在计算相关系数之前,我们需要确保DataFrame中只包含数值列。 解决步骤: 1. 检查DataFrame的列类型:使用 `train_data.dtypes` 查看各列的数据类型,找出非数值列(如object, datetime等)。 2. 处理非数值列: a. 如果非数值列不需要参与相关性计算,我们可以选择只选取数值列进行计算。 b. 如果非数值列包含重要信息(如日期),我们可以考虑将其转换为数值形式(例如,将日期转换为时间戳)或者提取特征(如年、月、日等)使其成为数值列。 3. 使用处理后的数值列计算相关系数矩阵。 另外,根据错误中出现的字符串内容('2010-01-02'),这很可能是一个日期列。我们可以尝试将其转换为datetime类型,然后提取数值特征(如时间戳)或者分解为多个数值列(年、月、日等)。 具体操作建议: 步骤1:查看数据类型 ```python print(train_data.dtypes) ``` 步骤2:处理日期列(假设该列名为'date') 如果有一个日期列,我们可以这样做: ```python # 将字符串转换为datetime对象 train_data['date'] = pd.to_datetime(train_data['date']) # 然后,我们可以创建新的数值列,例如: train_data['year'] = train_data['date'].dt.year train_data['month'] = train_data['date'].dt.month train_data['day'] = train_data['date'].dt.day # 然后删除原来的日期列(如果不删除,后面计算相关矩阵还是会包含非数值列) train_data_numeric = train_data.drop('date', axis=1) ``` 但是,请注意,可能还有其他非数值列。因此,更通用的做法是选取所有数值类型的列,或者将非数值列转换为数值列(如果可能且有意义)。 步骤3:只选择数值列 ```python train_data_numeric = train_data.select_dtypes(include=[np.number]) ``` 步骤4:计算相关系数矩阵 ```python corrmat = train_data_numeric.corr() ``` 然后就可以使用这个相关系数矩阵进行后续操作,比如用seaborn绘制热图。 如果我们需要保留某些非数值列的信息,那么必须将其转换为数值形式。例如,分类变量可以使用独热编码(one-hot encoding)或标签编码(label encoding)转换为数值形式。 但是,请注意:相关系数通常用于衡量两个连续变量之间的线性关系,对于分类变量转换后的数值,相关系数的解释可能并不直观(特别是对于无序的分类变量,使用相关系数可能并不合适)。 因此,解决这个错误的核心是确保在调用 `corr()` 之前,DataFrame中只包含数值列。 让我们根据上述思路修改代码: 假设原始代码可能是这样的: ```python import pandas as pd import seaborn as sns # ... 读取数据到train_data ... corrmat = train_data.corr() # 这里出错 ``` 修改后: ```python import pandas as pd import seaborn as sns import numpy as np # ... 读取数据到train_data ... # 处理日期列(如果有明确列名,假设为'date') # 如果不知道列名,我们可以通过检查数据类型来找到非数值列 # 首先,将日期字符串转换为datetime(如果存在且为字符串) # 注意:这里需要知道日期列的列名,或者通过数据类型为object来推断 # 方法1:直接选取数值列 train_data_numeric = train_data.select_dtypes(include=[np.number]) # 如果我们需要保留日期信息,可以按照上面的方式转换日期列并创建新特征 # 但这里我们假设只使用数值列 # 计算相关系数 corrmat = train_data_numeric.corr() # 然后可以继续使用corrmat,例如画热图 sns.heatmap(corrmat, annot=True) ``` 如果错误中提到的日期字符串是在一个我们不知道的列中,我们可以通过打印列的数据类型来定位: ```python non_numeric_columns = train_data.select_dtypes(exclude=[np.number]).columns print("非数值列有:", non_numeric_columns) ``` 然后针对这些非数值列进行处理(转换或删除)。 另一种情况:如果我们的数据集中有多个非数值列,并且我们想要保留一些重要的非数值列(如分类列),我们可以将这些分类列转换为数值编码。例如,使用`pd.get_dummies`进行独热编码: ```python # 将分类变量转换为哑变量 train_data_encoded = pd.get_dummies(train_data, columns=['category_column1', 'category_column2']) # 但是注意,这样可能会创建很多列,且对于日期列,我们可能需要单独处理(如上面提到的分解) # 然后我们只选取数值列(因为pd.get_dummies转换后是数值,但我们也可以直接使用,因为非数值列都被转换了?) # 实际上,get_dummies不会处理数值列,所以我们可以直接对转换后的数据计算相关系数 corrmat = train_data_encoded.corr() ``` 综上所述,根据我们的具体情况,我们可以选择只保留数值列,或者将非数值特征转换为数值特征。 现在,根据错误信息,我们明确知道有一个字符串是日期格式,所以我们可以优先处理日期列。 但是,如果日期列并不是我们想要分析的特征,我们也可以直接删除它,只分析其他数值列。 因此,解决方案总结如下: 1. 识别并处理非数值列,特别是日期列。 2. 使用数值列计算相关系数矩阵。 注意:在删除列或转换列之前,确保我们了解数据,以免删除重要信息。 最后,如果我们的数据集中有大量的非数值列,并且我们希望将它们都纳入相关性分析,那么我们需要将它们转换为数值形式。但是,相关性分析对于数值变量更有意义,对于分类变量,我们可能需要使用其他统计方法(如卡方检验)来探索关系。 根据用户的问题,我们只需要解决这个错误,所以采用上述方法即可。 下面提供一个修改后的代码示例: </think>### 解决 `corrmat = train_data.corr()` 的 ValueError 错误 这个错误发生在 Pandas 的 `corr()` 方法尝试计算相关性时遇到非数值数据(如日期字符串 `'2010-01-02'`)。以下是系统化的解决方案: #### 1. **检查数据类型** ```python print(train_data.dtypes) ``` 输出各列数据类型,确认哪些是非数值列(如 `object` 类型)。 #### 2. **处理日期/时间列** - **转换日期为数值特征**: ```python # 转换为 datetime 类型 train_data['date_column'] = pd.to_datetime(train_data['date_column']) # 提取数值特征(如时间戳) train_data['timestamp'] = train_data['date_column'].astype('int64') / 10**9 # 转为秒级时间戳 train_data = train_data.drop('date_column', axis=1) # 移除原始日期列 ``` - **或分解为多个数值列**: ```python train_data['year'] = train_data['date_column'].dt.year train_data['month'] = train_data['date_column'].dt.month train_data['day'] = train_data['date_column'].dt.day ``` #### 3. **选择性过滤数值列** ```python # 方法1:自动选择数值列 numeric_data = train_data.select_dtypes(include=['int64', 'float64']) # 方法2:手动指定数值列 numeric_cols = ['col1', 'col2', 'timestamp'] # 替换为实际数值列名 numeric_data = train_data[numeric_cols] corrmat = numeric_data.corr() # 重新计算相关性 ``` #### 4. **处理其他非数值数据** - **分类变量**:使用独热编码转换: ```python train_data = pd.get_dummies(train_data, columns=['category_column']) ``` - **文本数据**:需通过 NLP 技术向量化(如 TF-IDF)。 #### 5. **绘制热力图** ```python import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(12, 8)) sns.heatmap(corrmat, annot=True, cmap='coolwarm') plt.show() ``` #### 错误原因说明 - `corr()` 仅支持数值数据,遇到字符串(如 `'2010-01-02'`)会抛出 `ValueError`[^1]。 - 日期列需显式转换为数值格式(如时间戳或分解特征)才能参与计算。 - 分类/文本数据需转换为数值表示(独热编码、向量化等)。 --- ### 相关问题 1. Pandas 中如何高效处理大型数据集的混合类型(数值+非数值)列? 2. 计算相关性时,除了 Pearson 相关系数,还有哪些替代方法适用于非数值数据? 3. Seaborn 热力图有哪些高级定制技巧(如聚类、掩码)? 4. 时间序列数据在进行相关性分析前需要进行哪些预处理? [^1]: 引用自用户提供的 Pandas 文档参考 [^2]: 引用自用户提供的 TensorFlow 示例说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值