
简介西交大《R语言初学者指南》配套教材电子书与分章代码包面向刚接触统计建模与数据可视化的R语言初学者。压缩包共十个文件包含一本教材电子书和九个按章节整理的R脚本整体大小约16MB便于离线阅读与逐个运行练习。目前已有三百零九人学习下载。书中系统讲解R语言基础语法、数据结构、数据读写、描述性统计、假设检验、线性回归、主成分分析以及ggplot2绘图的图层语法、主题定制、包管理与R Markdown报告生成代码文件与章节一一对应可随时复制到RStudio中验证结果。整包内容将理论讲解与动手操作结合起来适合希望系统入门R语言并积累可复用代码的学习者亦可作为课程实训的配套参考资料尤其适合想要快速上手统计分析的数据分析入门者。1. 拿到《R语言初学者指南》PDF和书本代码别再只翻PDF去跑代码某高校课程资料里流传的《R语言初学者指南》PDF和配套书本代码很多初学者下载后就躺在硬盘里吃灰。问题几乎一模一样打开PDF每一行命令似乎都看得懂但等到自己把代码敲进RStudio报错比正文还多。原因并不是书编得不好而是这份资源的核心价值在配套的代码文件里不在PDF本身——数据路径、依赖包、画图参数这些“隐形知识”都在代码里。这篇笔记把这份PDF和书本代码当成一个完整单元按“资源结构→环境配置→跟跑案例→踩坑排查→改造成自己的模板”的顺序展开适合零基础入门R也适合书读了半本却跑不通例子的学习者。2. 拆解《R语言初学者指南》的资源结构PDF里没写全的东西都在代码里2.1 为什么照书敲代码总报错排版、包加载与数据路径三个“隐性断层”先把这个“黑匣子”打开。一本书从作者写下源码到变成你屏幕上的PDF中间要经过排版、转码、压缩最终呈现在PDF里的代码片段往往和原始可运行脚本并不一致。最常见的是换行位置变了一句很长的代码在PDF里被折成两行你抄的时候少抄了一个右括号更常见的是引号被排版成中文弯引号R根本不认。所以真正权威的版本从来不是PDF那一页而是配套代码文件里按章节组织的.R脚本。我帮A同学排查过一次他盯着PDF第3章里的五行代码敲了一个小时一直报错我把配套代码文件打开给他看才发现PDF里漏掉了开头两行library()——书里为了排版紧凑把依赖包加载统一放在章节开头而不是每个例子前面初学者单跑一段就拿不到依赖包。这只是第一层断层。第二层是包加载断层很多入门书的配套脚本会在章节顶部统一加载所有包但PDF正文里为了节省版面常常不在每个示例处重复这些语句。你单独抄PDF上的某一段执行自然报错。第三层是数据路径断层脚本里写read.csv(data/example.csv)这是相对路径只有当你把工作目录切到代码解压的根目录时才有效。很多同学是新建一个空白R脚本粘贴代码工作目录还是默认的“我的文档”那这条路径就等于不存在。理解了这三层断层再去拆解这份资源就明白该先看什么、后看什么。如果你手头只有PDF没有代码文件最稳妥的办法是去书籍附录或作者主页找源码包但如果这份资源本身就是“PDF书本代码”的组合那么请把.R脚本当成唯一能运行的事实标准。PDF可以是阅读线索代码文件才是运行依据。这个认知转变之后学习流程会顺畅很多也省掉了将来对着PDF一遍遍抄代码的后悔药。2.2 解压后先做一次资源盘点目录结构、数据文件和运行顺序这类入门书的代码包常见组织方式是“章节脚本 数据文件 图形输出”三个部分。我的做法是解压后先不改任何文件把目录结构完整看一遍别急着双击运行。在RStudio里跑几行基础命令先把家底盘清楚# 第一遍体检先把工作目录切到代码解压根目录 setwd(D:/learnR/r4guide) # 路径换成你自己的解压目录 getwd() # 确认切换成功 dir() # 查看根目录下有哪些文件和文件夹 # 目录层级较多时递归列出全部文件 list.files(recursive TRUE)setwd()里用的是正斜杠Windows路径复制过来是反斜杠R里要手动改成正斜杠或双反斜杠这是最常见的初学问题。dir()只列当前目录一层看不到子目录内容这时候用list.files(recursive TRUE)递归展开才能看到数据到底放在哪个文件夹。目录看明白后我一般会做一张“用途对照表”不需要记下来但心里要有数。常见文件类型与用途如下表。文件或目录常见命名在资源包里的用途章节脚本ch02_basics.R、chapter3_plot.R对应PDF某章的完整可运行代码数据文件data/、datasets/ 下的 .csv .txt案例自带数据脚本用相对路径读取图形输出目录figures/、output/运行脚本后生成的图写入此处运行说明README.txt、requirements.R写明依赖的R包、版本和运行顺序注意不要用记事本双击打开.R文件也不要在浏览器里当文本看。R脚本要用RStudio或支持UTF-8的编辑器打开源码里的中文注释在Windows记事本里常常显示成乱码但那个乱码不影响运行真正影响运行的是文件编码本身。盘点的下一步是找运行说明。如果压缩包里有README.txt先读它里面通常写了依赖的R包、推荐的运行顺序和注意事项。读取说明并顺手检查数据目录是否存在# 查看是否存在 README并读取前 30 行 if (file.exists(README.txt)) { readLines(README.txt, n 30) } # 检查几个关键目录是否存在 dir.exists(data) dir.exists(figures)file.exists()和dir.exists()返回逻辑值TRUE说明路径存在FALSE说明路径缺失。运行前做这两项检查可以避免脚本跑到一半才报“目录不存在”。还要提醒一句不要一次性选中整个文件夹里的所有.R脚本全部运行目录里不同章节脚本之间可能有公共变量名互相覆盖也可能有顺序依赖。运行方式是“按章节逐个打开、逐个运行”而不是一把梭。2.3 用 RStudio Project 代替反复改路径一次建立目录关联我在帮人排查时发现一个很普遍的习惯每天打开RStudio第一件事就是把书里代码的路径手动改一遍改成自己电脑上的位置第二天换了一台电脑又改一遍。这非常消耗耐心而且极易改错。正确做法是把解压后的整个文件夹当作一个RStudio项目来管理。如果代码包里自带.Rproj文件直接用RStudio的File → Open Project打开如果没有也可以自己新建一个项目在新建时选择“Existing Directory”并指向这个代码目录。项目方式最大的好处是工作目录从此固定在代码包根目录每次打开RStudio都不用重新setwd()。用RStudio的Existing Directory创建项目比新建目录再把文件复制进去更安全因为复制文件经常漏掉隐藏数据文件或子目录。如果你还在学习阶段、频繁切换不同课程的代码包我建议脚本开头保留一行显式的setwd()更容易定位问题# 脚本开头统一设置工作目录只改这一处即可 main_dir - D:/learnR/r4guide setwd(main_dir) # 后面读取数据统一使用相对路径 dat - read.csv(data/example.csv)把路径集中放在脚本头部比藏在每个read.csv()里更利于维护。换电脑或者换目录时只改main_dir这一行。永远不要在别人的脚本里看到setwd()就顺手删掉删掉之后后面的相对路径全部失效——这是一次血泪教训。另外如果你经常忘记之前把代码解压到哪里可以运行history()查看RStudio的历史命令八成能找到当时的setwd()记录这比翻文件夹快得多。3. 跑通书本代码前的一次性配置工作目录、包依赖与文件编码对齐3.1 先确认基础环境R版本、包安装路径和依赖包是否齐全开始跑书上的代码之前不需要急着一口气装二十个包但三件事必须确认当前R版本不要太老入门代码在R 4.x下通常都能跑关键依赖包确实装上了工作目录正确。这三个问题如果混在一起新手往往把环境问题和代码问题搅成一团最后连错在哪一行都找不到。先执行一段环境体检脚本把问题暴露在代码里而不是“猜”# 环境体检看版本、看包安装位置、看工作目录 R.version.string # 输出当前R版本 .libPaths() # 包被安装到哪个目录 getwd() # 当前工作目录 # 一次性检查多个包是否可用 need_pkgs - c(ggplot2, dplyr, readr, tidyr) for (p in need_pkgs) { cat(p, :, requireNamespace(p, quietly TRUE), \n) }R.version.string返回的字符串比R.version列表更直观一眼能看清大版本。requireNamespace()和library()的区别在于它只检查包是否存在并返回一个逻辑值不会真的把包加载进当前环境非常适合做“体检”。如果某个包显示FALSE就需要安装。安装时我建议先用chooseCRANmirror()手动挑一个合适的镜像再执行安装否则可能出现下载慢或者长时间卡住# 安装常用的数据处理与绘图包 install.packages(c(ggplot2, dplyr, readr, tidyr))依赖包之间有版本关联这是第5章第5节要展开的坑这里先记住一个原则安装阶段只要“装上”不要追求“最新”。能跑通入门书代码的通常是稳定版。另外不要把install.packages()写进要反复运行的脚本里——包已经装好时它每次都会检查网络浪费时间更合理的做法是单独运行一次安装命令脚本里只保留library()调用。3.2 工作目录的两种打开方式显式 setwd 与 RStudio Project这里把工作目录这个问题再讲透一点因为它值得。入门阶段最不容易出错的方案是“脚本开头显式指定工作目录”原因有两个一是你可以在RStudio之外、在命令行里用Rscript直接运行脚本而不迷路二是当你同时学两三门统计课程时每个脚本开头是哪份资料、对应哪个目录一目了然。另一种方案是把整个代码目录作为RStudio Project打开。两者的本质差别在于setwd()是“脚本级别”的约定它写死在代码里Project是“会话级别”的约定由RStudio记住打开项目时自动设置。如果你切换项目频繁Project更稳但如果你经常使用source()调用多个脚本脚本里又没有setwd()很容易出现“到处找不到文件”的情况。下面是两种写法的对比# 方式一适合跟着书一篇篇跑脚本独立性强 setwd(D:/learnR/r4guide) # 方式二适合长期维护自己的分析项目运行时自动定位到脚本所在目录 if (interactive() requireNamespace(rstudioapi, quietly TRUE)) { setwd(dirname(rstudioapi::getSourceEditorContext()$path)) }方式二有一个前提必须在RStudio里交互式执行且当前有一个已打开的脚本。getSourceEditorContext()$path拿到的是当前打开脚本的完整路径再用dirname()去掉文件名得到脚本所在目录。这样无论这个文件夹被移动到哪个位置运行都能定位。但它不能脱离RStudio使用在Rscript命令行模式下会报错所以我用interactive()做了保护。个人建议学习这本书期间用方式一简单直接等你开始拿R处理自己的课题再切换到Project或方式二。从命令行运行整章脚本时还有一个容易忽略的坑Rscript ch02_basics.R不会自动加载library()之外的任何包而且不会打开交互式图形窗口。如果你在脚本里画了图但没写png()保存用Rscript运行时图会直接消失连报错都没有。所以我用Rscript做整章脚本验证时会刻意把图形输出部分改成保存到文件。这个习惯帮我抓出过很多“看起来能跑、实际没输出”的假运行。3.3 文件编码read.csv 读不出数据的头号元凶运行脚本过程中第一道真正意义上的“坎”往往不是统计模型而是read.csv()读文件。Windows环境下最典型的翻车场景是read.csv(data/example.csv)读进来全是乱码或者直接报“incomplete final line found by readTableHeader”。原因不在代码而在文件的字符编码。Windows记事本保存CSV时默认使用ANSI/GBK编码而配套脚本和数据文件常常以UTF-8编码保存R在读取时又不会自动侦测编码于是两边对不上。解决方式不是打开Excel手动另存为那样会改掉字段类型、日期格式甚至引入不可见字符。正确的做法是在读取时显式指定编码参数# 读取数据时的稳健写法 dat - read.csv( data/example.csv, fileEncoding UTF-8, # 乱码时改成 GBK 或 GB2312 再试 stringsAsFactors FALSE, # 不把字符列自动变成因子 check.names TRUE # 列名里的非法字符自动替换 ) str(dat) # 读进来第一件事看结构无条件fileEncoding指定源文件编码R按照这个参数去解码。stringsAsFactors FALSE非常关键早期R版本默认把字符串列转成因子很多入门书里的代码基于旧默认值写的你现在不关掉后面做mutate()或字符匹配时会得到莫名奇妙的结果。check.names TRUE会把列名里的空格、括号替换成合法字符防止后续$取列时报错。读入后我坚持先执行str(dat)而不是head(dat)因为str()能同时告诉你数据框的行数列数、每列的类型和因子水平这些信息决定了下一步代码该怎么写。编码问题还有一个隐藏变体UTF-8 BOM头。某些编辑器在保存UTF-8文件时会自动在文件开头加三个不可见字节R读入后第一列列名会变成ï..列名或者X.U.FEFF.列名。遇到这种名字用colnames(dat)看一眼如果第一列带着奇怪前缀要么用编辑器把文件另存为“无BOM的UTF-8”要么在read.csv()里设置check.names FALSE先读进来再用names(dat)手动改掉第一列列名。这属于典型的“看代码看不出来、必须看数据”的坑排查效率比反复改代码高得多。4. 跟跑书上的“完整分析”从读数据、看结构到出图的一条龙操作4.1 先用R内置数据验证环境通了再碰外部数据很多人拿到脚本就全选、运行然后面对满屏红色报错手足无措。我的习惯相反先跑一个最简单的、只依赖R内置数据集的例子确认环境本身没有毛病再把问题缩小到路径和编码。内置数据最大的好处是开箱即用不涉及文件读取排除了90%的路径和编码变量。比如运行以下代码# 用 R 自带数据验证基础绘图环境是否正常 data(iris) # 加载内置鸢尾花数据集 plot(iris[, 1:4], col iris$Species)如果这一句能弹出一张带三种颜色散点的图形窗口说明R、图形设备和基础绘图函数都正常。如果完全没有反应不要继续往下跑外部数据脚本先检查图形设备或重启RStudio。plot()接收一个数据框时会自动生成散点图矩阵col iris$Species把三种鸢尾花显示成三种颜色。这一步是纯验证不写文件所以不需要dev.off()。如果连plot()都没有反应最可能的原因是图形设备没启动或RStudio的图形窗口被关闭。交互式环境下用dev.new()强制开一个新窗口再画一次如果是通过命令行跑脚本则必须用png()保存否则图根本无处显示。这个判断顺序能帮你区分“代码错了”和“环境没显示”避免在错误层上反复纠结。4.2 跑通“读入—概览—回归—出图”的经典四段式入门书里出现频率最高的套路可以概括成四段式读数据、看结构、做统计、出图。我把这套流程用iris完整跑一遍方便你把书里某个具体章节的代码对照进这个框架里。先看概览和统计部分# 数据概览任何分析的第一步都是看清楚数据 str(iris) # 结构行数列数、每列类型 summary(iris) # 数值列的五数概括与均值 # 简单线性回归用花瓣长度预测花瓣宽度 fit - lm(Petal.Width ~ Petal.Length, data iris) summary(fit)lm()的第一个参数是公式左边的Petal.Width是响应变量右边的Petal.Length是解释变量。summary()给出的Estimate是回归系数Pr(|t|)是显著性检验的p值入门阶段先看这两列就够了。str()和summary()看起来都是“看数据”但一个看结构一个看分布前者回答“这列是什么类型”后者回答“这列数值范围多大、有没有异常”。四段式里还可以插入分组对比这是入门书描述统计章节的常客# 分组箱线图看不同类别之间数值分布差异 boxplot(Petal.Length ~ Species, data iris, col c(lightblue, lightgreen, lightpink), ylab Petal Length) # 两组均值差异检验 sub - iris[iris$Species ! setosa, ] t.test(Petal.Length ~ Species, data sub)boxplot()的公式写法Petal.Length ~ Species表示“按Species分组画Petal.Length的箱线图”col是三个分组的填充色向量长度必须和分组数一致。t.test()同样用公式接口sub只保留两种鸢尾花检验两组均值是否有显著差异。这组代码覆盖了“分组描述”和“差异检验”两个常见需求很多书本案例就是把它们和前面的回归拼在一起。接下来是绘图部分。入门书这里的坑最多因为绘图涉及图形设备、画布尺寸、中文字体几个变量# 输出一张高分辨率PNG图打开设备、绘图、关闭设备 png(figures/iris_fit.png, width 6, height 4, units in, res 300) plot(iris$Petal.Length, iris$Petal.Width, cex 1.2, pch 16, col steelblue, xlab Petal Length, ylab Petal Width) abline(fit, col darkred, lwd 2) dev.off()这里逐个说清参数png()的第一个参数是输出文件路径路径里包含了figures/目录运行前要确保这个目录存在否则会报错width6, height4, unitsin指定画布尺寸是6英寸宽、4英寸高单位也可以改成cmres300是分辨率300dpi适合打印屏幕阅读用150足够。plot()函数里cex 1.2控制点和文字的整体放大倍数pch 16把点形设为实心圆点col steelblue设置点的颜色xlab和ylab是坐标轴标签。abline(fit)在散点图上叠加一条回归直线lwd 2是线宽。最后一行dev.off()关闭图形设备这一步漏了图片文件就会一直是空的——新手翻车的高频位置。再补充一个实用习惯如果书上用par(mfrowc(1,2))它表示把画布分成一行两列可以并排画两张图。这个参数放在par()里全局生效会影响之后的所有绘图直到重新设置。很多初学者画出两张图叠在一起就是因为没注意这个参数没有“自动恢复”功能。用完记得用par(mfrowc(1,1))还原。4.3 把书里的一次性脚本改造成可复用函数跑通流程之后我建议做一次“抽象”把四段式流程包装成一个函数。直接好处是明天换成你自己的数据不再需要翻开书重新复制代码只需要调用这个函数并指定列名。这一步是将“看懂别人的代码”变成“写出自己的代码”的分水岭。quick_reg_plot - function(dat, x, y, out_file NULL) { fit - lm(reformulate(x, y), data dat) if (!is.null(out_file)) { png(out_file, width 6, height 4, units in, res 300) } plot(dat[[x]], dat[[y]], cex 1.2, pch 16, xlab x, ylab y) abline(fit, col darkred, lwd 2) if (!is.null(out_file)) dev.off() fit } # 调用方式示例 fit - quick_reg_plot(iris, Petal.Length, Petal.Width)reformulate(x, y)的作用是把两个字符串拼成程序可用的公式对象等价于as.formula(Petal.Width ~ Petal.Length)但更简洁。dat[[x]]用变量名取列比dat$x更灵活因为x在函数参数里。out_file留给调用者决定是否输出到文件传NULL时只在屏幕上显示不产生文件这对调试阶段很友好。函数返回fit对象调用者可以继续用summary(fit)、coef(fit)提取系数而不是只得到一张图这才是模板的意义。5. 跑《R语言初学者指南》代码的 5 个常见坑与排查顺序5.1 could not find function包没加载还是函数名变了现象照着脚本逐行执行执行到某一行弹出could not find function geom_smooth但明明书里就是这么写的。原因主要有两种一是脚本开头的library()没有被执行到比如你只运行了画图那一段漏掉了前面的加载语句二是R包更新后某个函数被挪到另一个包或改了名字。排查时先执行library(ggplot2)再重新运行如果仍然找不到用find(geom_smooth)查看这个函数存在于哪个包、当前是否可用。解决把脚本顶部所有library()统一执行一遍若是包版本问题进入第5.5节处理。5.2 cannot open file路径和解压目录对不上现象运行read.csv(data/example.csv)报错cannot open file data/example.csv: No such file or directory。原因当前工作目录不在代码解压的根目录。很多初学者在RStudio里直接双击打开脚本文件但RStudio在“打开脚本”时并不会自动把工作目录切到脚本所在位置工作目录仍然是默认目录。解决先运行getwd()看当前路径再用setwd()切到代码包根目录然后重跑。不要在每个读取语句里写绝对路径否则换电脑后要改几十处。这个问题的排查优先级应该排在所有“代码报错”之前因为路径错后面全白搭。5.3 读入的中文全变乱码编码不匹配不要用Excel抢救现象read.csv()读进来之后列名和字符列全部变成“涓、、乱码”一类。原因CSV文件本身是GBK编码R按UTF-8解析或者反过来。解决把fileEncoding参数从UTF-8改成GBK再不行试GB2312如果你用readr包read_csv()内部会做更聪明的编码猜测但依然不是万能。最需要记住的是不要用Excel打开CSV再另存为xlsx那个操作会改动字段类型和日期格式属于用一个新的坑去填补旧坑。编码问题应该放在数据读取阶段一次性解决不要拖到画图阶段再处理后面的麻烦会成倍增加。5.4 图不弹出来或图片文件空白图形设备打开和关闭必须成对现象运行plot()没有任何反应或者写了png()后文件生成但打不开、打开是空的。原因最典型的是用png()打开设备之后忘记dev.off()后续绘图内容全部写进那个还开着的设备里文件一直处于未完成状态另一种是脚本在非交互模式下运行窗口一闪而过画的内容没被保存。解决写脚本时养成成对使用图形设备的习惯png()、pdf()等打开设备的函数必须以dev.off()结束。交互式查看图时用dev.new()开新窗口画完直接关闭窗口即可不需要dev.off()。如果怀疑设备状态异常用dev.list()查看当前还有哪些图形设备开着再逐层dev.off()关掉。5.5 包装了仍然报错版本不兼容优先改代码而不是改环境现象install.packages(ggplot2)显示安装成功但运行书上代码时提示某个参数不存在、某个函数已被移除。原因R包版本更新很快一本书从写作到出版通常经历两三个大版本书中代码基于旧版本写就参数接口和函数名很可能发生变化。解决先运行sessionInfo()查看当前环境中的R和包版本再去该包帮助文档查新接口。如果确实是新版本不兼容可以用remotes::install_version()安装书上对应的历史版本但不要为了这一本书把整套包环境全部降级那会让你的R环境长期停留在旧状态以后学新东西又要再折腾。取舍标准能用一行代码改写搞定绝不降级包只有当你确实需要复现书中某个经典案例的原始输出时才考虑锁定版本。6. 把这本指南变成你自己的模板库一个验证学习效果的习惯6.1 选三章做数据替换实验验证你是否真的吸收了《R语言初学者指南》这本书不是把脚本背下来而是把书里的数据全部换成自己的数据。我建议只选三章第一章是数据导入把自己手头的一个CSV按书上的步骤读进来跑一遍结构检查第二章是描述统计对你自己数据的数值列依次计算summary()、分组统计和相关系数第三章是绘图把书里的散点图模板、箱线图模板改成你自己数据的变量出两到三张图。三轮做完这本书对你来说就不再是一份待读PDF而是一套你亲手改过、能运行、能改参数的脚本库。到这个状态书本代码才算真正归你所有。6.2 记录每次改动一个参数一提交的土办法我最后想分享一个看似笨拙但极其有效的小技巧运行书本代码时一次只改一个参数。比如把cex从1.0改成1.2就重新输出一张图对比两张图后决定保留哪个不要同时改颜色、点型、边距和字体否则图坏了你根本不知道是哪个参数导致的。保存脚本时在修改行上方留一行注释写清楚“这里改了什么为什么改”这个习惯比任何书签都好用也让你三个月后再看代码时能想起当初为什么折腾。我以前也喜欢把PDF从头翻到尾后来发现真正学到手里的是某一次把书中某章代码改成自己数据时的那场折腾而不是阅读本身。希望帮到你。本文还有配套的精品资源点击获取