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

R语言:ifelse嵌套str_split_i实现双条件匹配的问题

利用映射文件替换长文件中的学生姓名

需求说明

  • 用较短的映射文件(含学生全名、考试文件名)替换长文件中的学生姓名
  • 匹配条件:同时满足学生名前缀一致、考试文件名一致
  • 长文件仅包含学生名前缀和考试文件名,需从映射文件中提取对应全名

数据定义

映射文件 student_file_mapping

student_file_mapping <- data.frame(
  student=c("paul_johns","mary_bash","paul_simons"),
  file=c("johns bash hunter 2022_exam1.paul_johns.csv",
         "johns bash hunter 2022_exam1.mary_bash.csv",
         "nichols simons smith 2022_exam1.paul_simonsh.csv")
)

输出结果:

student                                             file
1  paul_johns      johns bash hunter 2022_exam1.paul_johns.csv
2   mary_bash       johns bash hunter 2022_exam1.mary_bash.csv
3 paul_simons nichols simons smith 2022_exam1.paul_simonsh.csv

长文件 data_full

data_full <- data.frame(
  student_file=c("paul_johns bash hunter 2022_exam1",
                 "paul_johns bash hunter 2022_exam1",
                 "paul_johns bash hunter 2022_exam1",
                 "mary_johns bash hunter 2022_exam1",
                 "mary_johns bash hunter 2022_exam1",
                 "mary_johns bash hunter 2022_exam1",
                 "paul_nichols simons smith 2022_exam1",
                 "paul_nichols simons smith 2022_exam1",
                 "paul_nichols simons smith 2022_exam1",
                 "paul_johns bash hunter 2022_exam1",
                 "mary_johns bash hunter 2022_exam1",
                 "paul_nichols simons smith 2022_exam1"),
  File=c("johns bash hunter 2022_exam1.csv", 
         "johns bash hunter 2022_exam1.csv",
         "johns bash hunter 2022_exam1.csv",
         "johns bash hunter 2022_exam1.csv",
         "johns bash hunter 2022_exam1.csv",
         "johns bash hunter 2022_exam1.csv",
         "nichols simons smith 2022_exam1.csv",
         "nichols simons smith 2022_exam1.csv",
         "nichols simons smith 2022_exam1.csv",
         "jons bash hunter 2022_exam1.csv",
         "johns bash hunter 2022_exam1.csv",
         "nichols simons smith 2022_exam1.csv")
)

输出结果:

student_file                                File
1     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
2     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
3     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
4     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
5     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
6     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
7  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv
8  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv
9  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv
10    paul_johns bash hunter 2022_exam1     jons bash hunter 2022_exam1.csv
11    mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv
12 paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv

尝试的代码及问题

提取匹配字段的代码

提取学生名前缀:

# 从映射文件提取前缀
str_split_i(student_file_mapping$student,"_",1)[1] -> paul
# 从长文件提取前缀
str_split_i(data_full$student_file,"_",1)[1] -> paul

提取考试文件名:

# 从映射文件提取考试文件名
str_split_i(student_file_mapping$file,"\\.",1)[1] -> "johns bash hunter 2022_exam1"
# 从长文件提取考试文件名
str_split_i(data_full$File,".csv",1)[1] -> "johns bash hunter 2022_exam1"

错误的匹配逻辑(ifelse)

尝试用ifelse实现匹配,但仅能为长文件中每个学生匹配一行,实际数据集还会报错longer object length is not a multiple of shorter object length:

data_full$student <- ifelse( 
  str_split_i(student_file_mapping$file,"\\.",1) == str_split_i(data_full$File,".csv",1) & 
  str_split_i(student_file_mapping$student,"_",1) == str_split_i(data_full$student_file,"_",1) , 
  paste0(student_file_mapping$student),
  "NOT FOUND" 
)

执行后结果:

student_file                                File     student
1     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv  paul_johns
2     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   NOT FOUND
3     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   NOT FOUND
4     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   NOT FOUND
5     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   mary_bash
6     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   NOT FOUND
7  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv   NOT FOUND
8  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv   NOT FOUND
9  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv paul_simons
10    paul_johns bash hunter 2022_exam1     jons bash hunter 2022_exam1.csv   NOT FOUND
11    mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   mary_bash
12 paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv paul_simons

正确解决方案

问题出在ifelse是逐元素循环,当两个对象长度不匹配时会触发循环补齐,导致匹配错误。正确做法是先为两个数据集生成匹配键,再用连接操作完成匹配:

步骤1:加载必要包

library(dplyr)
library(stringr)

步骤2:处理映射文件,生成匹配键

mapping_processed <- student_file_mapping %>%
  mutate(
    # 提取学生名前缀
    student_prefix = str_split_i(student, "_", 1),
    # 提取考试文件名(去掉后缀部分)
    exam_file = str_split_i(file, "\\.", 1)
  )

步骤3:处理长文件,生成匹配键

data_full_processed <- data_full %>%
  mutate(
    # 提取学生名前缀
    student_prefix = str_split_i(student_file, "_", 1),
    # 提取考试文件名(去掉.csv后缀)
    exam_file = str_remove(File, "\\.csv$")
  )

步骤4:通过匹配键连接两个数据集

result <- data_full_processed %>%
  left_join(mapping_processed, by = c("student_prefix", "exam_file")) %>%
  # 将未匹配到的项替换为"NOT FOUND"
  mutate(student = ifelse(is.na(student), "NOT FOUND", student)) %>%
  # 保留原长文件的列和匹配后的student列
  select(student_file, File, student)

最终结果

student_file                                File     student
1     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv  paul_johns
2     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv  paul_johns
3     paul_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv  paul_johns
4     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   mary_bash
5     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   mary_bash
6     mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   mary_bash
7  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv paul_simons
8  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv paul_simons
9  paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv paul_simons
10    paul_johns bash hunter 2022_exam1     jons bash hunter 2022_exam1.csv   NOT FOUND
11    mary_johns bash hunter 2022_exam1    johns bash hunter 2022_exam1.csv   mary_bash
12 paul_nichols simons smith 2022_exam1 nichols simons smith 2022_exam1.csv paul_simons

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:55:21