# 分离特征与目标变量 data_final_vars=data_final.columns.values.tolist() y=['y'] X=[i for i in data_final_vars if i not in y] from sklearn import datasets from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression logreg = LogisticRegression() rfe = RFE(logreg, 18) rfe = rfe.fit(data_final[X], data_final[y] ) print(rfe.support_) print(rfe.ranking_)#当结果是1表示该特征比较重要,被选出来,这段代码报错如下:init() takes 2 positional arguments but 3 were given,怎么解决
时间: 2024-03-25 18:40:12 浏览: 96
这个错误一般是因为 LogisticRegression() 函数的参数传递有误导致的。根据你提供的代码,可能是因为在初始化 LogisticRegression() 函数时没有指定 solver 和 max_iter 参数,导致报错。
可以试着将 LogisticRegression() 函数的初始化修改为如下形式:
```
logreg = LogisticRegression(solver='lbfgs', max_iter=1000)
```
其中的参数根据具体情况可以进行调整。如果修改后仍然报错,请确保你已经正确导入了所需的库和模块,并且 X 和 y 的格式正确。同时,建议检查一下是否有其他代码对该部分代码造成了影响。
相关问题
我发现表单3的数据并没有被处理和分析。下面是对此的修改: ```python def load_and_process_data(file_path, sheet_name): """加载和处理数据""" try: # 检查文件是否存在 if not os.path.exists(file_path): log_message(f"错误: 文件 '{file_path}' 不存在") return None # 读取数据 data = pd.read_excel(file_path, sheet_name=sheet_name) log_message(f"成功加载数据, 共 {len(data)} 行") # 列名修复 col_renames = { '表面风化化': '表面风化', '采采样点风化类型': '采样点风化类型', '样点风化类型': '采样点风化类型', '总成分': '总含量' } new_columns = [] for col in data.columns: if col in col_renames: new_columns.append(col_renames[col]) else: new_columns.append(col) data.columns = new_columns # 化学成分列重命名 rename_dict = { '氧化硅(Si)': '二氧化硅(SiO2)', '氧化锡(SnO)': '氧化锡(SnO2)', '氧化硫(SO3)': '二氧化硫(SO2)', '氧化亚铜(Cu2O)': '氧化亚铜(Cu2O)', '氧化铜(CuO)': '氧化铜(CuO)', '三氧化二铁(Fe2O3)': '三氧化二铁(Fe2O3)' } data = data.rename(columns=rename_dict) # 删除总含量列 if '总含量' in data.columns: data = data.drop('总含量', axis=1) log_message("已删除'总含量'列") # 添加缺失列的处理 required_cols = ['表面风化', '采样点风化类型', '类型'] for col in required_cols: if col not in data.columns: data[col] = np.nan log_message(f"警告: 列 '{col}' 不存在,已创建空白列") # 移除空白行 data.dropna(how='all', inplace=True) log_message(f"处理后数据行数: {len(data)}") return data except Exception as e: log_message(f"数据处理失败: {str(e)}") traceback.print_exc() return None # 加载表单3的数据 unknown_file_path = r"D:\Users\86157\Desktop\数学建模\附件.xlsx" unknown_data = load_and_process_data(unknown_file_path, sheet_name='表单3') if unknown_data is not None: # 在这里对表单3的数据进行分析和处理 log_message("成功加载并处理了表单3的数据") else: log_message("无法加载或处理表单3的数据") ``` 添加了一个新的参数`sheet_name`到`load_and_process_data`函数中,以便加载特定的工作表。然后我直接调用了这个函数来加载表单3的数据,并在后续的代码中对其进行处理。 这样就可以确保表单3的数据也被正确地加载和处理了。请检查一下下面代码,不要修改文件地址,修改下面代码,并给出完整代码 代码如下: import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt from sklearn.model_selection import GridSearchCV from sklearn.ensemble import RandomForestClassifier from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler from sklearn.metrics import f1_score, adjusted_rand_score from itertools import permutations import os import traceback from mpl_toolkits.mplot3d import Axes3D import warnings from scipy.stats import f_oneway # 设置中文显示 plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 warnings.filterwarnings('ignore') def log_message(message): """记录日志消息并打印到控制台""" print(f"[INFO] {message}") def get_colors(style='bright'): """获取颜色调色板""" if style == 'bright': return sns.color_palette('bright') elif style == 'all': return sns.color_palette('hsv', 15) elif style == 'rainbow': return sns.color_palette('rainbow') else: return sns.color_palette('deep') def boxplot(data, rows, cols, hue=None, vars=None, figsize=(12, 8), subplots_adjust=(0.5, 0.5)): """创建箱线图""" try: if not vars: numerical_cols = data.select_dtypes(include=['float64', 'int64']).columns.tolist() if hue and hue in numerical_cols: numerical_cols.remove(hue) vars = numerical_cols fig = plt.figure(figsize=figsize) ax_num = 1 if hue: palette = get_colors('rainbow') else: palette = None for col in vars: plt.subplot(rows, cols, ax_num) if hue: sns.boxplot(x=hue, y=col, data=data, palette=palette) else: sns.boxplot(y=data[col], color=np.random.choice(sns.color_palette())) plt.title(col) plt.xticks(rotation=45) ax_num += 1 plt.tight_layout() plt.subplots_adjust(hspace=subplots_adjust[0], wspace=subplots_adjust[1]) plt.savefig('化学成分箱线图分析.jpg', dpi=300, bbox_inches='tight') plt.show() return True except Exception as e: log_message(f"创建箱线图失败: {str(e)}") return False def distplot(data, rows=3, cols=4, bins=10, vars=None, hue=None, kind='hist', stat='count', shade=True, figsize=(12, 5), color_style='all', alpha=0.7, subplots_adjust=(0.3, 0.2)): """创建分布图""" try: fig = plt.figure(figsize=figsize) numerical_cols = data.select_dtypes(include=['float64', 'int64']).columns.tolist() if not vars: vars = numerical_cols colors = get_colors(color_style) ax_num = 1 for col in vars: if col in numerical_cols and col != hue: plt.subplot(rows, cols, ax_num) col_data = data[col].dropna() if kind == 'hist': sns.histplot(data=data, x=col, bins=bins, color=np.random.choice(colors), hue=hue, alpha=alpha, stat=stat) elif kind == 'kde': sns.kdeplot(data=data, x=col, color=np.random.choice(colors), alpha=alpha, hue=hue, fill=shade) elif kind == 'both': sns.histplot(data=data, x=col, bins=bins, color=np.random.choice(colors), alpha=alpha, hue=hue, stat='density') sns.kdeplot(data=data, x=col, color='darkred', alpha=0.7, hue=hue, fill=False) plt.xlabel(col) ax_num += 1 plt.subplots_adjust(hspace=subplots_adjust[0], wspace=subplots_adjust[1]) plt.savefig('化学成分分布图.jpg', dpi=300, bbox_inches='tight') plt.show() return True except Exception as e: log_message(f"创建分布图失败: {str(e)}") return False def load_and_process_data(file_path): """加载和处理数据""" try: # 检查文件是否存在 if not os.path.exists(file_path): log_message(f"错误: 文件 '{file_path}' 不存在") return None # 读取数据 data = pd.read_excel(file_path) log_message(f"成功加载数据, 共 {len(data)} 行") # 列名修复 col_renames = { '表面风化化': '表面风化', '采采样点风化类型': '采样点风化类型', '样点风化类型': '采样点风化类型', '总成分': '总含量' } new_columns = [] for col in data.columns: if col in col_renames: new_columns.append(col_renames[col]) else: new_columns.append(col) data.columns = new_columns # 化学成分列重命名 rename_dict = { '氧化硅(Si)': '二氧化硅(SiO2)', '氧化锡(SnO)': '氧化锡(SnO2)', '氧化硫(SO3)': '二氧化硫(SO2)', '氧化亚铜(Cu2O)': '氧化亚铜(Cu2O)', '氧化铜(CuO)': '氧化铜(CuO)', '三氧化二铁(Fe2O3)': '三氧化二铁(Fe2O3)' } data = data.rename(columns=rename_dict) # 删除总含量列 if '总含量' in data.columns: data = data.drop('总含量', axis=1) log_message("已删除'总含量'列") # 添加缺失列的处理 required_cols = ['表面风化', '采样点风化类型', '类型'] for col in required_cols: if col not in data.columns: data[col] = np.nan log_message(f"警告: 列 '{col}' 不存在,已创建空白列") # 移除空白行 data.dropna(how='all', inplace=True) log_message(f"处理后数据行数: {len(data)}") return data except Exception as e: log_message(f"数据处理失败: {str(e)}") traceback.print_exc() return None def select_subclass_features(data): """亚类划分特征选择""" try: # 分离高钾和铅钡玻璃数据 gaojia_data = data[data['类型'] == '高钾'].copy() qianbai_data = data[data['类型'] == '铅钡'].copy() log_message(f"高钾玻璃数据量: {len(gaojia_data)}") log_message(f"铅钡玻璃数据量: {len(qianbai_data)}") # 获取化学成分列 chem_cols = [col for col in data.columns if any(x in col for x in ['氧化', '二氧化', '化学'])] log_message(f"找到 {len(chem_cols)} 个化学成分列") # 高钾玻璃的特征选择 log_message("\n==== 高钾玻璃特征选择 ====") if len(gaojia_data) > 0: gaojia_x = gaojia_data[chem_cols] gaojia_y = gaojia_data['采样点风化类型'] # 处理缺失值 for col in chem_cols: if gaojia_x[col].isna().any(): median_val = gaojia_x[col].median() gaojia_x[col].fillna(median_val, inplace=True) # 特征重要性分析 model = RandomForestClassifier(random_state=42) parameters = {'max_depth': range(1, 5), 'min_samples_leaf': [1, 2], 'criterion': ['gini', 'entropy'], 'min_impurity_decrease': [0.01, 0.02]} grid_search = GridSearchCV(model, parameters, cv=min(5, len(gaojia_data)), n_jobs=-1) grid_search.fit(gaojia_x, gaojia_y) log_message(f'高钾玻璃特征选择精度: {grid_search.best_score_:.4f}') log_message(f'最优参数: {grid_search.best_params_}') best_model = grid_search.best_estimator_ best_model.fit(gaojia_x, gaojia_y) # 特征重要性排序 gaojia_fea_df = pd.DataFrame({ '化学成分': chem_cols, '特征重要性': best_model.feature_importances_ }).sort_values('特征重要性', ascending=False) log_message("\n高钾玻璃特征重要性排序:") log_message(gaojia_fea_df.head(10).to_string()) else: log_message("警告: 没有高钾玻璃数据,跳过特征选择") gaojia_fea_df = pd.DataFrame({'化学成分': [], '特征重要性': []}) # 铅钡玻璃的特征选择 log_message("\n==== 铅钡玻璃特征选择 ====") if len(qianbai_data) > 0: qianbai_x = qianbai_data[chem_cols] qianbai_y = qianbai_data['采样点风化类型'] # 处理缺失值 for col in chem_cols: if qianbai_x[col].isna().any(): median_val = qianbai_x[col].median() qianbai_x[col].fillna(median_val, inplace=True) # 特征重要性分析 grid_search = GridSearchCV(RandomForestClassifier(random_state=42), parameters, cv=min(5, len(qianbai_data)), n_jobs=-1) grid_search.fit(qianbai_x, qianbai_y) log_message(f'铅钡玻璃特征选择精度: {grid_search.best_score_:.4f}') log_message(f'最优参数: {grid_search.best_params_}') best_model = grid_search.best_estimator_ best_model.fit(qianbai_x, qianbai_y) # 特征重要性排序 qianbai_fea_df = pd.DataFrame({ '化学成分': chem_cols, '特征重要性': best_model.feature_importances_ }).sort_values('特征重要性', ascending=False) log_message("\n铅钡玻璃特征重要性排序:") log_message(qianbai_fea_df.head(10).to_string()) else: log_message("警告: 没有铅钡玻璃数据,跳过特征选择") qianbai_fea_df = pd.DataFrame({'化学成分': [], '特征重要性': []}) return gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols except Exception as e: log_message(f"特征选择失败: {str(e)}") traceback.print_exc() return None, None, None, None, None def optimize_features_and_cluster(gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols): """特征优化和聚类分析""" try: # 高钾玻璃优化的聚类 log_message("\n==== 高钾玻璃优化聚类 ====") if len(gaojia_data) > 0: def evaluate_gaojia(pred): score = 0 for perm in permutations([0, 1]): true_labels = gaojia_data['采样点风化类型'].replace({'未风化点': perm[0], '风化点': perm[1]}) score_ = f1_score(true_labels, pred, average='weighted') score = max(score, score_) return score gaojia_fea_list = gaojia_fea_df['化学成分'].tolist() best_score = 0 best_features = [] deleted_features = [] # 特征优化 for num_features in range(1, min(15, len(gaojia_fea_list))): current_features = gaojia_fea_list[:num_features].copy() for feat in deleted_features: if feat in current_features: current_features.remove(feat) if not current_features: continue log_message(f"尝试特征数: {num_features}, 特征: {current_features}") # 数据标准化 X = gaojia_data[current_features].values scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 聚类分析 kmeans = KMeans(n_clusters=2, random_state=42, n_init=10) cluster_labels = kmeans.fit_predict(X_scaled) # 评估聚类效果 score = evaluate_gaojia(cluster_labels) log_message(f"聚类评估得分: {score:.4f}") if score > best_score: best_score = score best_features = current_features.copy() log_message(f"新最佳得分: {score:.4f},特征: {best_features}") else: last_feature = gaojia_fea_list[num_features - 1] if last_feature not in deleted_features: deleted_features.append(last_feature) log_message(f"将特征 {last_feature} 添加到删除列表") log_message(f"\n高钾玻璃最终选择的特征: {best_features}") log_message(f"聚类评估得分: {best_score:.4f}") # 最终聚类 if best_features: X_final = gaojia_data[best_features].values scaler_final = StandardScaler() X_final_scaled = scaler_final.fit_transform(X_final) kmeans_final = KMeans(n_clusters=2, random_state=42, n_init=10) final_labels = kmeans_final.fit_predict(X_final_scaled) gaojia_data['聚类标签'] = final_labels # 保存聚类中心 cluster_centers = kmeans_final.cluster_centers_ gaojia_cluster_centers = pd.DataFrame(cluster_centers, columns=best_features) gaojia_cluster_centers.index = ['亚类1', '亚类2'] else: log_message("警告: 没有为高钾玻璃找到合适的聚类特征") gaojia_cluster_centers = None else: log_message("没有高钾玻璃数据,跳过聚类") gaojia_cluster_centers = None best_features = [] # 铅钡玻璃优化的聚类 log_message("\n==== 铅钡玻璃优化聚类 ====") if len(qianbai_data) > 0: def evaluate_qianbai(pred): score = 0 for perm in permutations([0, 1, 2]): true_labels = qianbai_data['采样点风化类型'].replace({ '未风化点': perm[0], '风化点': perm[1], '严重风化点': perm[2] }) score_ = f1_score(true_labels, pred, average='weighted') score = max(score, score_) return score qianbai_fea_list = qianbai_fea_df['化学成分'].tolist() best_score_qb = 0 best_features_qb = [] deleted_features_qb = [] # 特征优化 for num_features in range(1, min(15, len(qianbai_fea_list))): current_features = qianbai_fea_list[:num_features].copy() for feat in deleted_features_qb: if feat in current_features: current_features.remove(feat) if not current_features: continue log_message(f"尝试特征数: {num_features}, 特征: {current_features}") # 数据标准化 X = qianbai_data[current_features].values scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 聚类分析 kmeans = KMeans(n_clusters=3, random_state=42, n_init=10) cluster_labels = kmeans.fit_predict(X_scaled) # 评估聚类效果 score = evaluate_qianbai(cluster_labels) log_message(f"聚类评估得分: {score:.4f}") if score > best_score_qb: best_score_qb = score best_features_qb = current_features.copy() log_message(f"新最佳得分: {score:.4f},特征: {best_features_qb}") else: last_feature = qianbai_fea_list[num_features - 1] if last_feature not in deleted_features_qb: deleted_features_qb.append(last_feature) log_message(f"将特征 {last_feature} 添加到删除列表") log_message(f"\n铅钡玻璃最终选择的特征: {best_features_qb}") log_message(f"聚类评估得分: {best_score_qb:.4f}") # 最终聚类 if best_features_qb: X_final = qianbai_data[best_features_qb].values scaler_final = StandardScaler() X_final_scaled = scaler_final.fit_transform(X_final) kmeans_final = KMeans(n_clusters=3, random_state=42, n_init=10) final_labels = kmeans_final.fit_predict(X_final_scaled) qianbai_data['聚类标签'] = final_labels # 保存聚类中心 cluster_centers = kmeans_final.cluster_centers_ qianbai_cluster_centers = pd.DataFrame(cluster_centers, columns=best_features_qb) qianbai_cluster_centers.index = ['亚类1', '亚类2', '亚类3'] else: log_message("警告: 没有为铅钡玻璃找到合适的聚类特征") qianbai_cluster_centers = None else: log_message("没有铅钡玻璃数据,跳过聚类") qianbai_cluster_centers = None best_features_qb = [] return gaojia_data, qianbai_data, best_features, best_features_qb, gaojia_cluster_centers, qianbai_cluster_centers except Exception as e: log_message(f"聚类优化失败: {str(e)}") traceback.print_exc() return None, None, [], [], None, None def visualize_and_analyze_subclasses(gaojia_data, qianbai_data, gaojia_features, qianbai_features, gaojia_cluster_centers, qianbai_cluster_centers): """亚类划分结果可视化与分析""" try: log_message("\n==== 亚类划分结果可视化与分析 ====") # 高钾玻璃亚类划分可视化 if gaojia_data is not None and '聚类标签' in gaojia_data.columns: plt.figure(figsize=(12, 8)) plt.suptitle("高钾玻璃亚类划分(基于聚类)") # 3D散点图 ax1 = plt.subplot(121, projection='3d') use_cols = gaojia_features[:3] if len(gaojia_features) >= 3 else gaojia_features colors = get_colors('bright') if use_cols: for i in range(2): # 两个亚类 cluster_data = gaojia_data[gaojia_data['聚类标签'] == i] label = f'亚类{i + 1}' if len(use_cols) == 3: ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]], cluster_data[use_cols[2]], color=colors[i], label=label, s=50, alpha=0.7) elif len(use_cols) == 2: ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]], np.zeros(len(cluster_data)), color=colors[i], label=label, s=50, alpha=0.7) else: # 只有1个特征 ax1.scatter(cluster_data[use_cols[0]], np.zeros(len(cluster_data)), np.zeros(len(cluster_data)), color=colors[i], label=label, s=50, alpha=0.7) if len(use_cols) >= 1: ax1.set_xlabel(use_cols[0]) if len(use_cols) >= 2: ax1.set_ylabel(use_cols[1]) if len(use_cols) >= 3: ax1.set_zlabel(use_cols[2]) ax1.legend() else: ax1.text(0.5, 0.5, "没有足够的特征进行可视化", ha='center', va='center') # 箱线图比较亚类特征分布 ax2 = plt.subplot(122) if gaojia_features: box_data = gaojia_data.copy() box_data['亚类'] = box_data['聚类标签'].apply(lambda x: f'亚类{x + 1}') sns.boxplot(x='亚类', y=gaojia_features[0], data=box_data, palette=[colors[0], colors[1]]) plt.title(f'关键特征比较: {gaojia_features[0]}') else: ax2.text(0.5, 0.5, "没有可用特征", ha='center', va='center') plt.tight_layout() plt.savefig('高钾玻璃亚类划分结果.jpg', dpi=300) plt.show() else: log_message("警告: 高钾玻璃聚类结果不可用,跳过可视化") # 铅钡玻璃亚类划分可视化 if qianbai_data is not None and '聚类标签' in qianbai_data.columns: plt.figure(figsize=(12, 8)) plt.suptitle("铅钡玻璃亚类划分(基于聚类)") # 3D散点图 ax1 = plt.subplot(121, projection='3d') use_cols = qianbai_features[:3] if len(qianbai_features) >= 3 else qianbai_features colors = get_colors('bright') if use_cols: for i in range(3): # 三个亚类 cluster_data = qianbai_data[qianbai_data['聚类标签'] == i] label = f'亚类{i + 1}' if len(use_cols) == 3: ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]], cluster_data[use_cols[2]], color=colors[i], label=label, s=50, alpha=0.7) elif len(use_cols) == 2: ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]], np.zeros(len(cluster_data)), color=colors[i], label=label, s=50, alpha=0.7) else: # 只有1个特征 ax1.scatter(cluster_data[use_cols[0]], np.zeros(len(cluster_data)), np.zeros(len(cluster_data)), color=colors[i], label=label, s=50, alpha=0.7) if len(use_cols) >= 1: ax1.set_xlabel(use_cols[0]) if len(use_cols) >= 2: ax1.set_ylabel(use_cols[1]) if len(use_cols) >= 3: ax1.set_zlabel(use_cols[2]) ax1.legend() else: ax1.text(0.5, 0.5, "没有足够的特征进行可视化", ha='center', va='center') # 箱线图比较亚类特征分布 ax2 = plt.subplot(122) if qianbai_features: box_data = qianbai_data.copy() box_data['亚类'] = box_data['聚类标签'].apply(lambda x: f'亚类{x + 1}') sns.boxplot(x='亚类', y=qianbai_features[0], data=box_data, palette=colors[:3]) plt.title(f'关键特征比较: {qianbai_features[0]}') else: ax2.text(0.5, 0.5, "没有可用特征", ha='center', va='center') plt.tight_layout() plt.savefig('铅钡玻璃亚类划分结果.jpg', dpi=300) plt.show() else: log_message("警告: 铅钡玻璃聚类结果不可用,跳过可视化") # 合理性分析 - ANOVA检验特征显著差异 log_message("\n==== 合理性分析 - 亚类特征差异检验 ====") # 高钾玻璃 if gaojia_data is not None and '聚类标签' in gaojia_data.columns and gaojia_features: log_message("\n高钾玻璃:") for i, feature in enumerate(gaojia_features[:3]): try: groups = [gaojia_data[gaojia_data['聚类标签'] == j][feature] for j in range(2)] f_val, p_val = f_oneway(*groups) log_message(f"{feature}: F值={f_val:.4f}, p值={p_val:.4f}{' (显著)' if p_val < 0.05 else ''}") except Exception as e: log_message(f"无法计算特征 {feature} 的ANOVA检验: {str(e)}") # 铅钡玻璃 if qianbai_data is not None and '聚类标签' in qianbai_data.columns and qianbai_features: log_message("\n铅钡玻璃:") for i, feature in enumerate(qianbai_features[:3]): try: groups = [qianbai_data[qianbai_data['聚类标签'] == j][feature] for j in range(3)] f_val, p_val = f_oneway(*groups) log_message(f"{feature}: F值={f_val:.4f}, p值={p_val:.4f}{' (显著)' if p_val < 0.05 else ''}") except Exception as e: log_message(f"无法计算特征 {feature} 的ANOVA检验: {str(e)}") # 保存聚类中心 try: if gaojia_cluster_centers is not None: gaojia_cluster_centers.to_excel("高钾玻璃亚类聚类中心.xlsx") log_message("高钾玻璃聚类中心已保存") if qianbai_cluster_centers is not None: qianbai_cluster_centers.to_excel("铅钡玻璃亚类聚类中心.xlsx") log_message("铅钡玻璃聚类中心已保存") except Exception as e: log_message(f"保存聚类中心失败: {str(e)}") return gaojia_data, qianbai_data except Exception as e: log_message(f"可视化与分析失败: {str(e)}") traceback.print_exc() return None, None def main(): """主函数""" try: # 文件路径 file_path = r"D:\BianChen\python_studycode\tf_env\玻璃\分析结果.xlsx" log_message(f"开始执行分析,数据文件: {file_path}") # 1. 加载和处理数据 log_message("\n==== 步骤1: 数据加载与预处理 ====") data = load_and_process_data(file_path) if data is None or len(data) == 0: log_message("错误: 数据处理失败或没有有效数据,程序终止") return # 初始数据可视化 log_message("\n执行初始数据可视化...") plt.figure(figsize=(8, 6)) sns.countplot(x='类型', data=data, palette='Set2') plt.title('玻璃类型分布') plt.savefig('玻璃类型分布.jpg', dpi=300) plt.show() # 2. 亚类划分的特征选择 log_message("\n==== 步骤2: 亚类划分特征选择 ====") gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols = select_subclass_features(data) if gaojia_fea_df is not None and not gaojia_fea_df.empty: gaojia_fea_df.to_excel("高钾玻璃特征重要性.xlsx", index=False) log_message("高钾玻璃特征重要性已保存") if qianbai_fea_df is not None and not qianbai_fea_df.empty: qianbai_fea_df.to_excel("铅钡玻璃特征重要性.xlsx", index=False) log_message("铅钡玻璃特征重要性已保存") # 3. 聚类和优化特征选择 log_message("\n==== 步骤3: 特征优化与亚类聚类 ====") (gaojia_with_subclasses, qianbai_with_subclasses, gaojia_features, qianbai_features, gaojia_centers, qianbai_centers) = optimize_features_and_cluster( gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols ) log_message(f"高钾玻璃最终使用特征: {gaojia_features}") log_message(f"铅钡玻璃最终使用特征: {qianbai_features}") # 4. 亚类划分的可视化与分析 log_message("\n==== 步骤4: 亚类划分可视化与分析 ====") gaojia_final, qianbai_final = visualize_and_analyze_subclasses( gaojia_with_subclasses, qianbai_with_subclasses, gaojia_features, qianbai_features, gaojia_centers, qianbai_centers ) # 5. 保存最终结果 log_message("\n==== 步骤5: 保存结果 ====") try: if gaojia_final is not None and not gaojia_final.empty: gaojia_final.to_excel("高钾玻璃亚类划分结果.xlsx", index=False) log_message("高钾玻璃亚类划分结果已保存") if qianbai_final is not None and not qianbai_final.empty: qianbai_final.to_excel("铅钡玻璃亚类划分结果.xlsx", index=False) log_message("铅钡玻璃亚类划分结果已保存") except Exception as e: log_message(f"保存最终结果失败: {str(e)}") log_message("\n亚类划分分析完成!") except Exception as e: log_message(f"程序执行出错: {str(e)}") traceback.print_exc() if __name__ == "__main__": main()
<think>好的,用户指出表单3的数据没有被处理和分析,并提供了一段修改后的代码。用户希望我检查并修改现有代码,确保表单3的数据被正确加载和处理,同时不改变文件路径。用户还要求给出完整的代码。
首先,我需要理解用户的问题。原代码中的`load_and_process_data`函数没有处理Excel文件中的特定工作表,因此用户添加了一个`sheet_name`参数来指定要加载的工作表。用户还添加了加载表单3的代码,并调用了这个修改后的函数。
接下来,我需要检查用户提供的代码,并确定需要修改的部分。原代码中的`load_and_process_data`函数确实缺少`sheet_name`参数,导致无法指定工作表。用户修改后的函数添加了该参数,但需要确保所有调用该函数的地方都传递正确的参数。例如,在`main`函数中,调用`load_and_process_data(file_path)`需要改为`load_and_process_data(file_path, sheet_name)`,但用户可能没有在`main`函数中处理这一点。
然后,用户希望将表单3的数据加载并处理,可能需要将处理后的数据与其他数据结合分析,或者单独分析。用户提供的代码中,在`main`函数之后添加了加载表单3的代码,但需要将其整合到现有代码中,可能需要调整主函数的结构,或者创建新的处理流程。
我需要确保修改后的代码不会影响原有功能,同时正确加载表单3的数据。可能的解决方案是在`main`函数中添加处理不同工作表的逻辑,或者在程序中区分不同数据源的处理步骤。
另外,用户提到“不要修改文件地址”,因此需要保留原有的`file_path`变量,同时为表单3指定不同的工作表名称。例如,原数据可能在某个工作表中,而表单3是另一个工作表,需要分别加载和处理。
需要检查`load_and_process_data`函数的调用位置,确保在主函数中正确传递`sheet_name`参数。例如,在`main`函数中,可能需要为不同的数据集调用多次该函数,每次指定不同的工作表名称。
可能还需要处理多个数据集的合并或对比分析,但用户可能只需要加载和处理表单3的数据,可能不需要与原数据合并。因此,需要确定用户希望如何处理这两个数据集:是否独立处理,还是合并后处理。
在用户提供的修改代码中,他们在`main`函数之后添加了加载表单3的代码,但这样会导致主函数运行后再次处理数据。可能需要将这部分整合到`main`函数中,或者作为独立的流程处理。
最后,确保所有修改后的代码语法正确,没有遗漏参数或错误。例如,确保`pd.read_excel`正确接收`sheet_name`参数,并且所有函数调用一致。
总结步骤:
1. 修改`load_and_process_data`函数,添加`sheet_name`参数,默认值设为None,以保持向后兼容。
2. 在`main`函数中调用该函数时,传递适当的工作表名称,例如原数据可能在默认工作表,而表单3需要单独处理。
3. 在代码中添加处理表单3的逻辑,可能作为另一个主函数或独立流程,确保不干扰原有分析流程。
4. 测试修改后的代码,确保原有功能正常,同时正确加载和处理表单3的数据。</think>以下是修改后的完整代码,主要改进包括:
1. 为`load_and_process_data`函数添加sheet_name参数(默认为0)
2. 在main函数中新增对表单3的处理流程
3. 保持原有数据分析流程完整
4. 新增对未知数据的预测功能
```python
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import f1_score, adjusted_rand_score
from itertools import permutations
import os
import traceback
from mpl_toolkits.mplot3d import Axes3D
import warnings
from scipy.stats import f_oneway
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
warnings.filterwarnings('ignore')
def log_message(message):
"""记录日志消息并打印到控制台"""
print(f"[INFO] {message}")
def get_colors(style='bright'):
"""获取颜色调色板"""
if style == 'bright':
return sns.color_palette('bright')
elif style == 'all':
return sns.color_palette('hsv', 15)
elif style == 'rainbow':
return sns.color_palette('rainbow')
else:
return sns.color_palette('deep')
def boxplot(data, rows, cols, hue=None, vars=None, figsize=(12, 8), subplots_adjust=(0.5, 0.5)):
"""创建箱线图"""
try:
if not vars:
numerical_cols = data.select_dtypes(include=['float64', 'int64']).columns.tolist()
if hue and hue in numerical_cols:
numerical_cols.remove(hue)
vars = numerical_cols
fig = plt.figure(figsize=figsize)
ax_num = 1
if hue:
palette = get_colors('rainbow')
else:
palette = None
for col in vars:
plt.subplot(rows, cols, ax_num)
if hue:
sns.boxplot(x=hue, y=col, data=data, palette=palette)
else:
sns.boxplot(y=data[col], color=np.random.choice(sns.color_palette()))
plt.title(col)
plt.xticks(rotation=45)
ax_num += 1
plt.tight_layout()
plt.subplots_adjust(hspace=subplots_adjust[0], wspace=subplots_adjust[1])
plt.savefig('化学成分箱线图分析.jpg', dpi=300, bbox_inches='tight')
plt.show()
return True
except Exception as e:
log_message(f"创建箱线图失败: {str(e)}")
return False
def distplot(data, rows=3, cols=4, bins=10, vars=None, hue=None, kind='hist', stat='count', shade=True,
figsize=(12, 5), color_style='all', alpha=0.7, subplots_adjust=(0.3, 0.2)):
"""创建分布图"""
try:
fig = plt.figure(figsize=figsize)
numerical_cols = data.select_dtypes(include=['float64', 'int64']).columns.tolist()
if not vars:
vars = numerical_cols
colors = get_colors(color_style)
ax_num = 1
for col in vars:
if col in numerical_cols and col != hue:
plt.subplot(rows, cols, ax_num)
col_data = data[col].dropna()
if kind == 'hist':
sns.histplot(data=data, x=col, bins=bins, color=np.random.choice(colors),
hue=hue, alpha=alpha, stat=stat)
elif kind == 'kde':
sns.kdeplot(data=data, x=col, color=np.random.choice(colors), alpha=alpha,
hue=hue, fill=shade)
elif kind == 'both':
sns.histplot(data=data, x=col, bins=bins, color=np.random.choice(colors),
alpha=alpha, hue=hue, stat='density')
sns.kdeplot(data=data, x=col, color='darkred', alpha=0.7, hue=hue, fill=False)
plt.xlabel(col)
ax_num += 1
plt.subplots_adjust(hspace=subplots_adjust[0], wspace=subplots_adjust[1])
plt.savefig('化学成分分布图.jpg', dpi=300, bbox_inches='tight')
plt.show()
return True
except Exception as e:
log_message(f"创建分布图失败: {str(e)}")
return False
def load_and_process_data(file_path, sheet_name=0):
"""加载和处理数据"""
try:
# 检查文件是否存在
if not os.path.exists(file_path):
log_message(f"错误: 文件 '{file_path}' 不存在")
return None
# 读取数据
data = pd.read_excel(file_path, sheet_name=sheet_name)
log_message(f"成功加载数据, 共 {len(data)} 行")
# 列名修复
col_renames = {
'表面风化化': '表面风化',
'采采样点风化类型': '采样点风化类型',
'样点风化类型': '采样点风化类型',
'总成分': '总含量'
}
new_columns = []
for col in data.columns:
if col in col_renames:
new_columns.append(col_renames[col])
else:
new_columns.append(col)
data.columns = new_columns
# 化学成分列重命名
rename_dict = {
'氧化硅(Si)': '二氧化硅(SiO2)',
'氧化锡(SnO)': '氧化锡(SnO2)',
'氧化硫(SO3)': '二氧化硫(SO2)',
'氧化亚铜(Cu2O)': '氧化亚铜(Cu2O)',
'氧化铜(CuO)': '氧化铜(CuO)',
'三氧化二铁(Fe2O3)': '三氧化二铁(Fe2O3)'
}
data = data.rename(columns=rename_dict)
# 删除总含量列
if '总含量' in data.columns:
data = data.drop('总含量', axis=1)
log_message("已删除'总含量'列")
# 添加缺失列的处理
required_cols = ['表面风化', '采样点风化类型', '类型']
for col in required_cols:
if col not in data.columns:
data[col] = np.nan
log_message(f"警告: 列 '{col}' 不存在,已创建空白列")
# 移除空白行
data.dropna(how='all', inplace=True)
log_message(f"处理后数据行数: {len(data)}")
return data
except Exception as e:
log_message(f"数据处理失败: {str(e)}")
traceback.print_exc()
return None
def select_subclass_features(data):
"""亚类划分特征选择"""
try:
# 分离高钾和铅钡玻璃数据
gaojia_data = data[data['类型'] == '高钾'].copy()
qianbai_data = data[data['类型'] == '铅钡'].copy()
log_message(f"高钾玻璃数据量: {len(gaojia_data)}")
log_message(f"铅钡玻璃数据量: {len(qianbai_data)}")
# 获取化学成分列
chem_cols = [col for col in data.columns if any(x in col for x in ['氧化', '二氧化', '化学'])]
log_message(f"找到 {len(chem_cols)} 个化学成分列")
# 高钾玻璃的特征选择
log_message("\n==== 高钾玻璃特征选择 ====")
if len(gaojia_data) > 0:
gaojia_x = gaojia_data[chem_cols]
gaojia_y = gaojia_data['采样点风化类型']
# 处理缺失值
for col in chem_cols:
if gaojia_x[col].isna().any():
median_val = gaojia_x[col].median()
gaojia_x[col].fillna(median_val, inplace=True)
# 特征重要性分析
model = RandomForestClassifier(random_state=42)
parameters = {'max_depth': range(1, 5), 'min_samples_leaf': [1, 2],
'criterion': ['gini', 'entropy'], 'min_impurity_decrease': [0.01, 0.02]}
grid_search = GridSearchCV(model, parameters, cv=min(5, len(gaojia_data)), n_jobs=-1)
grid_search.fit(gaojia_x, gaojia_y)
log_message(f'高钾玻璃特征选择精度: {grid_search.best_score_:.4f}')
log_message(f'最优参数: {grid_search.best_params_}')
best_model = grid_search.best_estimator_
best_model.fit(gaojia_x, gaojia_y)
# 特征重要性排序
gaojia_fea_df = pd.DataFrame({
'化学成分': chem_cols,
'特征重要性': best_model.feature_importances_
}).sort_values('特征重要性', ascending=False)
log_message("\n高钾玻璃特征重要性排序:")
log_message(gaojia_fea_df.head(10).to_string())
else:
log_message("警告: 没有高钾玻璃数据,跳过特征选择")
gaojia_fea_df = pd.DataFrame({'化学成分': [], '特征重要性': []})
# 铅钡玻璃的特征选择
log_message("\n==== 铅钡玻璃特征选择 ====")
if len(qianbai_data) > 0:
qianbai_x = qianbai_data[chem_cols]
qianbai_y = qianbai_data['采样点风化类型']
# 处理缺失值
for col in chem_cols:
if qianbai_x[col].isna().any():
median_val = qianbai_x[col].median()
qianbai_x[col].fillna(median_val, inplace=True)
# 特征重要性分析
grid_search = GridSearchCV(RandomForestClassifier(random_state=42),
parameters,
cv=min(5, len(qianbai_data)),
n_jobs=-1)
grid_search.fit(qianbai_x, qianbai_y)
log_message(f'铅钡玻璃特征选择精度: {grid_search.best_score_:.4f}')
log_message(f'最优参数: {grid_search.best_params_}')
best_model = grid_search.best_estimator_
best_model.fit(qianbai_x, qianbai_y)
# 特征重要性排序
qianbai_fea_df = pd.DataFrame({
'化学成分': chem_cols,
'特征重要性': best_model.feature_importances_
}).sort_values('特征重要性', ascending=False)
log_message("\n铅钡玻璃特征重要性排序:")
log_message(qianbai_fea_df.head(10).to_string())
else:
log_message("警告: 没有铅钡玻璃数据,跳过特征选择")
qianbai_fea_df = pd.DataFrame({'化学成分': [], '特征重要性': []})
return gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols
except Exception as e:
log_message(f"特征选择失败: {str(e)}")
traceback.print_exc()
return None, None, None, None, None
def optimize_features_and_cluster(gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols):
"""特征优化和聚类分析"""
try:
# 高钾玻璃优化的聚类
log_message("\n==== 高钾玻璃优化聚类 ====")
if len(gaojia_data) > 0:
def evaluate_gaojia(pred):
score = 0
for perm in permutations([0, 1]):
true_labels = gaojia_data['采样点风化类型'].replace({'未风化点': perm[0], '风化点': perm[1]})
score_ = f1_score(true_labels, pred, average='weighted')
score = max(score, score_)
return score
gaojia_fea_list = gaojia_fea_df['化学成分'].tolist()
best_score = 0
best_features = []
deleted_features = []
# 特征优化
for num_features in range(1, min(15, len(gaojia_fea_list))):
current_features = gaojia_fea_list[:num_features].copy()
for feat in deleted_features:
if feat in current_features:
current_features.remove(feat)
if not current_features:
continue
log_message(f"尝试特征数: {num_features}, 特征: {current_features}")
# 数据标准化
X = gaojia_data[current_features].values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 聚类分析
kmeans = KMeans(n_clusters=2, random_state=42, n_init=10)
cluster_labels = kmeans.fit_predict(X_scaled)
# 评估聚类效果
score = evaluate_gaojia(cluster_labels)
log_message(f"聚类评估得分: {score:.4f}")
if score > best_score:
best_score = score
best_features = current_features.copy()
log_message(f"新最佳得分: {score:.4f},特征: {best_features}")
else:
last_feature = gaojia_fea_list[num_features - 1]
if last_feature not in deleted_features:
deleted_features.append(last_feature)
log_message(f"将特征 {last_feature} 添加到删除列表")
log_message(f"\n高钾玻璃最终选择的特征: {best_features}")
log_message(f"聚类评估得分: {best_score:.4f}")
# 最终聚类
if best_features:
X_final = gaojia_data[best_features].values
scaler_final = StandardScaler()
X_final_scaled = scaler_final.fit_transform(X_final)
kmeans_final = KMeans(n_clusters=2, random_state=42, n_init=10)
final_labels = kmeans_final.fit_predict(X_final_scaled)
gaojia_data['聚类标签'] = final_labels
# 保存聚类中心
cluster_centers = kmeans_final.cluster_centers_
gaojia_cluster_centers = pd.DataFrame(cluster_centers, columns=best_features)
gaojia_cluster_centers.index = ['亚类1', '亚类2']
else:
log_message("警告: 没有为高钾玻璃找到合适的聚类特征")
gaojia_cluster_centers = None
else:
log_message("没有高钾玻璃数据,跳过聚类")
gaojia_cluster_centers = None
best_features = []
# 铅钡玻璃优化的聚类
log_message("\n==== 铅钡玻璃优化聚类 ====")
if len(qianbai_data) > 0:
def evaluate_qianbai(pred):
score = 0
for perm in permutations([0, 1, 2]):
true_labels = qianbai_data['采样点风化类型'].replace({
'未风化点': perm[0],
'风化点': perm[1],
'严重风化点': perm[2]
})
score_ = f1_score(true_labels, pred, average='weighted')
score = max(score, score_)
return score
qianbai_fea_list = qianbai_fea_df['化学成分'].tolist()
best_score_qb = 0
best_features_qb = []
deleted_features_qb = []
# 特征优化
for num_features in range(1, min(15, len(qianbai_fea_list))):
current_features = qianbai_fea_list[:num_features].copy()
for feat in deleted_features_qb:
if feat in current_features:
current_features.remove(feat)
if not current_features:
continue
log_message(f"尝试特征数: {num_features}, 特征: {current_features}")
# 数据标准化
X = qianbai_data[current_features].values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 聚类分析
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
cluster_labels = kmeans.fit_predict(X_scaled)
# 评估聚类效果
score = evaluate_qianbai(cluster_labels)
log_message(f"聚类评估得分: {score:.4f}")
if score > best_score_qb:
best_score_qb = score
best_features_qb = current_features.copy()
log_message(f"新最佳得分: {score:.4f},特征: {best_features_qb}")
else:
last_feature = qianbai_fea_list[num_features - 1]
if last_feature not in deleted_features_qb:
deleted_features_qb.append(last_feature)
log_message(f"将特征 {last_feature} 添加到删除列表")
log_message(f"\n铅钡玻璃最终选择的特征: {best_features_qb}")
log_message(f"聚类评估得分: {best_score_qb:.4f}")
# 最终聚类
if best_features_qb:
X_final = qianbai_data[best_features_qb].values
scaler_final = StandardScaler()
X_final_scaled = scaler_final.fit_transform(X_final)
kmeans_final = KMeans(n_clusters=3, random_state=42, n_init=10)
final_labels = kmeans_final.fit_predict(X_final_scaled)
qianbai_data['聚类标签'] = final_labels
# 保存聚类中心
cluster_centers = kmeans_final.cluster_centers_
qianbai_cluster_centers = pd.DataFrame(cluster_centers, columns=best_features_qb)
qianbai_cluster_centers.index = ['亚类1', '亚类2', '亚类3']
else:
log_message("警告: 没有为铅钡玻璃找到合适的聚类特征")
qianbai_cluster_centers = None
else:
log_message("没有铅钡玻璃数据,跳过聚类")
qianbai_cluster_centers = None
best_features_qb = []
return gaojia_data, qianbai_data, best_features, best_features_qb, gaojia_cluster_centers, qianbai_cluster_centers
except Exception as e:
log_message(f"聚类优化失败: {str(e)}")
traceback.print_exc()
return None, None, [], [], None, None
def visualize_and_analyze_subclasses(gaojia_data, qianbai_data, gaojia_features, qianbai_features,
gaojia_cluster_centers, qianbai_cluster_centers):
"""亚类划分结果可视化与分析"""
try:
log_message("\n==== 亚类划分结果可视化与分析 ====")
# 高钾玻璃亚类划分可视化
if gaojia_data is not None and '聚类标签' in gaojia_data.columns:
plt.figure(figsize=(12, 8))
plt.suptitle("高钾玻璃亚类划分(基于聚类)")
# 3D散点图
ax1 = plt.subplot(121, projection='3d')
use_cols = gaojia_features[:3] if len(gaojia_features) >= 3 else gaojia_features
colors = get_colors('bright')
if use_cols:
for i in range(2): # 两个亚类
cluster_data = gaojia_data[gaojia_data['聚类标签'] == i]
label = f'亚类{i + 1}'
if len(use_cols) == 3:
ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]], cluster_data[use_cols[2]],
color=colors[i], label=label, s=50, alpha=0.7)
elif len(use_cols) == 2:
ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]],
np.zeros(len(cluster_data)),
color=colors[i], label=label, s=50, alpha=0.7)
else: # 只有1个特征
ax1.scatter(cluster_data[use_cols[0]],
np.zeros(len(cluster_data)),
np.zeros(len(cluster_data)),
color=colors[i], label=label, s=50, alpha=0.7)
if len(use_cols) >= 1: ax1.set_xlabel(use_cols[0])
if len(use_cols) >= 2: ax1.set_ylabel(use_cols[1])
if len(use_cols) >= 3: ax1.set_zlabel(use_cols[2])
ax1.legend()
else:
ax1.text(0.5, 0.5, "没有足够的特征进行可视化", ha='center', va='center')
# 箱线图比较亚类特征分布
ax2 = plt.subplot(122)
if gaojia_features:
box_data = gaojia_data.copy()
box_data['亚类'] = box_data['聚类标签'].apply(lambda x: f'亚类{x + 1}')
sns.boxplot(x='亚类', y=gaojia_features[0], data=box_data, palette=[colors[0], colors[1]])
plt.title(f'关键特征比较: {gaojia_features[0]}')
else:
ax2.text(0.5, 0.5, "没有可用特征", ha='center', va='center')
plt.tight_layout()
plt.savefig('高钾玻璃亚类划分结果.jpg', dpi=300)
plt.show()
else:
log_message("警告: 高钾玻璃聚类结果不可用,跳过可视化")
# 铅钡玻璃亚类划分可视化
if qianbai_data is not None and '聚类标签' in qianbai_data.columns:
plt.figure(figsize=(12, 8))
plt.suptitle("铅钡玻璃亚类划分(基于聚类)")
# 3D散点图
ax1 = plt.subplot(121, projection='3d')
use_cols = qianbai_features[:3] if len(qianbai_features) >= 3 else qianbai_features
colors = get_colors('bright')
if use_cols:
for i in range(3): # 三个亚类
cluster_data = qianbai_data[qianbai_data['聚类标签'] == i]
label = f'亚类{i + 1}'
if len(use_cols) == 3:
ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]], cluster_data[use_cols[2]],
color=colors[i], label=label, s=50, alpha=0.7)
elif len(use_cols) == 2:
ax1.scatter(cluster_data[use_cols[0]], cluster_data[use_cols[1]],
np.zeros(len(cluster_data)),
color=colors[i], label=label, s=50, alpha=0.7)
else: # 只有1个特征
ax1.scatter(cluster_data[use_cols[0]],
np.zeros(len(cluster_data)),
np.zeros(len(cluster_data)),
color=colors[i], label=label, s=50, alpha=0.7)
if len(use_cols) >= 1: ax1.set_xlabel(use_cols[0])
if len(use_cols) >= 2: ax1.set_ylabel(use_cols[1])
if len(use_cols) >= 3: ax1.set_zlabel(use_cols[2])
ax1.legend()
else:
ax1.text(0.5, 0.5, "没有足够的特征进行可视化", ha='center', va='center')
# 箱线图比较亚类特征分布
ax2 = plt.subplot(122)
if qianbai_features:
box_data = qianbai_data.copy()
box_data['亚类'] = box_data['聚类标签'].apply(lambda x: f'亚类{x + 1}')
sns.boxplot(x='亚类', y=qianbai_features[0], data=box_data, palette=colors[:3])
plt.title(f'关键特征比较: {qianbai_features[0]}')
else:
ax2.text(0.5, 0.5, "没有可用特征", ha='center', va='center')
plt.tight_layout()
plt.savefig('铅钡玻璃亚类划分结果.jpg', dpi=300)
plt.show()
else:
log_message("警告: 铅钡玻璃聚类结果不可用,跳过可视化")
# 合理性分析 - ANOVA检验特征显著差异
log_message("\n==== 合理性分析 - 亚类特征差异检验 ====")
# 高钾玻璃
if gaojia_data is not None and '聚类标签' in gaojia_data.columns and gaojia_features:
log_message("\n高钾玻璃:")
for i, feature in enumerate(gaojia_features[:3]):
try:
groups = [gaojia_data[gaojia_data['聚类标签'] == j][feature] for j in range(2)]
f_val, p_val = f_oneway(*groups)
log_message(f"{feature}: F值={f_val:.4f}, p值={p_val:.4f}{' (显著)' if p_val < 0.05 else ''}")
except Exception as e:
log_message(f"无法计算特征 {feature} 的ANOVA检验: {str(e)}")
# 铅钡玻璃
if qianbai_data is not None and '聚类标签' in qianbai_data.columns and qianbai_features:
log_message("\n铅钡玻璃:")
for i, feature in enumerate(qianbai_features[:3]):
try:
groups = [qianbai_data[qianbai_data['聚类标签'] == j][feature] for j in range(3)]
f_val, p_val = f_oneway(*groups)
log_message(f"{feature}: F值={f_val:.4f}, p值={p_val:.4f}{' (显著)' if p_val < 0.05 else ''}")
except Exception as e:
log_message(f"无法计算特征 {feature} 的ANOVA检验: {str(e)}")
# 保存聚类中心
try:
if gaojia_cluster_centers is not None:
gaojia_cluster_centers.to_excel("高钾玻璃亚类聚类中心.xlsx")
log_message("高钾玻璃聚类中心已保存")
if qianbai_cluster_centers is not None:
qianbai_cluster_centers.to_excel("铅钡玻璃亚类聚类中心.xlsx")
log_message("铅钡玻璃聚类中心已保存")
except Exception as e:
log_message(f"保存聚类中心失败: {str(e)}")
return gaojia_data, qianbai_data
except Exception as e:
log_message(f"可视化与分析失败: {str(e)}")
traceback.print_exc()
return None, None
def predict_unknown_samples(unknown_data, gaojia_model, qianbai_model, gaojia_features, qianbai_features):
"""对未知样本进行预测"""
try:
log_message("\n==== 对未知样本进行预测 ====")
if unknown_data is None or len(unknown_data) == 0:
log_message("错误: 未知样本数据无效")
return None
# 分离高钾和铅钡玻璃数据
unknown_gaojia = unknown_data[unknown_data['类型'] == '高钾'].copy()
unknown_qianbai = unknown_data[unknown_data['类型'] == '铅钡'].copy()
# 高钾玻璃预测
if not unknown_gaojia.empty and gaojia_model is not None:
# 特征选择
features = [f for f in gaojia_features if f in unknown_gaojia.columns]
if features:
X = unknown_gaojia[features].values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 预测
cluster_labels = gaojia_model.predict(X_scaled)
unknown_gaojia['预测亚类'] = cluster_labels
log_message(f"高钾玻璃未知样本预测完成,共 {len(unknown_gaojia)} 个样本")
log_message("预测结果示例:")
log_message(unknown_gaojia[['文物编号', '预测亚类']].head().to_string())
# 保存结果
unknown_gaojia.to_excel("高钾玻璃未知样本预测结果.xlsx", index=False)
# 铅钡玻璃预测
if not unknown_qianbai.empty and qianbai_model is not None:
# 特征选择
features = [f for f in qianbai_features if f in unknown_qianbai.columns]
if features:
X = unknown_qianbai[features].values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 预测
cluster_labels = qianbai_model.predict(X_scaled)
unknown_qianbai['预测亚类'] = cluster_labels
log_message(f"铅钡玻璃未知样本预测完成,共 {len(unknown_qianbai)} 个样本")
log_message("预测结果示例:")
log_message(unknown_qianbai[['文物编号', '预测亚类']].head().to_string())
# 保存结果
unknown_qianbai.to_excel("铅钡玻璃未知样本预测结果.xlsx", index=False)
return pd.concat([unknown_gaojia, unknown_qianbai], ignore_index=True)
except Exception as e:
log_message(f"未知样本预测失败: {str(e)}")
return None
def main():
"""主函数"""
try:
# 文件路径
file_path = r"D:\BianChen\python_studycode\tf_env\玻璃\分析结果.xlsx"
log_message(f"开始执行分析,数据文件: {file_path}")
# 1. 加载和处理训练数据
log_message("\n==== 步骤1: 数据加载与预处理 ====")
data = load_and_process_data(file_path, sheet_name=0)
if data is None or len(data) == 0:
log_message("错误: 数据处理失败或没有有效数据,程序终止")
return
# 初始数据可视化
log_message("\n执行初始数据可视化...")
plt.figure(figsize=(8, 6))
sns.countplot(x='类型', data=data, palette='Set2')
plt.title('玻璃类型分布')
plt.savefig('玻璃类型分布.jpg', dpi=300)
plt.show()
# 2. 亚类划分的特征选择
log_message("\n==== 步骤2: 亚类划分特征选择 ====")
gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols = select_subclass_features(data)
if gaojia_fea_df is not None and not gaojia_fea_df.empty:
gaojia_fea_df.to_excel("高钾玻璃特征重要性.xlsx", index=False)
log_message("高钾玻璃特征重要性已保存")
if qianbai_fea_df is not None and not qianbai_fea_df.empty:
qianbai_fea_df.to_excel("铅钡玻璃特征重要性.xlsx", index=False)
log_message("铅钡玻璃特征重要性已保存")
# 3. 聚类和优化特征选择
log_message("\n==== 步骤3: 特征优化与亚类聚类 ====")
(gaojia_with_subclasses, qianbai_with_subclasses,
gaojia_features, qianbai_features,
gaojia_centers, qianbai_centers) = optimize_features_and_cluster(
gaojia_data, qianbai_data, gaojia_fea_df, qianbai_fea_df, chem_cols
)
log_message(f"高钾玻璃最终使用特征: {gaojia_features}")
log_message(f"铅钡玻璃最终使用特征: {qianbai_features}")
# 4. 亚类划分的可视化与分析
log_message("\n==== 步骤4: 亚类划分可视化与分析 ====")
gaojia_final, qianbai_final = visualize_and_analyze_subclasses(
gaojia_with_subclasses, qianbai_with_subclasses,
gaojia_features, qianbai_features,
gaojia_centers, qianbai_centers
)
# 5. 保存最终结果
log_message("\n==== 步骤5: 保存结果 ====")
try:
if gaojia_final is not None and not gaojia_final.empty:
gaojia_final.to_excel("高钾玻璃亚类划分结果.xlsx", index=False)
log_message("高钾玻璃亚类划分结果已保存")
if qianbai_final is not None and not qianbai_final.empty:
qianbai_final.to_excel("铅钡玻璃亚类划分结果.xlsx", index=False)
log_message("铅钡玻璃亚类划分结果已保存")
except Exception as e:
log_message(f"保存最终结果失败: {str(e)}")
# 6. 加载并处理未知数据(表单3)
log_message("\n==== 步骤6: 加载并处理未知数据(表单3) ====")
unknown_file_path = r"D:\Users\86157\Desktop\数学建模\附件.xlsx"
unknown_data = load_and_process_data(unknown_file_path, sheet_name='表单3')
if unknown_data is not None:
log_message(f"成功加载表单3数据,共 {len(unknown_data)} 行")
# 7. 对未知样本进行预测
log_message("\n==== 步骤7: 对未知样本进行预测 ====")
# 准备模型
gaojia_model = KMeans(n_clusters=2, random_state=42).fit(gaojia_final[gaojia_features])
qianbai_model = KMeans(n_clusters=3, random_state=42).fit(qianbai_final[qianbai_features])
# 执行预测
predict_unknown_samples(unknown_data, gaojia_model, qianbai_model,
gaojia_features, qianbai_features)
else:
log_message("无法加载表单3的数据")
log_message("\n亚类划分分析完成!")
except Exception as e:
log_message(f"程序执行出错: {str(e)}")
traceback.print_exc()
if __name__ == "__main__":
main()
```
阅读全文
相关推荐


















