用R语言做ROC曲线,解决横纵坐标轴重叠的问题

文章介绍了在使用R语言绘制ROC曲线时遇到横纵坐标轴不重叠的问题,提供了两种解决方案。方案一是通过调整RStudio图像显示区域的大小来临时解决视觉效果,而方案二是通过手动设置plot函数参数,确保输出图像的横纵坐标轴间距一致。这两种方法都可以帮助用户改善ROC曲线的显示效果。

用R语言做ROC曲线,横纵坐标轴不重叠,如下图所示

使用的代码如下:

plot(roc10,  
     print.auc=TRUE, 
     print.auc.x=0.2, print.auc.y=0.6,print.auc.cex=0.7,
     auc.polygon=T,
     auc.polygon.col="white", 
     grid= FALSE, 
     legacy.axes=T) 

以下是解决这种问题的两种方案

方案一:继续使用上述代码。但是plot.roc()函数会自动调整坐标轴范围和标尺,使得曲线和AUC值适应于绘图区域,然后导致横坐标轴和纵坐标轴的间距不同,所以最简单的方法就是调整R Studio右下角展示图片位置的那个框的大小,平时不是占右下1/4大小,调成占1/2大小,它的横坐标轴和纵坐标轴的间距就相同啦(可以自行调节,使横纵坐标轴的间距相同),但是export输出的结果还是不同的,所以可以调整好位置后截图保存。

方案二:更换代码。如下

plot(1-roc1$specificities,roc1$sensitivities,
type="l",col="red",lty=1,xlab = "1-Specificity",
ylab = "Sensitivities",lwd=2)

plot函数是手动设置的横纵坐标轴标签,所以间距是相同的,这种方法的输出结果间距也是相同的,不用截图保存。

希望这个回答可以帮助到你。

如果有疑问可以评论或私信。

共同学习,共同进步

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, confusion_matrix, roc_curve from sklearn.preprocessing import LabelEncoder, OneHotEncoder from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline import shap import warnings warnings.filterwarnings('ignore') # 设置中文显示 plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] plt.rcParams['axes.unicode_minus'] = False # 1. 数据加载与预处理 def load_and_preprocess(disease): if disease == "stroke": df = pd.read_csv("stroke.csv") # 特征选择 features = ['age', 'hypertension', 'heart_disease', 'avg_glucose_level', 'bmi', 'smoking_status'] target = 'stroke' # 处理缺失值 df['bmi'].fillna(df['bmi'].median(), inplace=True) # 分类变量编码 cat_features = ['smoking_status'] elif disease == "heart": df = pd.read_csv("heart.csv") features = ['Age', 'ChestPainType', 'Cholesterol', 'MaxHR', 'ExerciseAngina', 'ST_Slope'] target = 'HeartDisease' # 处理缺失值 df['Cholesterol'].replace(0, df['Cholesterol'].median(), inplace=True) cat_features = ['ChestPainType', 'ExerciseAngina', 'ST_Slope'] elif disease == "cirrhosis": df = pd.read_csv("cirrhosis.csv") features = ['Bilirubin', 'Albumin', 'Prothrombin', 'Edema', 'Stage', 'Platelets'] target = 'Status' # 假设Status中'D'表示患病(需根据实际数据调整) # 处理缺失值 for col in features: if df[col].dtype == 'float64': df[col].fillna(df[col].median(), inplace=True) else: df[col].fillna(df[col].mode()[0], inplace=True) # 目标变量处理(将状态转为二分类:患病=1,否则=0) df[target] = df[target].apply(lambda x: 1 if x == 'D' else 0) cat_features = ['Edema', 'Stage'] # 划分特征与目标 X = df[features] y = df[target] # 编码分类特征 preprocessor = ColumnTransformer( transformers=[('cat', OneHotEncoder(drop='first'), cat_features)], remainder='passthrough' ) X_processed = preprocessor.fit_transform(X) # 划分训练集与测试集 X_train, X_test, y_train, y_test = train_test_split(X_processed, y, test_size=0.2, random_state=42) return X_train, X_test, y_train, y_test, preprocessor, features # 2. 训练随机森林模型 def train_rf(X_train, y_train): model = RandomForestClassifier(n_estimators=100, max_depth=8, random_state=42) model.fit(X_train, y_train) return model # 3. 模型评估 def evaluate_model(model, X_test, y_test, disease): y_pred = model.predict(X_test) y_prob = model.predict_proba(X_test)[:, 1] # 评估指标 metrics = { '准确率': accuracy_score(y_test, y_pred), '精确率': precision_score(y_test, y_pred), '召回率': recall_score(y_test, y_pred), 'F1分数': f1_score(y_test, y_pred), 'AUC': roc_auc_score(y_test, y_prob) } print(f"\n{disease}模型评估指标:") for k, v in metrics.items(): print(f"{k}: {v:.4f}") # 混淆矩阵可视化 cm = confusion_matrix(y_test, y_pred) plt.figure(figsize=(6, 4)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['未患病', '患病'], yticklabels=['未患病', '患病']) plt.xlabel('预测标签') plt.ylabel('真实标签') plt.title(f'{disease}模型混淆矩阵') plt.show() # ROC曲线 fpr, tpr, _ = roc_curve(y_test, y_prob) plt.figure(figsize=(6, 4)) plt.plot(fpr, tpr, label=f'AUC = {metrics["AUC"]:.4f}') plt.plot([0, 1], [0, 1], 'k--') plt.xlabel('假阳性率') plt.ylabel('真阳性率') plt.title(f'{disease}模型ROC曲线') plt.legend() plt.show() return y_pred, y_prob # 4. SHAP灵敏度分析 import matplotlib.pyplot as plt import numpy as np import shap def shap_analysis(model, X_train, X_test, features, disease, preprocessor): # 提取特征名称(处理编码后的特征) # 注意:确保preprocessor是已拟合的,且X_test是预处理后的数据 cat_features = [f for f in features if f in preprocessor.transformers_[0][2]] num_features = [f for f in features if f not in cat_features] ohe = preprocessor.named_transformers_['cat'] cat_names = ohe.get_feature_names_out(cat_features) # 独热编码后的特征名 feature_names = list(cat_names) + num_features # 合并类别特征和数值特征名 # SHAP值计算(关键修正:处理分类模型的多类别结构) explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) # 分类模型需指定目标类别(如二分类取正类,多分类按需选择) # 若模型是回归模型,shap_values是二维数组,无需此步骤 if isinstance(shap_values, list): # 分类模型返回列表(每个元素对应一个类别) # 假设关注第一个类别(可根据实际需求调整索引,如二分类常用1表示正类) target_class = 1 if len(shap_values) == 2 else 0 # 示例逻辑,按需修改 shap_values = shap_values[target_class] # 验证特征维度匹配(避免因预处理导致特征数不一致) assert X_test.shape[1] == len(feature_names), \ f"特征维度不匹配:X_test有{X_test.shape[1]}列,feature_names有{len(feature_names)}个名称" # 摘要图(全局特征重要性) plt.figure(figsize=(10, 6)) # 修正:明确传递特征名,并确保shap_values维度为(n_samples, n_features) shap.summary_plot(shap_values, X_test, feature_names=feature_names, plot_type="bar") plt.title(f'{disease}模型SHAP特征重要性') plt.tight_layout() # 防止标签重叠导致显示不全 plt.show() # 计算前3个最敏感特征 shap_sum = np.abs(shap_values).mean(0) # 各特征SHAP绝对值的均值 top3_idx = np.argsort(shap_sum)[-3:] # 取重要性最大的3个特征索引(升序排序后取最后3个) assert np.issubdtype(top3_idx.dtype, np.integer), "Indices must be integers" top3_idx = np.array(top3_idx, dtype=int).flatten() top3_features = [feature_names[i] for i in top3_idx[::-1]] # 反转索引以按重要性降序排列 print(f"{disease}模型最敏感的3个因素(降序):{top3_features}") return top3_features ##def shap_analysis(model, X_train, X_test, features, disease, preprocessor): ## # 提取特征名称(处理编码后的特征) ## cat_features = [f for f in features if f in preprocessor.transformers_[0][2]] ## num_features = [f for f in features if f not in cat_features] ## ohe = preprocessor.named_transformers_['cat'] ## cat_names = ohe.get_feature_names_out(cat_features) ## feature_names = list(cat_names) + num_features ## ## # SHAP值计算 ## explainer = shap.TreeExplainer(model) ## shap_values = explainer.shap_values(X_test) ## ## # 摘要图(全局特征重要性) ## plt.figure(figsize=(10, 6)) ## shap.summary_plot(shap_values, X_test, feature_names=feature_names, plot_type="bar") ## plt.title(f'{disease}模型SHAP特征重要性') ## plt.show() ## ## # 前3个最敏感特征 ## shap_sum = np.abs(shap_values).mean(0) ## assert np.issubdtype(top3_idx.dtype, np.integer), "Indices must be integers" ## top3_idx = np.array(top3_idx, dtype=int).flatten() ## top3_features = [feature_names[i] for i in top3_idx] ## print(f"{disease}模型最敏感的3个因素:{top3_features}") ## ## return top3_features # 5. 主函数 def main(): diseases = ["stroke", "heart", "cirrhosis"] results = {} for disease in diseases: print(f"\n===== {disease}预测模型 =====") X_train, X_test, y_train, y_test, preprocessor, features = load_and_preprocess(disease) model = train_rf(X_train, y_train) y_pred, y_prob = evaluate_model(model, X_test, y_test, disease) top3 = shap_analysis(model, X_train, X_test, features, disease, preprocessor) # 保存预测结果(示例:前10个样本) results[disease] = { '预测值(前10)': y_pred[:10], '预测概率(前10)': y_prob[:10], '最敏感因素': top3 } return results if __name__ == "__main__": results = main() 解释以上代码为何在绘制SHAP摘要图时,有横纵坐标但是除坐标外图中没有任何图,折线,并给出对相应代码的改进措施以及修正修改过后的代码
最新发布
07-17
### 解决R语言绘制ROC曲线横坐标倒置的问题 在R语言中,当遇到绘制ROC曲线横坐标出现倒置的情况,通常是因为数据集标签或预测概率的方向设置不正确。为了修正这一问题,可以调整`ROCR`包或其他绘图工具中的参数配置。 #### 使用 `ROCR` 包绘制 ROC 曲线并修复横坐标方向 下面是一个具体的解决方案: ```r library(ROCR) # 假设 pred_prob 是模型输出的概率向量, labels 是真实的类别标签 (0 或 1) pred <- prediction(pred_prob, labels) # 绘制原始的ROC曲线 perf <- performance(pred, "tpr", "fpr") plot(perf, main="Original ROC Curve") # 如果发现FPR轴(即X轴)显示错误,则可以通过反转输入来解决问题 rev_pred <- prediction(rev(pred_prob), rev(labels)) # 再次计算性能指标,并重新绘制图形 rev_perf <- performance(rev_pred, "tpr", "fpr") plot(rev_perf, col="red", add=TRUE) # 添加红色线条表示修正后的结果 legend("bottomright", legend=c("Original","Reversed"), fill=c("black","red")) ``` 上述代码展示了如何利用`prediction()`函数创建预测对象以及使用`performance()`获取TPR和FPR值用于绘图。如果初次尝试后发现横坐标的顺序不对,那么就应当考虑调用`rev()`函数对预测概率和实际标签进行反序排列后再执行相同的操作[^1]。 另外一种可能是由于某些特定情况下默认设定不符合预期;此时应该查阅所使用的库文档查看是否有专门针对此情况的选项可调节。对于`pROC`这样的其他流行包来说,可能只需要简单修改参数即可实现正常展示。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值