R 语言技巧

R
dplyr
stringr
正则表达式
CSS颜色
文本分析
数据可视化
代码片段
常用 R 技巧与代码片段:dplyr 数据处理、stringr 文本操作、CSS 颜色名称、代码速查表等。
作者

Pinn Xu

发布于

2026年3月27日

7 min read · 410 EN words · 1416 中文字

常用要点

要点 说明
相对路径 数据与代码放同一文件夹,用相对路径读取,避免路径含空格报错
统计量加 na.rm = TRUE sum、mean、sd、IQR 等均需加,否则有缺失值时结果为 NA
明确观测单位 确认每行代表什么;
混合类型(如 post/comment)应先 filter(type == "post")
count() 内计算时命名 如 count(month = month(date))
区分 filter() 和 select() filter(condition) 选行; select(col) 选列 (filter逻辑运算符)
取值用 nrow() / pull() nrow() 返回行数;pull() 从数据框取出单个值
文本处理用 stringr + Regex str_length() 数字符;str_count(text, "\\S+") 数单词
新增列后赋值回原变量 data <- data |> mutate(…)
TRUE / FALSE 别名 等价于 T / F
善用 RStudio Snippet 用代码模板减少重复输入

1 观察数据

1.1 行数 / 列数

nrow(data)
ncol(data)

1.2 有多少符合条件的 Observation

data |> filter(条件) |> nrow()
# 示例: 已知 data 有 type 列, 其中只有 "comment" 和 "post" 两种值
# 求一共多少个 post

# 方法1: 用 nrow() 直接返回行数, 其他 dplyr 函数都需要最终用 pull() 来取出数值
data |>
    filter(type == "post") |>
    nrow()

# 方法2:
data |>
    filter(type == "post") |>
    count(type) |>  # 此处 count 和 filter 的顺序即使调换结果也一样
    pull(n)

# 方法3:
data |> 
    filter(type == "post") |> 
    summarize(n = n()) |> 
    pull(n)

1.3 某列中 Observation 数量最多的 类 是哪个

data |> count(col, sort=T) |> head(1) |> pull(col)
# 示例: 已知 data 里有 date 列, 其 datatype 是 Date (yyyy-mm-dd)
# 求哪一年的 post 最多

# 方法1:
data |>
    filter(type == "post") |>
    count(year = year(date), sort = TRUE) |>
    head(1) |> # 上一行已经指定了 sort=T, 此处直接用 head(1) 即可
    pull(year)

# 方法2:
data |>
    filter(type == "post") |>
    count(year = year(date)) |> # count 生成一个两列的 df, year 和 n
    slice_max(n, n = 1) |> # 第一个 n 是列名, 第二个是行数, 意为选取n最大的一行
    pull(year)

1.4 某列的 min / max 值是多少

# 问的是所有行的话 (e.g. "overall activity", "across the whole dataframe")
# 无需用 pipe, 如果有限制条件 (e.g. "only posts"), 先 filter
min(data$col, na.rm = TRUE)
max(data$col, na.rm = TRUE)

1.5 某列有多少 unique value

n_distinct(data$col)

2 清理数据

2.1 求 mean / median 并保留 2 位小数

summarize(mean = round(mean(col, na.rm = TRUE), 2)) |> pull(mean)
# 示例: 求 2019 年 post 的 score 的平均值, 保留 2 位小数
data |>
    filter(type == "post" & year(date) == 2019) |>
    summarize(mean = round(mean(score, na.rm = TRUE), 2)) |>
    pull(mean)
# 示例: 求每年的 post median score, 保留 2 位小数,
# 按 median score 从高到低排列, 展示成一个 dataframe
data |>
    filter(type == "post") |>
    group_by(year = year(date)) |>
    summarize(
        median_score = round(median(score, na.rm = TRUE), 2),
        .groups = "drop"  # group + summarize 必须加上 drop
    ) |>
    arrange(desc(median_score)) # 排序, 也可以写成 arrange(-median_score)

2.2 增加一列

data <- data |> mutate(new_col = 对于col进行操作)
# 添加一列 字符数
data <- data |>
    mutate(text_length = str_length(text))

# 添加一列 单词数
data <- data |>
    mutate(word_count = str_count(text, "\\S+"))

2.3 某列最大值所在行的另一列值

data |> 
    slice_max(col1, n = 1) |> 
    pull(col2)
# 示例: word_count 最多的 post 的 author 是谁?
data |>
    # 问的是 post, 但 data 里不都是 post, 首先要 filter 
    filter(type == "post") |>
    slice_max(word_count, n = 1) |>
    pull(author)

2.4 求 text length (字符数)

str_length(text)

2.5 求单词数量

str_count(text, "\\S+")

3 可视化

3.1 Bar Chart

# 示例: 画出 2019 年每月 post 数量的 bar chart

# 第一步: 获取用于绘图的数据
bar_data <- data |>
    filter(type == "post" & year(date) == 2019) |>
    count(month = month(date)) # 无需 sort = TRUE

# 第二步: 画图
ggplot(bar_data, aes(x = factor(month), y = n)) +
    # month 列是数字, 直接用的话 x 轴会变成连续的, 要用 factor(month)
    # 注: 由于"月份"是时间, 本身有顺序, 无需把 bar 按照大小排列;
    # 如果是 nominal 比如"地区", 可以用 x = reorder(area, -n) 来降序排列
    # 如果地区过多或地区名称过长, 可以用 coord_flip() 来转成横向 bar chart

    # 注意要用 geom_col 而不是 _bar, 因为此处 y 是 n 列中的值 (预先计算好的行数),
    # 而不是让 ggplot 自己去数 x 中不同 category 的行数
    geom_col(fill = "steelblue") + # 随便指定一个喜欢的颜色
    
    labs(
        title = "Monthly Post Count in 2019",
        x = "Month",
        y = "Post Count"
    )

3.2 Histogram

# 画出 post score 的 histogram
ggplot(data |> filter(type == "post"), aes(x = score)) +
    geom_histogram(fill = "steelblue", bins = 30) + # 指定 bin 数
    labs(
        title = "Post Score Distribution",
        x = "Post Score",
        y = "Frequency"
    )

4 文本分析

# 示例: 用一个 dataframe 展示出 post 中 top10 词频的词, 并保存到 top1 词成变量
data |>
    filter(type == "post") |>
    unnest_tokens(word, text) |>
    anti_join(stop_words) |>
    count(word, sort = TRUE) |>
    head(10)

top1 <- data |>
    filter(type == "post") |>
    unnest_tokens(word, text) |>
    anti_join(stop_words) |>
    count(word, sort = TRUE) |>
    head(1) |>
    pull(word)

5 统计

5.1 求统计量

round(sd(data$col, na.rm = TRUE), 2)
IQR(data$col, na.rm = TRUE)

5.2 先处理再求统计量

filter(条件) |> summarize(mean = mean(col, na.rm = TRUE)) |> pull(mean)

5.3 检测统计量 + 解读结果

t.test(col1 ~ col2, data = data)

5.4 线性回归 + 系数

m <- lm(col1 ~ col2, data = data)
coef(m)[[1]]  # intercept
coef(m)[[2]]  # slope

6 附加

6.1 常用 dplyr 函数

函数 作用 示例
filter(条件) 保留满足条件的行 filter(type == "post" & score > 10)
select(列) 根据列名选列 select(col1), col1:col3, -col3
count(列) 这列中所有 unique value 的行数 count(year = year(date), sort = TRUE)
nrow() 数当前有多少行 没有参数, 一般配合 filter() 使用:
filter(score > mean(score, na.rm=T)) |> nrow()
slice_max(列, n=行数) 选出这列中值最大的行 slice_max(score, n = 10)
pull(列) 返回这列的值 一般先 filter / slice_max / head / summarize 到只剩一行, 然后 pull(列名), 比如:
summarize(mean_age=mean(age,na.rm=T))|> pull(mean_age)
mutate(新列=表达式) 在原df基础上添加/修改列 mutate(perc = col1/col2*100)
group_by(分类的列) 分组 (配合 summarize/mutate) group_by(age)
summarize(...) 返回总结报告 group_by(age) |>
summarize(avg = mean(score, na.rm=T), .groups=“drop”)
arrange(列) 排序(默认升序) arrange(age, desc(score))
glimpse(df) 查看结构(≈ str()) glimpse(data)
rename(新=旧) 重命名列(不新建列) rename(new_col = old_col)

group_by + summarize:必须加 .groups="drop";保留分组列 + 汇总列,行数压缩为每组一行 group_by + mutate:保留所有列且行数不变,之后须 ungroup() mean(condition) → 满足条件的比例;sum(condition) → 满足条件的个数

注意区分 nrow() 和 n() : 同样是数行数, nrow() 接受 dataframe 作为参数; n() 是 dplyr 上下文函数, 只能在 summarize() / mutate() 内部使用 (如 summarize(number_of_observation = n())), pipe 时只能用 nrow()

# 示例:
# 已知 data 有一列 type, 只有 "post" 和 "comment" 两种值;
# 另一列 word_count 是帖子或评论中的词数, 求有多少帖子词数少于 10
data |> 
    filter(type == "post" & word_count < 10) |>
    nrow() # 直接返回数字

data |>
    filter(type == "post" & word_count < 10) |>
    summarize(count = n()) |> # summarize() 仍然返回 dataframe
    pull(count) # 需要 pull 才能得到数字

6.2 filter() 中的逻辑运算符

Operator 说明
! & | not / and / or
== != 向量相等 / 不等
> >= < <= 大于 / 大于等于 / 小于 / 小于等于
%in% 左元素是否存在于右向量 (非向量比较)

%in% 判断元素存在性;== 按位置匹配(长度不等会循环)

# 示例:
# 已知 data 中有一列 date, 该列的 datatype 是 Date (yyyy-mm-dd);
# 已知另一列 type, 该列有 "post" 和 "comment" 两种值;
# 求年份是 2019 和 2023 的 post 一共有多少个

data |>
    filter(type == "post" & year(date) %in% c(2019, 2023)) |>
    nrow()
    
# 1. 条件1 是 type 为 "post", 用 == 符号
# 2. 条件2 是 年份 为 2019 或 2023,
#    首先要取出 date 列中的 年份, 使用 year() 取出完整日期(yyyy-mm-dd)中的年份;
#    然后满足年份是 2019 或 2023, 此处可以用两种方法: 
#      1) (year(date) == 2019 | year(date) == 2023)
#      2) year(date) %in% c(2019, 2023)
# 3. 同时满足两个条件, 用 & 符号连接
#    注: 如果上一步使用了 1) 的写法, 最好在外面加上括号后再用 & 连接两个条件
# 4. 用 nrow() 数符合 filter 条件的一共有多少行

# 扩展: 
# 如果求年份从 2019 到 2023 的所有 post 一共有多少个, 可以用
#   year(date) %in% 2019:2023
# 因为 2019:2023 实际返回 c(2019, 2020, 2021, 2022, 2023)

6.3 select() 中的辅助函数

注意: select() 选择的是列, filter() 选择的是行; 两者功能不同, 不可混用

写法 效果
select(col1:col3) 选 col1 到 col3
select(-col3) 排除 col3
select(contains(“x”)) 列名含 “x”
select(starts_with(“c”)) 列名以 “c” 开头
select(ends_with(“3”)) 列名以 “3” 结尾
select(everything()) 全选

6.4 Regex

# 添加一列 字符数
data <- data |>
    mutate(text_length = str_length(text))

# 添加一列 单词数
data <- data |>
    mutate(word_count = str_count(text, "\\S+"))
Pattern Meaning Example Matches
. 任意单个字符 "a.c" “abc”, “a1c”, “a c”
^ 字符串开头 "^The" “The dog” 但不匹配 “See The dog”
$ 字符串结尾 "end$" “the end” 但不匹配 “endless”
* 前一个字符出现零次或多次 "ab*c" “ac”, “abc”, “abbc”
+ 前一个字符出现一次或多次 "ab+c" “abc”, “abbc” 但不匹配 “ac”
? 前一个字符出现零次或一次 "colou?r" “color”, “colour”
\\ 转义特殊字符 "\\." 字面意义的句点 “.”
Pattern Meaning Example
[abc] 匹配 a、b 或 c "[aeiou]" 匹配元音
[a-z] 匹配任意小写字母
[A-Z] 匹配任意大写字母
[0-9] 匹配任意数字 等同于 \\d
[^abc] 匹配除 a、b、c 以外的任意字符 [^0-9] 匹配非数字
Shorthand Meaning Equivalent
\\d 任意数字 [0-9]
\\D 任意非数字 [^0-9]
\\w 任意单词字符 [a-zA-Z0-9_]
\\W 任意非单词字符 [^a-zA-Z0-9_]
\\s 任意空白字符 空格、制表符、换行
\\S 任意非空白字符

6.5 stringr 函数

Function Purpose Example
str_detect() 是否存在匹配 (TRUE/FALSE) str_detect(x, "pattern")
str_subset() 返回匹配的元素 str_subset(x, "pattern")
str_extract() 提取第一个匹配 str_extract(x, "pattern")
str_extract_all() 提取所有匹配 str_extract_all(x, "pattern")
str_replace() 替换第一个匹配 str_replace(x, "pattern", "replacement")
str_replace_all() 替换所有匹配 str_replace_all(x, "pattern", "replacement")
str_match() 提取第一个匹配的分组 str_match(x, "pattern")
str_count() 统计匹配次数 str_count(x, "pattern")
str_split() 按模式拆分字符串 str_split(x, "pattern")

6.6 常用颜色名称

颜色名称 预览 颜色名称 预览
pink ████ beige ████
lightpink ████ darkseagreen ████
lightcoral ████ mediumseagreen ████
palevioletred ████ forestgreen ████
rosybrown ████ green ████
indianred ████ seagreen ████
firebrick ████ teal ████
tomato ████ lightseagreen ████
coral ████ mediumaquamarine ████
salmon ████ powderblue ████
lightsalmon ████ lightblue ████
sandybrown ████ skyblue ████
orange ████ lightskyblue ████
peru ████ lightsteelblue ████
tan ████ steelblue ████
wheat ████ mediumpurple ████
bisque ████ plum ████
linen ████ thistle ████

6.7 相对路径

相对路径。 将 Rmd 文件与 csv 放在同一文件夹, 用 read_csv("./exam-data.csv") 读取; ./ 指当前文件夹。推荐使用相对路径, 可避免路径含空格导致的报错。

绝对路径。 在 Finder 中选中文件后按 ⌥⌘C 可复制绝对路径, 如 data <- read_csv("/Users/username/EM747/mid-exam/exam-data.csv")。

6.8 RStudio Snippet

在 RStudio > Tools > Edit Code Snippets

编辑代码片段

R > 在最下方添加新代码 > 保存

RStudio里创建代码片段的流程

例如 ggplot 画图的模板:

snippet ggplot
    ggplot(${1:data}, aes(x = ${2:x}, y = ${3:y})) +
        geom_${4:bar}(${5:fill} = "${6:steelblue}") + 
        labs(
            title = "${7:title}",
            x = "${8:xlab}",
            y = "${9:ylab}"
        )

保存成功后, 在 R 代码块里输入 ggplot, 选择 snippet:

在代码块里输入代码片段别名

按回车, 自动嵌入模板:

插入后的模板

↑回到顶部

回到顶部