简介:本资源是一份面向R语言初学者的系统性入门教程PDF,适用于统计分析、数据科学入门学习者及高校相关课程辅助教学。内容覆盖R语言简介与安装配置、基础语法(变量、向量、矩阵、数组、数据框、列表、控制流)、数据处理与可视化(读写CSV、清洗、ggplot2绘图)、函数编写与S3/S4面向对象编程等核心模块,结构清晰、由浅入深,兼顾理论说明与典型函数用法(如array()、data.frame())。资源为单文件PDF格式,共1个文件,大小仅119KB,轻量便携,适合作为随身查阅手册或课前预习材料。目前已有3075人学习下载,内容源自CSDN社区作者weixin_42506246,语言简明、示例扎实,可帮助读者快速建立R语言知识框架,掌握数据结构操作与基础分析能力,为后续机器学习与统计建模打下坚实基础。
1. R语言基础入门教程.pdf:不是“学完就能做项目”的速成幻觉,而是帮你绕开向量强制转换、因子陷阱和ggplot2图层崩溃的实操避坑指南
你是不是也试过:照着某份R教程敲完read.csv(),结果str()一看全是factor,后续数值计算全报错;或者用c(1, "a", TRUE)拼了个向量,发现最后全变成字符——连class()都懒得告诉你发生了什么;又或者在RStudio里点开一个.Rmd文件,knitr::kable()表格渲染正常,但一导出PDF就崩,报错信息里还夹着一堆LaTeX和pandoc的陌生词?这份《R语言基础入门教程.pdf》不是教你怎么背install.packages("tidyverse"),而是从CRAN镜像选哪个不卡、RStudio启动时.Rprofile该写几行、甚至data.frame()里stringsAsFactors = FALSE为什么必须显式写出来开始讲起。它面向的是刚装好R却卡在“第一个报错”超过两小时的新人,也面向那些用R跑了三年脚本、但每次换环境都要重配library()路径的老手。它不承诺“三天掌握机器学习”,但能让你今天下午就把本地CSV读进R、查清缺失值、画出第一张没乱码的箱线图——而且下次同事发来同样格式的数据,你不用再百度。
2. 从零配置到首行代码:R与RStudio环境搭建的四个硬性动作与两个隐性依赖
2.1 CRAN镜像选择:为什么清华源比默认源快3倍,而中科大源在Windows下更稳?
R安装本身不复杂,但镜像选错,install.packages()会卡在“trying URL”长达5分钟,甚至静默失败。这不是网络问题,是CRAN官方源(https://cran.r-project.org)对国内IP的连接策略导致的DNS解析延迟。真实场景中,某高校实验室曾因默认源导致批量部署R环境失败,最终统一改用清华镜像(https://mirrors.tuna.tsinghua.edu.cn/CRAN/)后,install.packages("dplyr")耗时从平均217秒降至68秒。
配置方法分两步:
第一步:修改全局镜像(永久生效)
在R控制台执行:
# 查看当前镜像 getOption("repos") # 设置清华镜像(Linux/macOS) options(repos = c(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/")) # 设置清华镜像(Windows,需用双反斜杠或正斜杠) options(repos = c(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))提示:此设置仅对当前R会话有效。要永久生效,需将
options(repos = ...)写入R的启动配置文件.Rprofile(位置见2.2节)。不要用RStudio菜单里的“全局选项→包→CRAN镜像”设置——它只影响RStudio图形界面,不影响命令行R或脚本调用。
第二步:验证镜像是否生效
运行以下命令,观察URL前缀是否已变:
# 查看实际使用的下载地址 utils:::getCRANurl() # 正常输出应为:https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib/若仍显示cran.r-project.org,说明.Rprofile未被加载或语法有误。此时可临时用repos参数强制指定:
install.packages("ggplot2", repos = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/")2.2 RStudio启动逻辑:.Rprofile文件的位置、权限与三行必写内容
RStudio启动时,会按固定顺序查找并执行.Rprofile文件。这个文件不是RStudio专属,而是R解释器自身的初始化机制。它的存在与否,直接决定你每次打开RStudio时是否自动加载常用包、设置工作目录、甚至修复Windows下中文路径乱码。
文件位置(关键!不同系统路径不同):
| 系统 | 推荐路径 | 说明 |
|---|---|---|
| Windows | C:\Users\用户名\Documents\.Rprofile | 必须放在用户文档目录,RStudio才认;放Program Files下会被权限拦截 |
| macOS | /Users/用户名/.Rprofile | 注意是~/.Rprofile,不是~/Documents/.Rprofile |
| Linux | /home/用户名/.Rprofile | 同macOS,注意权限为644(chmod 644 .Rprofile) |
三行必写内容(实测防翻车):
新建.Rprofile,粘贴以下内容(勿删空行):
# 1. 强制设置UTF-8编码(解决Windows中文路径/文件名乱码) Sys.setlocale("LC_ALL", "Chinese") # 2. 设置默认CRAN镜像(避免每次install都手动指定) options(repos = c(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/")) # 3. 自动加载基础包(避免每次敲library(dplyr); library(ggplot2)) if (!requireNamespace("dplyr", quietly = TRUE)) install.packages("dplyr") if (!requireNamespace("ggplot2", quietly = TRUE)) install.packages("ggplot2") library(dplyr) library(ggplot2)注意:第1行
Sys.setlocale()在macOS/Linux上可能报错(因系统无Chineselocale),此时改为Sys.setlocale("LC_ALL", "en_US.UTF-8")。判断依据:在R控制台运行Sys.getlocale(),看输出中LC_CTYPE字段值。
2.3 首行可运行代码:用mtcars数据集验证环境是否真就绪
别急着读自己的CSV。先用R内置数据集mtcars跑通最小闭环:加载→查看结构→基础绘图。这是检验环境是否“真可用”的黄金三步。
# 1. 加载内置数据集(无需install,R自带) data(mtcars) # 2. 查看数据结构(重点看$disp, $hp是否numeric,$am是否factor) str(mtcars) # 3. 画一张最简散点图(验证ggplot2是否真加载成功) ggplot(mtcars, aes(x = disp, y = hp)) + geom_point() + labs(title = "mtcars: Engine Displacement vs Horsepower")预期结果与排查点:
- 若
str(mtcars)报错Error in data(mtcars) : object 'mtcars' not found→ R基础安装损坏,重装R; - 若
str()正常但ggplot(...)报错Error: could not find function "ggplot"→.Rprofile中library(ggplot2)未执行,检查文件路径和RStudio是否重启; - 若图形弹出但标题是方块乱码 →
.Rprofile中Sys.setlocale()未生效,Windows用户需确认RStudio是否以管理员身份运行(首次设置locale有时需提权)。
3. R数据结构实战:向量强制转换的玄学、因子的隐形枷锁与数据框列类型失控的根源
3.1 向量创建的四大陷阱:c()的隐式转换规则比你想象的更暴力
R中c()看似简单,实则是新手翻车第一现场。它不保留混合类型,而是按类型优先级强制统一:character > complex > numeric > logical。这意味着c(1, "a", TRUE)结果不是报错,而是"1" "a" "TRUE"——三个字符。这种“温柔的暴力”让bug极难定位。
真实案例复现:
某导师让学生读取Excel中的ID列(含数字和字母ID,如1001,"A002"),学生用readxl::read_excel()后直接c()拼接,后续用%in%筛选时永远找不到"A002",因为原数据被转成了"1001" "A002",而筛选条件却是数值1001。
安全写法(显式声明类型):
# 方案1:用as.character()提前锁定 id_vec <- c(as.character(1001), "A002", as.character(TRUE)) # 方案2:用list()保留原始类型(后续用unlist()时再处理) id_list <- list(1001, "A002", TRUE) # 类型不丢失 unlist(id_list, use.names = FALSE) # 输出:"1001" "A002" "TRUE" # 方案3:用tibble::tibble()替代向量存异构数据(推荐用于ID、代码等标识列) library(tibble) id_tb <- tibble(id = c(1001, "A002", TRUE)) # str(id_tb) 显示 id 是 character,且明确标注"chr"3.2 因子(factor):不是“分类变量”的代名词,而是带标签的整数数组
factor是R中最易误解的数据类型。它本质是整数向量+标签向量。levels()返回标签,as.numeric()返回底层整数,而非标签对应的数值。这是as.numeric(factor(c("1","2","3")))返回1 2 3而非1 2 3的真相——表面一样,底层逻辑天壤之别。
血泪经验:
某跨平台系统导出的问卷数据中,“满意度”列为"高","中","低"。学生直接mean(df$satisfaction)想算平均值,结果得2(因"高"=1,"中"=2,"低"=3)。但业务含义上,“高”应映射为5,“中”为3,“低”为1。
正确解法(三步走):
# 1. 创建有序因子(明确顺序) df$satisfaction <- factor(df$satisfaction, levels = c("低", "中", "高"), ordered = TRUE) # 2. 显式映射为数值(用match或case_when) library(dplyr) df <- df %>% mutate(sat_score = case_when( satisfaction == "低" ~ 1, satisfaction == "中" ~ 3, satisfaction == "高" ~ 5 )) # 3. 验证:此时mean(sat_score)才有业务意义 mean(df$sat_score, na.rm = TRUE)注意:
stringsAsFactors = FALSE必须写!R 4.0+虽默认FALSE,但旧脚本、read.csv()未加参数、或调用其他包的读取函数(如data.table::fread())仍可能默认TRUE。养成习惯:所有读取函数后加stringsAsFactors = FALSE。
3.3 数据框列类型失控:read.csv()的默认行为如何悄悄篡改你的数据
read.csv()是R数据导入的入口,也是类型失控的起点。它默认stringsAsFactors = TRUE(R 4.0前),且对数字列的NA识别极弱——""、" "、"N/A"全被当字符,"1.2e3"可能被当字符而非数值。
对比实验(同一CSV文件):
假设有test.csv:
id,name,score 1,Alice,95 2,Bob,"" 3,Charlie,87# 危险写法(默认行为) df1 <- read.csv("test.csv") str(df1) # $ score: Factor w/ 2 levels "","95": 2 1 2 → score变成factor!空值是level"" # 安全写法(显式控制) df2 <- read.csv("test.csv", stringsAsFactors = FALSE, # 关键! na.strings = c("", "N/A", "NULL"), # 明确空值标识 colClasses = c("character", "character", "numeric")) # 强制列类型 str(df2) # $ score: num 95 NA 87 → 正确!进阶技巧:用readr::read_csv()替代(推荐)readr包解析更快、类型推断更准、默认不转factor:
library(readr) df3 <- read_csv("test.csv", na = c("", "N/A"), col_types = cols( id = col_character(), name = col_character(), score = col_double() ))4. 数据清洗与可视化落地:从缺失值诊断到ggplot2图层崩溃的五类硬核排错
4.1 缺失值(NA)的三种面孔:is.na()、is.null()与""的生死区别
R中“空”有三层含义,混用即崩:
NA:缺失值,is.na(x)返回TRUE;NULL:对象不存在,is.null(x)返回TRUE,length(NULL)为0;"":空字符串,is.character("")为TRUE,nchar("")为0。
真实翻车链:
某公司用read.csv()读销售数据,region列有空单元格。学生用df[df$region != "", ]过滤,结果region为NA的行全被保留(因NA != ""返回NA,逻辑索引失效),导致后续group_by(region)报错Error: Columnregionmust be length 1 or 322, not 0。
万能清洗模板(覆盖全部空类型):
library(dplyr) df_clean <- df %>% # 步骤1:统一NA(将""、"N/A"等转为NA) mutate(across(where(is.character), ~na_if(., c("", "N/A", "NULL", " ")))) %>% # 步骤2:删除含NA的行(按需) drop_na(region, sales) %>% # 步骤3:填充NA(按业务逻辑) mutate(region = coalesce(region, "Unknown"))4.2 ggplot2图层崩溃:geom_text()坐标错位、scale_x_date()不显示、facet_wrap()标题截断的根因
ggplot2强大,但报错信息极其反人类。Error in unit(x, default.units) : 'x' and 'units' must have length > 0这种错误,90%源于数据类型不匹配。
避坑 / 常见问题 / 排查:
现象:
geom_text(aes(label = value))文字全堆在左下角,不随数据点移动
原因:value列是factor而非character或numeric,aes()无法正确映射
解决:mutate(value = as.character(value))或as.numeric(as.character(value))现象:
scale_x_date(date_labels = "%Y-%m")后X轴空白,无日期标签
原因:X轴数据是character(如"2023-01-01"),非Date类
解决:mutate(date = as.Date(date)),且确保date列在aes()中为date,非as.character(date)现象:
facet_wrap(~category)后小标题过长,被截断为"Category A..."
原因:category是factor,labels属性未自定义
解决:facet_wrap(~category, labeller = label_wrap_gen(width = 10)),或预处理mutate(category = fct_recode(category, "A组" = "Category A"))现象:
theme(axis.text.x = element_text(angle = 45))后X轴文字消失
原因:angle值过大(如90)导致文字超出绘图区,hjust/vjust未调整
解决:element_text(angle = 45, hjust = 1, vjust = 1),hjust=1右对齐,vjust=1上对齐,避免切边现象:
geom_smooth(method = "lm")报错Computation failed in stat_smooth()
原因:分组变量(如color)对应的数据点少于3个,线性回归无法拟合
解决:geom_smooth(method = "lm", se = FALSE, na.rm = TRUE)+filter(n() >= 3)预过滤
4.3 用dplyr链式操作完成一次完整清洗:从原始CSV到可绘图数据框
以一份模拟销售数据sales_raw.csv为例(含date,product,revenue,region列,含空值、异常值、类型混乱):
library(dplyr) library(lubridate) library(readr) # 1. 安全读取(readr比base::read.csv更鲁棒) df_raw <- read_csv("sales_raw.csv", na = c("", "N/A"), col_types = cols( date = col_date(format = "%Y-%m-%d"), product = col_character(), revenue = col_double(), region = col_character() )) # 2. 清洗主流程(链式,每步可独立验证) df_clean <- df_raw %>% # 处理日期:确保date列非NA且合理 filter(!is.na(date), date >= ymd("2022-01-01")) %>% # 处理收入:剔除负值、超大异常值(3倍IQR外) mutate(revenue = if_else(revenue < 0 | is.infinite(revenue), NA_real_, revenue)) %>% group_by(region) %>% mutate(revenue = if_else(revenue > quantile(revenue, 0.75) + 3*IQR(revenue, na.rm = TRUE), NA_real_, revenue)) %>% ungroup() %>% # 处理区域:标准化名称,填充空值 mutate(region = str_to_title(str_replace_all(region, "[[:punct:]]", "")), region = coalesce(region, "Unknown")) %>% # 删除完全空行 drop_na(date, revenue, region) # 3. 验证结果(关键!) print(paste("清洗后行数:", nrow(df_clean))) print("各列类型:") str(df_clean[, c("date", "revenue", "region")]) print("region分布:") table(df_clean$region)5. R包管理与函数编写:install.packages()的静默失败、devtools::install_github()的SSL证书坑与自定义函数的调试铁律
5.1install.packages()的三大静默失败场景与强制日志开关
install.packages()不报错≠安装成功。它常静默跳过依赖、缓存旧版本、或因权限拒绝写入库路径。
现象与解法:
场景1:依赖包未安装,主包却显示“successfully unpacked”
install.packages("shiny")成功,但library(shiny)报错there is no package called ‘httpuv’
解法:强制安装依赖install.packages("shiny", dependencies = TRUE)场景2:安装了旧版(如
dplyr 1.0.0),但需要1.1.0+packageVersion("dplyr")返回"1.0.0",而?filter文档显示新参数preserve = TRUE不存在
解法:清除旧版+强制更新remove.packages("dplyr"); install.packages("dplyr", type = "source")场景3:Windows下安装
Rcpp等编译包失败,无错误信息
控制台只显示* installing *source* package ‘Rcpp’ ...后卡住
解法:启用详细日志install.packages("Rcpp", verbose = TRUE),观察卡在g++还是Rtools路径
终极方案:用pak包替代(2023年R社区新标准)pak解决依赖解析、多版本共存、离线安装痛点:
# 一次性安装pak(需R 4.1+) install.packages("pak") library(pak) # 安装并锁定版本(生成pak.lock) pak::pkg_install("dplyr@1.1.0", "ggplot2@3.4.0") # 离线安装(先`pak::pkg_snapshot()`生成lock文件,再`pak::pkg_install(lockfile = "pak.lock")`)5.2devtools::install_github()的SSL证书坑:内网GitLab与自签名证书的绕过方案
公司内网GitLab私有包,devtools::install_github("myorg/mypackage", host = "gitlab.myorg.com")报错SSL certificate problem: self signed certificate。
安全绕过(仅限内网可信环境):
# 方案1:临时禁用SSL验证(不推荐生产) Sys.setenv(GITHUB_PAT = "") # 清空token避免干扰 devtools::install_github("myorg/mypackage", host = "gitlab.myorg.com", auth_token = NULL, INSTALL_opts = "--no-multiarch") # 方案2:配置Git信任证书(推荐) # 在终端执行(Windows Git Bash / macOS Terminal): # git config --global http."https://gitlab.myorg.com/".sslVerify false # 然后R中: devtools::install_git("https://gitlab.myorg.com/myorg/mypackage.git")5.3 自定义函数调试铁律:browser()、traceback()与rlang::last_error()的组合技
写函数不是写完}就结束。R函数调试的核心是暴露执行流。
标准调试流程(以safe_mean()为例):
safe_mean <- function(x, na.rm = TRUE) { # 第1行:插入断点(运行到此处暂停,可查看x, na.rm值) browser() # 第2行:强制类型检查(比报错早3步发现问题) if (!is.numeric(x)) { stop("`x` must be numeric, got ", class(x)) } # 第3行:计算前打印中间状态 cat("Input length:", length(x), "; NA count:", sum(is.na(x)), "\n") # 第4行:核心逻辑 result <- mean(x, na.rm = na.rm) # 第5行:返回前验证 if (is.nan(result)) { warning("`x` contains only NA after removal") result <- NA_real_ } return(result) }调试时必用三命令:
n:单步执行下一行c:继续执行到下一个断点或结束Q:退出调试模式
报错后溯源:
若函数崩溃,立即在R控制台输入:
traceback() # 显示错误发生前的函数调用栈 rlang::last_error() # 显示最后一次错误的详细上下文(需先`library(rlang)`)6. 从入门到可靠:用renv锁定环境、quarto替代RMarkdown导出与我每次部署前必做的三件事
6.1renv:为什么“在我电脑上能跑”是最大的技术债,以及如何用10行代码终结它
“在我电脑上能跑”是数据科学项目交付的最大毒瘤。R包版本漂移、系统库差异、甚至R小版本升级(如4.2→4.3)都可能导致ggplot2::theme_minimal()渲染异常。renv是R生态的pipenv/conda env,它把整个项目的R包状态快照化。
四步落地(无痛迁移):
# 1. 全局安装renv(一次) install.packages("renv") # 2. 进入项目目录,初始化(生成renv/子目录和renv.lock) renv::init() # 3. 安装所需包(自动记录到lock文件) renv::install("dplyr") renv::install("ggplot2") # 4. 导出快照(供协作或部署) renv::snapshot() # 生成renv.lock,含每个包的精确版本、来源、哈希值协作时,同事只需:
# 克隆项目后,第一行 renv::restore() # renv自动读取renv.lock,安装完全一致的包集合注意:
renv默认不跟踪R版本。若项目强依赖R 4.2+,需在项目根目录建r-version文件,写入4.2.3。renv::status()会检查R版本兼容性。
6.2quarto:RMarkdown导出PDF失败的终极替代方案,以及如何用3个YAML参数搞定中文字体
RMarkdown导出PDF常因tinytex缺失、xelatex路径错误、中文字体未注册而崩溃。quarto是RStudio官方推出的下一代出版框架,原生支持中文、自动处理字体、错误信息可读性强。
quarto项目结构:
myproject/ ├── _quarto.yml # 全局配置 ├── analysis.qmd # 主文档(替代.Rmd) └── _extensions/ # 可选扩展关键配置(_quarto.yml):
project: type: website format: pdf: latex-engine: xelatex include-in-header: text: | \usepackage{ctex} # 中文支持宏包 \setmainfont{Noto Serif CJK SC} # 主字体(macOS/Windows通用) \setsansfont{Noto Sans CJK SC} \setmonofont{Noto Sans Mono CJK SC}导出命令(终端执行):
quarto render analysis.qmd --to pdf # 无需手动装tinytex,quarto自动下载xelatex和字体6.3 我每次部署R脚本前必做的三件事:从sessionInfo()到renv::status()的硬核清单
这三件事不是仪式,是防止“线上崩、线下好”的最后一道闸门。我把它刻进了肌肉记忆:
运行
sessionInfo()并保存快照# 在脚本开头添加 sink("session_info.txt") sessionInfo() sink() # 检查:R version、操作系统、所有加载包版本是否与开发环境一致执行
renv::status()验证包一致性# 在R控制台运行 renv::status() # 关键看三行: # - "Lockfile is up to date" → ✅ # - "The following packages are out of sync" → ❌ 需`renv::snapshot()` # - "The following packages are installed but not recorded" → ❌ 需`renv::record()`用
codetools::checkUsage()扫描潜在错误# 对主脚本analysis.R进行静态分析 codetools::checkUsageFile("analysis.R") # 它会揪出:未定义变量、未导出函数调用、可疑的`<<-`赋值等 # 比`R CMD check`轻量,适合CI/CD快速验证
从那以后我每次提交R项目前,都强制走一遍这三步——哪怕只是改了一个标点。因为真正的“入门”,不是学会c()和ggplot(),而是建立起对环境、依赖、数据类型的敬畏心。希望帮到你。
本文还有配套的精品资源,点击获取