02使用 dplyr 创建和转换列

使用 mutate 新增、覆盖和批量转换列,并控制新列位置、原列保留和条件计算。

2026-03-05
RTidyversedplyrmutateData Transformation
本章目录 · 8

mutate() 根据已有列创建新列,也可以覆盖现有列。表达式按书写顺序求值,因此后面的新列可以引用同一次调用中前面刚创建的列。

library(dplyr)

students <- tibble(
  name = c("Alice", "Bob", "Charlie"),
  score = c(90, 85, 88),
  age = c(20, 21, 19)
)

新增与修改列

students |>
  mutate(double_score = score * 2)

同时创建多个变量:

students |>
  mutate(
    score_fraction = score / 100,
    score_percent = score_fraction * 100
  )

覆盖现有列:

students |>
  mutate(score = round(score / 10, 1))

覆盖会丢失原值。若后续需要核查,先创建一个有明确单位的新列通常更安全。

控制新列位置

students |>
  mutate(double_score = score * 2, .before = score)

students |>
  mutate(double_score = score * 2, .after = name)

复杂管道中,也可以先完成计算,再用 relocate() 统一排列。

控制保留哪些原列

.keep 决定输出保留的输入列:

保留内容
"all" 所有输入列,默认
"used" 新表达式使用过的输入列
"unused" 未被表达式使用的输入列
"none" 只保留分组列和新列
students |>
  mutate(double_score = score * 2, .keep = "used")

students |>
  mutate(double_score = score * 2, .keep = "none")

.keep 适合制作中间结果或最终特征表,但不应为了输出简短而过早丢掉标识列和核查字段。

条件转换

二选一使用 if_else()

students |>
  mutate(result = if_else(score >= 90, "high", "other"))

多个条件使用 case_when()

students |>
  mutate(
    grade = case_when(
      score >= 90 ~ "A",
      score >= 80 ~ "B",
      TRUE ~ "C"
    )
  )

条件从上到下匹配,先满足的分支生效。范围重叠时,顺序就是业务规则的一部分。

使用 across() 批量处理列

measurements <- tibble(
  id = 1:3,
  height = c(170.2, 168.8, 181.1),
  weight = c(65.4, 58.9, 82.2)
)

measurements |>
  mutate(
    across(
      c(height, weight),
      round,
      digits = 0
    )
  )

生成新列而不覆盖原列:

measurements |>
  mutate(
    across(
      c(height, weight),
      ~ round(.x, 0),
      .names = "{.col}_rounded"
    )
  )

也可以按类型选择:

measurements |>
  mutate(across(where(is.numeric), as.double))

批量转换前要确认所选列共享相同的含义和单位,不能因为它们都是 numeric 就自动采用相同处理。

分组内转换

scores <- tibble(
  group = c("A", "A", "B", "B"),
  score = c(10, 12, 20, 24)
)

scores |>
  mutate(
    group_mean = mean(score),
    centered = score - group_mean,
    .by = group
  )

.by 只作用于这一次 mutate(),结果不会保留分组状态。

缺失值传播

多数数值运算会保留 NA

tibble(x = c(1, NA, 3)) |>
  mutate(y = x * 2)

汇总函数是否移除缺失,需要明确指定:

scores |>
  mutate(group_mean = mean(score, na.rm = TRUE), .by = group)

na.rm = TRUE 只是忽略缺失,并不说明缺失机制合理。数据清洗和统计分析中仍需记录缺失数量与处理依据。

保持单位和类型清晰

patients |>
  mutate(
    height_m = height_cm / 100,
    bmi = weight_kg / height_m^2
  )

新列名称应表达单位和含义。mutate() 能让计算很短,但可复现性来自明确的变量定义,而不是管道长度。