在R中按相对位置为分组后的数据框添加标签
解决方案
可以使用dplyr包实现分组逻辑,并自定义序数标签函数来生成所需的分组标签,步骤如下:
1. 构造示例数据
首先将你提供的数据转换为R数据框:
library(dplyr) df <- tibble( Term = c(1000, 1020, 1020, 1040, 1040, 1040, 1060, 1020, 1060), Course = c("ABDC1101", "ABCD1101", "ABCD1101", "ABCD1101", "ABCD1101", "ABCD1101", "ABCD1101", "EFGH1101", "EFGH1101"), Mark = c("", "", "", "*", "*", "*", "", "", "*") )
2. 自定义序数转换函数
用于将数字转换为first、second这类序数词:
ordinal_label <- function(n) { switch(as.character(n), "1" = "first", "2" = "second", "3" = "third", # 可根据需求扩展更多序数 as.character(n) ) }
3. 分组处理生成标签
按Course分组后,确定每组的基准Term(Mark为*的Term),再根据当前Term与基准Term的相对位置生成标签:
result_df <- df %>% group_by(Course) %>% mutate( # 获取当前组的基准Term base_term = unique(Term[Mark == "*"]), # 对组内唯一Term排序 sorted_terms = list(sort(unique(Term))), # 找到基准Term在排序后的索引 base_idx = if (length(base_term) > 0) match(base_term, sorted_terms[[1]]) else NA, # 找到当前Term在排序后的索引 term_idx = match(Term, sorted_terms[[1]]), # 生成Group标签 Group = case_when( # Mark为*的直接标记为base Mark == "*" ~ "base", # 基准Term存在,当前Term在基准之前 !is.na(base_idx) & term_idx < base_idx ~ paste0(ordinal_label(base_idx - term_idx), "_before"), # 基准Term存在,当前Term在基准之后 !is.na(base_idx) & term_idx > base_idx ~ paste0(ordinal_label(term_idx - base_idx), "_after"), # 处理无基准Term的组,参考全局最小基准Term计算 TRUE ~ { global_min_base <- min(df$Term[df$Mark == "*"], na.rm = TRUE) # 假设Term间隔为20,与示例一致 gap_count <- (global_min_base - Term) %/% 20 paste0(ordinal_label(gap_count), "_before") } ) ) %>% ungroup() %>% # 移除中间计算变量 select(-base_term, -sorted_terms, -base_idx, -term_idx)
4. 查看结果
运行后输出的result_df与你期望的结果一致:
print(result_df, n = Inf)
输出:
# A tibble: 9 × 4 Term Course Mark Group <dbl> <chr> <chr> <chr> 1 1000 ABDC1101 "" second_before 2 1020 ABCD1101 "" first_before 3 1020 ABCD1101 "" first_before 4 1040 ABCD1101 "*" base 5 1040 ABCD1101 "*" base 6 1040 ABCD1101 "*" base 7 1060 ABCD1101 "" first_after 8 1020 EFGH1101 "" first_before 9 1060 EFGH1101 "*" base
内容的提问来源于stack exchange,提问作者kate88
相关产品推荐
相关产品推荐

