使用 pivot_wider() 将长格式转换为宽格式
将键值对展开回宽格式表格
使用 pivot_wider() 将长格式转换为宽格式 是 CoddyKit 上的免费 R Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。
何时使用宽格式
长格式适合分析,而宽格式通常用于报告、电子表格和某些算法(例如相关矩阵)。pivot_wider() 是 pivot_longer() 的逆操作——它会将一列中的值展开为多个新列。
library(tidyr)
# Long format: one row per student-quarter combination
long_df <- data.frame(
student = c('Alice','Alice','Alice','Bob','Bob','Bob'),
quarter = c('Q1','Q2','Q3','Q1','Q2','Q3'),
score = c(85, 88, 92, 90, 85, 88)
)
print(long_df)
cat('\n', nrow(long_df), 'rows x', ncol(long_df), 'cols')pivot_wider() 基础
pivot_wider(df, names_from, values_from)将长格式转换为宽格式。names_from 指定一个列,该列中的值将成为新列名;values_from 指定一个列,该列中的值将填入这些新列。
library(tidyr)
long_df <- data.frame(
student = c('Alice','Alice','Alice','Bob','Bob','Bob'),
quarter = c('Q1','Q2','Q3','Q1','Q2','Q3'),
score = c(85, 88, 92, 90, 85, 88)
)
wide_df <- pivot_wider(
long_df,
names_from = quarter,
values_from = score
)
print(wide_df)id_cols — 确定行键
id_cols 指定在宽格式输出中能够唯一确定每一行的列。默认情况下,dplyr 会使用未在 names_from 或 values_from 中指定的所有列。明确设置该参数可以避免意外分组。
library(tidyr)
df <- data.frame(
year = c(2023,2023,2024,2024),
region = c('East','West','East','West'),
quarter = c('Q1','Q1','Q1','Q1'),
revenue = c(100, 200, 120, 220)
)
pivot_wider(
df,
id_cols = c(year, quarter),
names_from = region,
values_from = revenue
)values_fill — 处理缺失的组合
当某些 id_cols 和 names_from 的组合不存在时,结果单元格会是 NA。使用 values_fill 可以将这些缺失值替换为默认值(例如,对于计数或求和可使用 0)。
library(tidyr)
df <- data.frame(
product = c('A','A','B'),
channel = c('online','store','online'),
sales = c(100, 150, 200)
)
# 'B' has no 'store' data — fill with 0
pivot_wider(
df,
names_from = channel,
values_from = sales,
values_fill = 0
)names_prefix — 添加前缀
使用 names_prefix 可在所有新列名之前添加一个字符串。当 names_from 中的值为数字,或您希望让列名更具描述性时,这可以避免相关问题。
library(tidyr)
df <- data.frame(
student = c('Alice','Alice','Bob','Bob'),
quarter = c(1, 2, 1, 2),
score = c(85, 90, 78, 82)
)
# Without prefix: columns named '1' and '2' (problematic)
# With prefix: q1, q2
pivot_wider(
df,
names_from = quarter,
values_from = score,
names_prefix = 'q'
)多个 values_from 列
您可以通过向 values_from 传入一个向量,一次转换多个值列。结果列的命名方式是使用 value_name,将值列名与类别组合起来。
library(tidyr)
df <- data.frame(
region = c('East','East','West','West'),
period = c('Q1','Q2','Q1','Q2'),
revenue = c(100, 120, 200, 210),
units = c(10, 12, 20, 22)
)
pivot_wider(
df,
names_from = period,
values_from = c(revenue, units)
)使用 values_fn 处理重复值
如果同一个 id + name 组合对应多个值,pivot_wider 不知道应使用哪一个值,因此会发出警告并返回一个列表列。使用 values_fn 指定聚合函数即可解决这个问题。
library(tidyr)
# Duplicate rows: Alice has two Q1 scores
df <- data.frame(
student = c('Alice','Alice','Alice','Bob','Bob'),
quarter = c('Q1','Q1','Q2','Q1','Q2'),
score = c(85, 87, 90, 78, 82)
)
# Resolve duplicates by taking the mean
pivot_wider(
df,
names_from = quarter,
values_from = score,
values_fn = mean
)使用命名列表传入 values_fn
向 values_fn 传入命名列表,可以同时对不同的值列应用不同的聚合函数。当转换的多个值列需要使用不同的汇总方法时,这种方式非常实用。
library(tidyr)
df <- data.frame(
region = c('East','East','West','West'),
period = c('Q1','Q1','Q1','Q1'),
revenue = c(100, 120, 200, 210),
orders = c(10, 12, 20, 22)
)
pivot_wider(
df,
names_from = period,
values_from = c(revenue, orders),
values_fn = list(revenue = sum, orders = sum)
)创建交叉表
使用 dplyr::count() 进行计数后,再调用 pivot_wider(),即可轻松创建数据框形式的交叉表(列联表)。这结合了两个包在频数分析方面的优势。
library(tidyr)
library(dplyr)
survey <- data.frame(
dept = c('HR','HR','Eng','Eng','HR','Eng'),
response = c('Yes','No','Yes','Yes','Yes','No')
)
survey %>%
count(dept, response) %>%
pivot_wider(
names_from = response,
values_from = n,
values_fill = 0
)往返转换:长表 → 宽表 → 长表
理解 pivot_longer() 与 pivot_wider() 之间的逆向关系,有助于发现错误。往返转换(长表→宽表→长表)应当返回原始数据(行顺序和类型转换可能有所不同)。
library(tidyr)
original_long <- data.frame(
id = c(1,1,2,2),
key = c('a','b','a','b'),
value = c(10, 20, 30, 40)
)
# Go wide
wide <- pivot_wider(original_long, names_from=key, values_from=value)
print(wide)
# Go long again
pivot_longer(wide, -id, names_to='key', values_to='value')实践:成绩报告
一个典型用例是:将按长格式存储的测试成绩表,转换为按学生和科目组织的报告表。结合 dplyr::arrange() 和 rename(),即可生成整洁、适合展示的输出。
library(tidyr)
library(dplyr)
scores <- data.frame(
student = c('Alice','Alice','Bob','Bob','Carol','Carol'),
subject = c('Math','Science','Math','Science','Math','Science'),
score = c(92, 88, 85, 91, 79, 83)
)
scores %>%
pivot_wider(names_from=subject, values_from=score) %>%
mutate(average = round((Math + Science) / 2, 1)) %>%
arrange(desc(average))快速检查
调用 pivot_wider() 时,如果同一个 id + name 组合对应多个值,会发生什么?
总结:pivot_wider()
长表转宽表的要点:
pivot_wider(names_from, values_from)将键列展开为多个新列id_cols指定用于标识每一行的列values_fill = 0(或任何标量)用于填充缺失的组合names_prefix在列名之前添加字符串,以避免数字列名或含义不明确的列名values_fn使用聚合函数处理重复的单元格值- 向
values_from传入向量,可以同时转换多个值列 - 在
count()之后使用,可高效构建交叉表
library(tidyr)
library(dplyr)
data.frame(
region = c('East','East','West','West'),
metric = c('revenue','units','revenue','units'),
value = c(100, 10, 200, 20)
) %>%
pivot_wider(
names_from = metric,
values_from = value,
values_fill = 0
) %>%
mutate(revenue_per_unit = revenue / units)常见问题解答
「使用 pivot_wider() 将长格式转换为宽格式」课时是免费的吗?
是的 — 「使用 pivot_wider() 将长格式转换为宽格式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。
「使用 pivot_wider() 将长格式转换为宽格式」这节课中我会学到什么?
将键值对展开回宽格式表格 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 R Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 pivot_wider() 将长格式转换为宽格式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 R Academy 课中编写并运行代码吗?
能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 pivot_longer() 将宽格式转换为长格式
- 使用 pivot_wider() 将长格式转换为宽格式
- 使用 separate() 和 unite() 处理字符串列
- 嵌套与展开数据框