
只是做一个记录后续还会修改这个代码来使用。20260318import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import StandardScaler, MinMaxScaler from sklearn.model_selection import train_test_split, cross_val_score from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import r2_score, silhouette_score, davies_bouldin_score, classification_report, confusion_matrix from sklearn.decomposition import PCA import warnings warnings.filterwarnings(ignore) # 设置中文显示 plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, DejaVu Sans] plt.rcParams[axes.unicode_minus] False # 1. 数据加载和预处理 def load_and_prepare_data(file_path): 加载数据并准备特征 # 加载数据 data pd.read_csv(file_path) print(原始数据形状:, data.shape) print(\n前5行数据:) print(data.head()) # 选择需要的特征 features [评论, 收藏, 转发] # 检查特征是否存在 missing_features [f for f in features if f not in data.columns] if missing_features: print(f警告: 数据中缺少以下特征: {missing_features}) # 尝试使用可能的列名 possible_features { 评论: [评论数, 评论量, 评论数, comments, comment], 收藏: [收藏数, 收藏量, favorites, favorite], 转发: [转发数, 转发量, 转发次数, shares, share, reposts] } for missing in missing_features: for possible in possible_features[missing]: if possible in data.columns: features[features.index(missing)] possible print(f使用 {possible} 替代 {missing}) break # 提取特征 X data[features].copy() print(f\n使用的特征: {list(X.columns)}) # 数据清洗 print(f\n数据清洗前 - 缺失值数量:) print(X.isnull().sum()) # 填充缺失值如果有 X X.fillna(X.median()) # 检查0值 print(f\n0值统计:) for col in X.columns: zero_count (X[col] 0).sum() zero_percentage (zero_count / len(X)) * 100 print(f{col}: {zero_count}个0值 ({zero_percentage:.2f}%)) # 数据探索 print(f\n数据统计描述:) print(X.describe()) return data, X, features # 2. 数据标准化 def standardize_data(X): 标准化数据 # 由于数据中有0值使用StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X) # 检查标准化后的数据 X_scaled_df pd.DataFrame(X_scaled, columnsX.columns) print(\n标准化后的数据统计:) print(X_scaled_df.describe()) return X_scaled, scaler # 3. 聚类分析无监督方法 def perform_clustering(X_scaled, n_clusters3): 使用多种聚类算法 clustering_results {} # 1. KMeans聚类 kmeans KMeans(n_clustersn_clusters, random_state42, n_init10) kmeans_labels kmeans.fit_predict(X_scaled) clustering_results[KMeans] { model: kmeans, labels: kmeans_labels, centers: kmeans.cluster_centers_ } # 2. 层次聚类 hierarchical AgglomerativeClustering(n_clustersn_clusters) hierarchical_labels hierarchical.fit_predict(X_scaled) clustering_results[Hierarchical] { model: hierarchical, labels: hierarchical_labels } # 3. DBSCAN聚类自动确定簇数 dbscan DBSCAN(eps0.5, min_samples5) dbscan_labels dbscan.fit_predict(X_scaled) clustering_results[DBSCAN] { model: dbscan, labels: dbscan_labels } return clustering_results # 4. 评估聚类结果 def evaluate_clustering(X_scaled, clustering_results): 评估不同聚类算法的效果 evaluation {} for name, result in clustering_results.items(): labels result[labels] # 跳过DBSCAN的噪声点标签为-1 if name DBSCAN: valid_mask labels ! -1 if sum(valid_mask) 0: X_valid X_scaled[valid_mask] labels_valid labels[valid_mask] if len(np.unique(labels_valid)) 1: silhouette silhouette_score(X_valid, labels_valid) db_index davies_bouldin_score(X_valid, labels_valid) else: silhouette -1 db_index 10 else: silhouette -1 db_index 10 else: silhouette silhouette_score(X_scaled, labels) db_index davies_bouldin_score(X_scaled, labels) n_clusters len(np.unique(labels[labels ! -1])) if name DBSCAN else len(np.unique(labels)) evaluation[name] { 轮廓系数: silhouette, DB指数: db_index, 簇数: n_clusters } return evaluation # 5. 分类算法如果有标签 def perform_classification(X, y, algorithmsNone): 使用多种分类算法 if algorithms is None: algorithms { 随机森林: RandomForestClassifier(n_estimators100, random_state42), 梯度提升: GradientBoostingClassifier(random_state42), K近邻: KNeighborsClassifier(n_neighbors5), 逻辑回归: LogisticRegression(max_iter1000, random_state42), SVM: SVC(kernelrbf, probabilityTrue, random_state42) } # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) # 标准化特征 scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) results {} for name, model in algorithms.items(): # 训练模型 model.fit(X_train_scaled, y_train) # 预测 y_pred model.predict(X_test_scaled) y_pred_train model.predict(X_train_scaled) # 计算R²分数 r2_test r2_score(y_test, y_pred) r2_train r2_score(y_train, y_pred_train) # 交叉验证R² cv_scores cross_val_score(model, X_train_scaled, y_train, cv5, scoringr2) results[name] { 模型: model, 测试集R²: r2_test, 训练集R²: r2_train, 交叉验证R²均值: np.mean(cv_scores), 交叉验证R²标准差: np.std(cv_scores), 预测值: y_pred, 真实值: y_test } print(f\n{name}:) print(f 测试集R²: {r2_test:.4f}) print(f 训练集R²: {r2_train:.4f}) print(f 交叉验证R²: {np.mean(cv_scores):.4f} (±{np.std(cv_scores):.4f})) return results, (X_train_scaled, X_test_scaled, y_train, y_test) # 6. 可视化函数 def visualize_results(data, X, X_scaled, clustering_results, classification_resultsNone): 可视化结果 # 1. 原始数据分布 fig, axes plt.subplots(2, 3, figsize(15, 10)) # 原始数据分布 for i, col in enumerate(X.columns): axes[0, i].hist(X[col], bins30, alpha0.7, colorskyblue, edgecolorblack) axes[0, i].set_title(f{col}分布) axes[0, i].set_xlabel(值) axes[0, i].set_ylabel(频数) # 2. 特征相关性 correlation X.corr() im axes[1, 0].imshow(correlation, cmapcoolwarm, vmin-1, vmax1) axes[1, 0].set_title(特征相关性热图) axes[1, 0].set_xticks(range(len(X.columns))) axes[1, 0].set_yticks(range(len(X.columns))) axes[1, 0].set_xticklabels(X.columns, rotation45) axes[1, 0].set_yticklabels(X.columns) plt.colorbar(im, axaxes[1, 0]) # 3. 三维散点图如果使用聚类 if clustering_results: from mpl_toolkits.mplot3d import Axes3D # 使用KMeans结果 labels clustering_results.get(KMeans, {}).get(labels, None) if labels is not None: # 使用PCA降维到2D用于可视化 pca PCA(n_components2) X_pca pca.fit_transform(X_scaled) axes[1, 1].scatter(X_pca[:, 0], X_pca[:, 1], clabels, cmapviridis, alpha0.6) axes[1, 1].set_title(KMeans聚类结果 (PCA降维)) axes[1, 1].set_xlabel(主成分1) axes[1, 1].set_ylabel(主成分2) # 4. 各算法R²比较如果有分类结果 if classification_results: ax axes[1, 2] algorithms list(classification_results.keys()) r2_scores [classification_results[alg][测试集R²] for alg in algorithms] bars ax.bar(algorithms, r2_scores, color[skyblue, lightgreen, lightcoral, gold, violet]) ax.set_title(各分类算法R²分数比较) ax.set_ylabel(R²分数) ax.set_ylim(0, 1) ax.set_xticklabels(algorithms, rotation45, haright) # 在柱子上添加数值 for bar, score in zip(bars, r2_scores): height bar.get_height() ax.text(bar.get_x() bar.get_width()/2., height 0.01, f{score:.3f}, hacenter, vabottom, fontsize9) plt.tight_layout() plt.show() # 5. 聚类中心可视化 if KMeans in clustering_results: kmeans_result clustering_results[KMeans] centers kmeans_result[centers] fig, axes plt.subplots(1, 3, figsize(15, 4)) # 对每个特征显示聚类中心 for i, col in enumerate(X.columns): cluster_means centers[:, i] axes[i].bar(range(len(cluster_means)), cluster_means, color[red, green, blue][:len(cluster_means)]) axes[i].set_title(f{col} - 聚类中心值) axes[i].set_xlabel(聚类) axes[i].set_ylabel(标准化值) axes[i].set_xticks(range(len(cluster_means))) axes[i].set_xticklabels([f聚类{j} for j in range(len(cluster_means))]) plt.tight_layout() plt.show() # 7. 生成最终结果报告 def generate_report(data, X, clustering_eval, classification_resultsNone): 生成分析报告 print( * 60) print(新闻热度分析报告) print( * 60) print(f\n1. 数据概况:) print(f 样本数量: {len(data)}) print(f 特征数量: {len(X.columns)}) print(f 使用的特征: {list(X.columns)}) print(f\n2. 数据统计:) for col in X.columns: print(f {col}: 均值{X[col].mean():.2f}, 中位数{X[col].median():.2f}, f最小值{X[col].min():.2f}, 最大值{X[col].max():.2f}) print(f\n3. 聚类算法评估:) for algo, metrics in clustering_eval.items(): print(f {algo}:) print(f 轮廓系数: {metrics[轮廓系数]:.4f} (越大越好-1到1)) print(f DB指数: {metrics[DB指数]:.4f} (越小越好)) print(f 簇数: {metrics[簇数]}) if classification_results: print(f\n4. 分类算法R²分数比较:) # 按测试集R²排序 sorted_results sorted(classification_results.items(), keylambda x: x[1][测试集R²], reverseTrue) for name, result in sorted_results: print(f {name}:) print(f 测试集R²: {result[测试集R²]:.4f}) print(f 训练集R²: {result[训练集R²]:.4f}) print(f 交叉验证R²: {result[交叉验证R²均值]:.4f} (±{result[交叉验证R²标准差]:.4f})) # 推荐最佳算法 best_algo sorted_results[0][0] print(f\n5. 推荐算法: {best_algo}) print(f 理由: 在测试集上获得最高的R²分数 ({classification_results[best_algo][测试集R²]:.4f})) print(f\n6. 建议:) print(f - 如果数据量较大且特征间有复杂关系推荐使用随机森林或梯度提升) print(f - 如果数据量较小推荐使用逻辑回归或K近邻) print(f - 如果追求可解释性推荐使用逻辑回归) print(f - 如果追求最高准确率推荐使用梯度提升) # 8. 主函数 def main(): 主函数 # 请替换为您的数据文件路径 file_path news_data.csv # 请修改为您的文件路径 try: # 1. 加载和准备数据 print(步骤1: 加载和准备数据) data, X, features load_and_prepare_data(file_path) # 2. 标准化数据 print(\n步骤2: 标准化数据) X_scaled, scaler standardize_data(X) # 3. 聚类分析 print(\n步骤3: 进行聚类分析) clustering_results perform_clustering(X_scaled, n_clusters3) # 4. 评估聚类 print(\n步骤4: 评估聚类结果) clustering_evaluation evaluate_clustering(X_scaled, clustering_results) # 5. 使用KMeans聚类结果作为伪标签进行分类算法比较 print(\n步骤5: 基于聚类结果进行分类算法比较) # 使用KMeans聚类结果作为标签 kmeans_labels clustering_results[KMeans][labels] # 映射标签到热度等级 (假设0:低, 1:中, 2:高) # 可以根据聚类中心的值调整映射 centers clustering_results[KMeans][centers] # 计算每个聚类的平均得分 cluster_scores [] for i in range(centers.shape[0]): # 对三个特征取平均值作为热度得分 score centers[i].mean() cluster_scores.append((i, score)) # 按得分排序确定热度等级 cluster_scores.sort(keylambda x: x[1]) label_mapping {} for rank, (cluster_idx, _) in enumerate(cluster_scores): label_mapping[cluster_idx] rank # 0:低, 1:中, 2:高 y np.array([label_mapping[label] for label in kmeans_labels]) # 检查标签分布 unique, counts np.unique(y, return_countsTrue) print(f\n热度等级分布:) for level, count in zip(unique, counts): level_name {0: 低, 1: 中, 2: 高}[level] percentage (count / len(y)) * 100 print(f 热度{level_name}: {count}条 ({percentage:.1f}%)) # 6. 使用多种分类算法 print(\n步骤6: 使用多种分类算法) classification_results, split_data perform_classification(X_scaled, y) # 7. 可视化结果 print(\n步骤7: 生成可视化结果) visualize_results(data, X, X_scaled, clustering_results, classification_results) # 8. 生成报告 print(\n步骤8: 生成分析报告) generate_report(data, X, clustering_evaluation, classification_results) # 9. 保存结果 print(\n步骤9: 保存结果) data[热度等级] y data[热度等级名称] data[热度等级].map({0: 低, 1: 中, 2: 高}) # 保存到新文件 output_file news_with_heat_level.csv data.to_csv(output_file, indexFalse, encodingutf-8-sig) print(f结果已保存到: {output_file}) # 显示前几条结果 print(f\n前10条新闻的热度等级:) result_sample data[[标题] features [热度等级名称]].head(10) print(result_sample.to_string(indexFalse)) except FileNotFoundError: print(f错误: 找不到文件 {file_path}) print(请确保文件路径正确或者使用以下示例数据:) # 创建示例数据 np.random.seed(42) n_samples 100 # 生成示例数据 example_data pd.DataFrame({ 标题: [f新闻{i1} for i in range(n_samples)], 评论: np.random.poisson(50, n_samples) np.random.randint(0, 20, n_samples), 收藏: np.random.poisson(30, n_samples) np.random.randint(0, 15, n_samples), 转发: np.random.poisson(20, n_samples) np.random.randint(0, 10, n_samples) }) # 添加一些异常值 example_data.loc[0:5, 评论] [200, 180, 160, 0, 0, 5] example_data.loc[0:5, 收藏] [100, 90, 80, 0, 0, 3] example_data.loc[0:5, 转发] [80, 70, 60, 0, 0, 2] # 保存示例数据 example_data.to_csv(example_news_data.csv, indexFalse, encodingutf-8-sig) print(f已生成示例数据: example_news_data.csv) print(请修改代码中的文件路径为 example_news_data.csv 并重新运行) # 运行主函数 if __name__ __main__: main()