R语言:将DataFrame转换为按卡片、学生分层的嵌套列表
数据格式(txt格式)
Time ; Source ; Action YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Student 2 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Mathematics; Reading succesful YYYY-MM-DD ; Student 2 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card History ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in
需求说明
- 先将DataFrame按
Action列值为"Reading succesful"的行分割为对应卡片的子列表; - 再将每个卡片子列表按
Action列值为"initialised"的行分割为对应学生的子列表; - 每个学生子列表需包含对应书籍记录,理想状态下附带卡片及学生自身的
Time和Action信息; - 期望最终数据结构为:
test$ [[card xxx]]$ [[Student 1]], [[Student 2]], etc [[card yyy]] [[Student 1]], [[Student 2]], etc
已尝试的代码
test <- split(i, cumsum(test$`b`$Text == "Reading succesful"))
为列表命名的代码:
for (a in test) { names(test)<-sapply(test, `[[`, 1,2) }
但后续循环分割学生子列表的操作未成功,寻求解决方案。
解决方案
步骤1:读取并预处理数据
先确保数据正确读入为DataFrame,处理分隔符和多余空格:
# 读取数据(如果是本地文件,替换为read.delim("你的文件路径", sep = ";", strip.white = TRUE)) df <- read.delim(text = "Time ; Source ; Action YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Student 2 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Mathematics; Reading succesful YYYY-MM-DD ; Student 2 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card History ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in YYYY-MM-DD ; Card Biology ; Reading succesful YYYY-MM-DD ; Student 1 ; initialised YYYY-MM-DD ; Book 1 ; first check out YYYY-MM-DD ; Book 2 ; Second check out YYYY-MM-DD ; Book 3 ; check in", sep = ";", strip.white = TRUE)
步骤2:按卡片分割数据
标记卡片分组并分割,同时给子列表命名为对应卡片名称:
# 标记每个卡片组:每遇到"Reading succesful"就开启新组 df$card_group <- cumsum(df$Action == "Reading succesful") # 分割为卡片子列表 card_list <- split(df, df$card_group) # 给卡片子列表命名为对应的卡片名称 names(card_list) <- sapply(card_list, function(x) x$Source[1])
步骤3:按学生分割每个卡片子列表
遍历每个卡片子列表,分割为学生子列表,同时保留卡片信息:
# 处理每个卡片子列表,生成学生子列表 final_list <- lapply(card_list, function(card_df) { # 标记学生组:从第二行开始,每遇到"initialised"就开启新组,第一行卡片记录归为0组 student_group <- c(0, cumsum(card_df$Action[-1] == "initialised")) card_df$student_group <- student_group # 分割为学生子列表,排除0组(卡片记录) student_list <- split(card_df, card_df$student_group)[-1] # 给学生子列表命名为对应学生名称 names(student_list) <- sapply(student_list, function(x) x$Source[which(x$Action == "initialised")]) # 给每个学生子列表添加卡片元信息(可选,方便后续调用) student_list <- lapply(student_list, function(student_df) { attr(student_df, "card_info") <- card_df[1, ] student_df }) return(student_list) })
验证结果
查看最终结构和内容:
# 查看Card Biology下的Student 1记录 final_list[["Card Biology"]][["Student 1"]] # 查看该学生对应的卡片信息 attr(final_list[["Card Biology"]][["Student 1"]], "card_info")
内容的提问来源于stack exchange,提问作者Romeo
相关产品推荐
相关产品推荐

