
从常见数据分析方法到可视化一份完整的 R 语言实战代码手册一、数据准备与描述性统计可视化直方图 密度曲线二、分组对比箱线图与统计检验可视化箱线图叠加抖动点三、相关分析与线性回归可视化散点图 回归线 置信带四、二分类建模Logistic 回归与 ROC 曲线预测与 ROC 曲线在上一篇文章中我们讨论了 R 语言数据整理的基本操作。这次我们把视角往前推一步拿到一份数据后如何根据分析目的选择合适的方法并用 ggplot2 把结果讲清楚。一、数据准备与描述性统计任何分析的第一步都是了解数据的分布形态和集中趋势。我们使用 tidyverse 生态完成数据导入、缺失值概览和描述统计。# 加载核心包library(tidyverse)library(readr)library(magrittr)library(dplyr)library(ggplot2)# 模拟一份健康调查数据实际使用时替换为 read_csv(your_data.csv)set.seed(42)df-tibble(id1:200,agernorm(200,mean45,sd15),bmirnorm(200,mean24,sd4),gendersample(c(Male,Female),200,replaceTRUE),educationsample(c(Low,Medium,High),200,replaceTRUE),outcomerbinom(200,1,plogis(-20.03*age0.1*bmi))# 二分类结局)%%mutate(ageifelse(age18,18,age))# 简单清理描述统计不用一上来就 summary() 了事。对于连续变量我们关心均值、标准差、中位数和四分位距对于分类变量频数分布才是重点。# 连续变量均值与标准差df%%summarise(mean_agemean(age,na.rmTRUE),sd_agesd(age,na.rmTRUE),median_bmimedian(bmi,na.rmTRUE),iqr_bmiIQR(bmi,na.rmTRUE))# 分类变量频数与比例df%%count(education)%%mutate(propn/sum(n))结果# A tibble: 1 x 4mean_age sd_age median_bmi iqr_bmidbldbldbldbl144.914.023.95.36# A tibble: 3 x 3education n propchrintdbl1High620.312Low640.323Medium740.37可视化直方图 密度曲线直方图用于看分布形态叠加密度曲线可以辅助判断偏态。binwidth 的选择比默认值更能反映数据结构。ggplot(df,aes(xage))geom_histogram(aes(yafter_stat(density)),binwidth5,fill#2E86AB,colorwhite,alpha0.8)geom_density(linewidth1,color#A23B72)labs(title年龄分布,x年龄,y密度)theme_minimal(base_size14)图上分布接近对称、无明显双峰或极端偏态因此后续用均值 ± 标准差描述、用 t 检验/线性回归等基于正态假设的方法是合理的。如果这图明显右偏比如收入分布就应该改报中位数和四分位距或考虑对数变换。二、分组对比箱线图与统计检验我们以性别分组比较 BMI 的分布差异。# 分组描述统计df%%group_by(gender)%%summarise(mean_bmimean(bmi,na.rmTRUE),sd_bmisd(bmi,na.rmTRUE),nn())# 独立样本 t 检验若方差不齐可使用 var.equal FALSEt.test(bmi~gender,datadf)结果# A tibble: 2 x 4gender mean_bmi sd_bmi nchrdbldblint1Female23.73.67952Male24.33.88105Welch Two Sample t-test data:bmi by gender t-1.1558,df197.59,p-value0.2492alternative hypothesis:true differenceinmeans between group Female and group Male is not equal to095percent confidence interval:-1.67178550.4362989sample estimates:meaningroup Female meaningroup Male23.7208224.33856可视化箱线图叠加抖动点ggplot(df,aes(xgender,ybmi,fillgender))geom_boxplot(width0.4,alpha0.6,outlier.shapeNA)geom_jitter(width0.1,alpha0.4,size1.8)labs(titleBMI 的性别差异,x性别,yBMI)theme_bw(base_size14)theme(legend.positionnone)如果分组超过两组比如教育水平三组把 t.test 换成 aov() 做方差分析箱线图的 x 映射到分类变量即可。若数据严重偏态或方差不齐可改用 Kruskal-Wallis 检验kruskal.test箱线图依然适用因为它展示的是中位数和四分位距对分布假设不敏感。三、相关分析与线性回归当两个连续变量之间存在关联时散点图加拟合线是最直接的呈现方式。相关系数给出方向与强度回归模型给出可解释的系数。# 相关系数Pearsoncor.test(df$age,df$bmi,usecomplete.obs)# 简单线性回归model_lm-lm(bmi~age,datadf)summary(model_lm)结果Call:lm(formulabmi~age,datadf)Residuals:Min1Q Median3Q Max-10.5287-2.5595-0.30342.47889.7228Coefficients:Estimate Std. Error t value Pr(|t|)(Intercept)25.061070.8999727.8472e-16***age-0.022650.01916-1.1820.238---Signif. codes:0‘***’0.001‘**’0.01‘*’0.05‘.’0.1‘ ’1Residual standard error:3.785on198degrees of freedom Multiple R-squared:0.007011,Adjusted R-squared:0.001996F-statistic:1.398on1and198DF,p-value:0.2385summary() 输出中重点看三处Estimate效应大小、Pr(|t|)显著性、Multiple R-squared解释比例。如果 R² 很低比如 0.05说明年龄只能解释 BMI 变异的 5%即使 p 值显著实际意义也有限。可视化散点图 回归线 置信带ggplot(df,aes(xage,ybmi))geom_point(alpha0.5,color#2E86AB,size2)geom_smooth(methodlm,seTRUE,color#A23B72,fillgrey70)labs(title年龄与 BMI 的线性关系,subtitlepaste(R² ,round(summary(model_lm)$r.squared,3)),x年龄,yBMI)theme_minimal(base_size14)四、二分类建模Logistic 回归与 ROC 曲线当结局是“是/否”类型的二分类变量时线性回归不再适用应使用 Logistic 回归。# 拟合 Logistic 回归model_glm-glm(outcome~agebmigender,datadf,familybinomial)summary(model_glm)# 将系数转换为优势比ORexp(coef(model_glm))结果Call:glm(formulaoutcome~agebmigender,familybinomial,datadf)Deviance Residuals:Min1Q Median3Q Max-2.21930.42520.52890.62580.8543Coefficients:Estimate Std. Error z value Pr(|z|)(Intercept)-1.428461.57470-0.9070.3643age0.020580.014791.3910.1641bmi0.094230.056931.6550.0979. genderMale0.075700.401230.1890.8504---Signif. codes:0‘***’0.001‘**’0.01‘*’0.05‘.’0.1‘ ’1(Dispersion parameterforbinomial family taken to be1)Null deviance:169.08on199degrees of freedom Residual deviance:164.67on196degrees of freedom AIC:172.67Number of Fisher Scoring iterations:4exp(coef) 是 Logistic 回归中最实用的输出。比如 age 的 OR 为 1.03表示年龄每增加一岁结局发生的优势增加约 3%。注意 OR 不等于风险比。预测与 ROC 曲线library(pROC)# 预测概率df$pred_prob-predict(model_glm,typeresponse)# 绘制 ROC 曲线并计算 AUCroc_obj-roc(df$outcome,df$pred_prob)auc_value-auc(roc_obj)plot(roc_obj,col#2E86AB,lwd2,mainpaste(ROC 曲线 (AUC ,round(auc_value,3),)))abline(a0,b1,lty2,colgrey60)AUC 在 0.5 到 1 之间0.7 以上通常认为模型有一定区分能力。如果 AUC 接近 0.5说明当前预测变量几乎没有区分力需要重新审视特征选择混淆矩阵用 caret 包可以快速得到准确率、敏感度、特异度library(caret)df$pred_class-factor(ifelse(df$pred_prob0.5,1,0),levelsc(0,1))confusionMatrix(df$pred_class,factor(df$outcome,levelsc(0,1)))Confusion Matrix and Statistics Reference Prediction01000130170Accuracy:0.8595% CI:(0.7928,0.8965)No Information Rate:0.85P-Value[AccNIR]:0.5485Kappa:0Mcnemars Test P-Value:1.192e-07Sensitivity:0.00Specificity:1.00Pos Pred Value:NaNNeg Pred Value:0.85Prevalence:0.15Detection Rate:0.00Detection Prevalence:0.00Balanced Accuracy:0.50PositiveClass:0准确率 85%但 NIR 也是 0.85、Kappa 0。这是一个经典的“无效模型”案例提醒我们面对倾斜的类分布盲目相信 Accuracy 会导致严重的误判。