使用 pivot_longer() 将宽格式转换为长格式
将宽格式表格重塑为适合分析的整洁长格式
使用 pivot_longer() 将宽格式转换为长格式 是 CoddyKit 上的免费 R Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。
宽格式与长格式数据
数据可以存储为宽格式(每个主体一行,包含多个值列),也可以存储为长格式(每条观测一行,包含一个变量名列和另一个值列)。许多用于可视化和建模的 R 软件包都要求使用长格式。
library(tidyr)
library(dplyr)
# Wide format: each quarter is a column
wide_df <- data.frame(
student = c('Alice','Bob','Carol'),
q1 = c(85, 90, 78),
q2 = c(88, 85, 80),
q3 = c(92, 88, 84)
)
print(wide_df)
cat('\nShape:', nrow(wide_df), 'rows x', ncol(wide_df), 'cols')pivot_longer() 基础
pivot_longer(df, cols, names_to, values_to)将宽格式转换为长格式。cols 指定要透视的列,names_to 是用于存放原列名的新列,values_to 是用于存放值的新列。
library(tidyr)
wide_df <- data.frame(
student = c('Alice','Bob','Carol'),
q1 = c(85, 90, 78),
q2 = c(88, 85, 80),
q3 = c(92, 88, 84)
)
long_df <- pivot_longer(
wide_df,
cols = c(q1, q2, q3),
names_to = 'quarter',
values_to = 'score'
)
print(long_df)使用 starts_with() 选择列
您无需明确列出列名,而可以在 cols 内使用 tidyselect 辅助函数。starts_with('prefix')、ends_with('suffix') 和 contains('string') 对于一致地透视具有相同命名模式的列尤其有用。
library(tidyr)
df <- data.frame(
id = 1:3,
sales_jan = c(100, 200, 150),
sales_feb = c(120, 180, 160),
sales_mar = c(130, 190, 170)
)
# Select all sales_ columns automatically
pivot_longer(
df,
cols = starts_with('sales_'),
names_to = 'month',
values_to = 'sales'
)使用 -col 排除列
另一种方法是使用 -col_name 指定要从透视中排除的列。其余所有列都会被透视。当只有一两个 ID 列、却有许多值列时,这种方法很方便。
library(tidyr)
df <- data.frame(
region = c('East','West'),
jan = c(100, 200),
feb = c(110, 210),
mar = c(120, 220),
apr = c(130, 230)
)
# Pivot everything except 'region'
pivot_longer(df, cols = -region, names_to = 'month', values_to = 'revenue')names_prefix — 去除前缀
当列名带有类似 score_q1、score_q2 的前缀时,names_prefix 参数会从生成的 names_to 列中去除该前缀,从而保持标识符整洁。
library(tidyr)
df <- data.frame(
id = 1:3,
score_q1 = c(85, 90, 78),
score_q2 = c(88, 85, 80),
score_q3 = c(92, 88, 84)
)
pivot_longer(
df,
cols = starts_with('score_'),
names_to = 'quarter',
names_prefix = 'score_',
values_to = 'score'
)透视多组列
当您有多组值列(例如同时有 sales_q1 和 cost_q1)时,请在 names_to 中使用多个值,并结合 names_pattern 将列名拆分为不同部分。
library(tidyr)
df <- data.frame(
id = 1:2,
sales_q1 = c(100, 200),
sales_q2 = c(110, 210),
cost_q1 = c(60, 110),
cost_q2 = c(65, 115)
)
pivot_longer(
df,
cols = -id,
names_to = c('.value', 'quarter'),
names_pattern = '(.+)_(q[0-9]+)'
)names_transform — 转换类型
默认情况下,新名称列的类型为字符型。使用 names_transform 可以自动将名称列转换为其他类型(例如,将 y2020、y2021 等列名转换为整数年份)。
library(tidyr)
df <- data.frame(
product = c('A','B'),
y2021 = c(100, 200),
y2022 = c(110, 210),
y2023 = c(120, 220)
)
result <- pivot_longer(
df,
cols = -product,
names_to = 'year',
names_prefix = 'y',
names_transform = list(year = as.integer),
values_to = 'sales'
)
print(result)
cat('year column type:', class(result$year))values_drop_na — 删除缺失值
当宽格式中某些列与行的组合存在缺失值时,它们在长格式中会显示为 NA。设置 values_drop_na = TRUE,即可自动删除值为 NA 的行。
library(tidyr)
df <- data.frame(
student = c('Alice','Bob','Carol'),
q1 = c(85, NA, 78),
q2 = c(88, 85, NA),
q3 = c(NA, 88, 84)
)
# Without drop: 9 rows including NAs
pivot_longer(df, -student, names_to='quarter', values_to='score',
values_drop_na = TRUE)长格式让 ggplot2 更易使用
转换为长格式最重要的原因是:ggplot2 会从列中映射图形美学属性。当所有值位于一列、类别位于另一列时,您就可以轻松使用 color = quarter 或 facet_wrap(~quarter)。
library(tidyr)
# (ggplot2 not run here, but showing the data preparation)
df <- data.frame(
month = c('Jan','Feb','Mar'),
product_A = c(100, 120, 110),
product_B = c(200, 190, 210)
)
# After pivoting, ready for ggplot2:
long_df <- pivot_longer(df, -month, names_to='product', values_to='sales')
print(long_df)
# ggplot(long_df, aes(x=month, y=sales, color=product)) + geom_line()透视数值列名
有时列名是纯数字(例如年份:2020、2021)。在 R 中,数据框中的数值列名需要加引号。请在 cols 参数中使用 num_range('', 2020:2023) 或反引号引起来的列名来处理它们。
library(tidyr)
# Year columns as numbers (common in census-style data)
df <- data.frame(
country = c('US','UK'),
'2021' = c(100, 80),
'2022' = c(110, 85),
'2023' = c(120, 90),
check.names = FALSE
)
pivot_longer(
df,
cols = c('2021','2022','2023'),
names_to = 'year',
values_to = 'gdp_index'
)比较透视结果
透视后请验证结果:行数应为 nrow(wide) * n_pivoted_cols,而 names_to 列中的唯一值应与原始列名一致(如果去除了前缀,则不包括该前缀)。
library(tidyr)
wide <- data.frame(
id = 1:4,
jan = c(10,20,30,40),
feb = c(11,21,31,41),
mar = c(12,22,32,42)
)
long <- pivot_longer(wide, -id, names_to='month', values_to='value')
cat('Wide rows:', nrow(wide), '\n')
cat('Long rows:', nrow(long), '(expected', nrow(wide)*3, ')\n')
cat('Months:', paste(unique(long$month), collapse=', '), '\n')快速检查
names_prefix 参数在 pivot_longer() 中的作用是什么?
回顾:pivot_longer()
将宽格式转换为长格式的要点:
pivot_longer(df, cols, names_to, values_to)是核心函数cols接受 tidyselect:starts_with()、-id_col、c('a','b')names_prefix去除列名开头的字符串names_transform转换名称列的类型(例如转换为整数)values_drop_na = TRUE自动删除包含 NA 的行- 长格式是 ggplot2、大多数建模函数和统计检验所要求的格式
- 验证方式:长格式行数 = 宽格式行数 × 透视列数
library(tidyr)
df <- data.frame(
team = c('Alpha','Beta'),
sales_2022 = c(100, 200),
sales_2023 = c(120, 220),
sales_2024 = c(140, 240)
)
pivot_longer(
df,
cols = starts_with('sales_'),
names_to = 'year',
names_prefix = 'sales_',
names_transform = list(year = as.integer),
values_to = 'revenue'
)常见问题解答
「使用 pivot_longer() 将宽格式转换为长格式」课时是免费的吗?
是的 — 「使用 pivot_longer() 将宽格式转换为长格式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。
「使用 pivot_longer() 将宽格式转换为长格式」这节课中我会学到什么?
将宽格式表格重塑为适合分析的整洁长格式 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 R Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「使用 pivot_longer() 将宽格式转换为长格式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 R Academy 课中编写并运行代码吗?
能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 pivot_longer() 将宽格式转换为长格式
- 使用 pivot_wider() 将长格式转换为宽格式
- 使用 separate() 和 unite() 处理字符串列
- 嵌套与展开数据框