You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中将含多组学生的宽格式数据集转换为长格式?

在R中将无统一列名的宽格式学生数据重构为长格式

我有一个包含22位讲师的数据集:

  • 每位讲师对应9个属性列(FirstName、LastName、School、Email等)
  • 每位讲师对应4组学生,每组学生的数据分布在64列中
  • 学生列的列名没有统一命名规则,但存在区间规律:"Student1 age"到"Student2 age"之间的63列均属于Student1,Student2的列从"Student2 age"到"Student3 age"前一列,以此类推,每组固定64列

我需要把这个宽格式数据转换成长格式,让每位学生的每条信息单独占一行。

简化示例数据

以下是简化版的数据集(仅保留2位讲师、1个讲师属性列,每组学生2列数据):

讲师讲师所属院校学生1年龄学生1性别学生2年龄学生2性别学生3年龄学生3性别学生4年龄学生4性别
JohnX18male18female16female17male
JaneY16female15male16male18female

期望的长格式结果

讲师讲师所属院校学生编号信息内容
JohnX118
JohnX1male
JohnX218
JohnX2female
JohnX316
JohnX3female
JohnX417
JohnX4male
JaneY116
JaneY1female
JaneY215
JaneY2male
JaneY316
JaneY3male
JaneY418
JaneY4female

我尝试的代码(仅适用于简化示例)

针对简化数据,我用以下代码实现了类似结果,但排序有差异:

library(tidyverse)

original_data <- data.frame(
  Instructor = c("John", "Jane"),
  Instructor_school = c("X", "Y"),
  Student1_age = c(18, 16),
  Student1_gender = c("male", "female"),
  Student2_age = c(18, 15),
  Student2_gender = c("female", "male"),
  Student3_age = c(16, 16),
  Student3_gender = c("female", "male"),
  Student4_age = c(17, 18),
  Student4_gender = c("male", "female")
)

# Reshape the data to long format
long_data <- original_data %>%
  gather(key = "key", value = "value", -Instructor, -Instructor_school) %>%
  separate(col = key, into = c("Student", "Info"), sep = "_") %>%
  mutate(Student = gsub("Student", "", Student))

View(long_data)

但这个方法无法应用到实际数据中,因为学生列没有统一的命名规则,无法通过分隔列名来区分学生组。恳请提供解决方案。


解决方案

针对实际数据的区间规律,我们可以按列的位置分组来处理,不需要依赖列名:

步骤说明

  1. 拆分数据集:前9列是讲师属性列,剩余列按每64列一组,分成4组(对应Student1到Student4)
  2. 对每组学生列单独转换为长格式,并标记对应的学生编号
  3. 合并所有组的结果,得到最终长格式数据

代码实现

library(tidyverse)

# 假设你的实际数据框名为`actual_data`
# 1. 定义讲师属性列数量和每组学生列数
instructor_cols_num <- 9
student_cols_per_group <- 64

# 2. 按位置拆分学生列组
student_col_indices <- seq(instructor_cols_num + 1, ncol(actual_data))
student_groups <- split(student_col_indices, ceiling(seq_along(student_col_indices)/student_cols_per_group))

# 3. 循环处理每个学生组
long_result_list <- map2(student_groups, 1:4, function(cols, student_id) {
  # 提取当前组的列,结合讲师属性列
  group_data <- actual_data %>%
    select(all_of(c(1:instructor_cols_num, cols)))
  
  # 转换为长格式
  group_data %>%
    pivot_longer(cols = -all_of(1:instructor_cols_num), 
                 values_to = "信息内容") %>%
    mutate(学生编号 = student_id) %>%
    # 保留讲师属性列、学生编号、信息内容
    select(all_of(1:instructor_cols_num), 学生编号, 信息内容)
})

# 4. 合并所有组结果并排序
final_long_data <- bind_rows(long_result_list) %>%
  arrange(FirstName, LastName, 学生编号) # 替换为你的讲师唯一标识列

精准分组优化(可选)

如果你的数据中"Student1 age"是每组学生的第一列,可以用它来定位分组起始位置,避免讲师列数量变化导致的错误:

# 找到Student1 age的列索引
student1_start <- which(colnames(actual_data) == "Student1 age")
# 手动定义4组学生的列范围
student_groups <- list(
  student1_start:(student1_start + student_cols_per_group - 1),
  (student1_start + student_cols_per_group):(student1_start + 2*student_cols_per_group - 1),
  (student1_start + 2*student_cols_per_group):(student1_start + 3*student_cols_per_group - 1),
  (student1_start + 3*student_cols_per_group):(student1_start + 4*student_cols_per_group - 1)
)

# 后续处理同上述代码...

内容的提问来源于stack exchange,提问作者beth_9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:35:54