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

基于变量顺序的条件标记:R语言实现A-B-C序列识别

问题描述

给定由事件A、B、C组成的序列(每个事件至少出现一次,可重复),需要为每个序列生成0/1标记向量,规则如下:

  • 每个序列中仅存在一个有效A和一个有效C,且有效A必须在有效C之前
  • 有效A和有效C之间可以包含任意数量的B
  • 属于这个有效A-B-C区间的事件标记为1,其余标记为0
  • 若序列中不存在符合A在C之前的情况(如B-A-C、C-B-A),则所有位置标记为0

示例序列与预期输出:

  • 序列1:c("A", "B", "C") → 输出c(1,1,1)
  • 序列2:c("A", "A", "B", "B", "C") → 输出c(0,1,1,1,1)(取最后一个在C之前的A作为有效A)
  • 序列3:c("B", "A", "C") → 输出c(0,0,0)(A之前有B,不符合规则)
  • 序列4:c("C", "B", "A") → 输出c(0,0,0)(C在A之前,无有效A-C对)
  • 序列5:c("A", "B", "B", "C", "A") → 输出c(1,1,1,1,0)(C之后的A标记为0)
解决方案

Base R 实现(使用lapply)

核心逻辑:对每个序列,先定位第一个出现的C,再找到该C之前最后一个A;若该A之前存在非A元素,则全标记为0,否则标记A到C区间为1。

# 定义单序列处理函数
mark_valid_sequence <- function(seq) {
  # 定位第一个C的位置
  c_pos <- which(seq == "C")
  if (length(c_pos) == 0) return(rep(0, length(seq)))
  first_c <- c_pos[1]
  
  # 定位第一个C之前最后一个A的位置
  a_pos <- which(seq[1:first_c] == "A")
  if (length(a_pos) == 0) return(rep(0, length(seq)))
  last_a <- a_pos[length(a_pos)]
  
  # 检查有效A之前是否有非A元素
  if (any(seq[1:(last_a - 1)] != "A")) {
    return(rep(0, length(seq)))
  }
  
  # 生成标记向量
  result <- rep(0, length(seq))
  result[last_a:first_c] <- 1
  return(result)
}

# 应用到序列列表
s.indexed_base <- lapply(s.list, mark_valid_sequence)
s.indexed_base

Tidyverse 实现

通过分组处理数据框,结合位置判断完成标记:

library(tidyverse)

s.df_marked <- s.df %>%
  group_by(group) %>%
  mutate(
    pos = row_number(),
    # 找到本组第一个C的位置
    first_c = min(pos[value == "C"]),
    # 找到第一个C之前最后一个A的位置
    last_a_before_c = max(pos[value == "A" & pos <= first_c]),
    # 判断是否符合有效区间条件
    valid = ifelse(
      is.finite(last_a_before_c) & all(value[1:(last_a_before_c - 1)] == "A"),
      pos >= last_a_before_c & pos <= first_c,
      FALSE
    ),
    # 转换为0/1标记
    index = as.integer(valid)
  ) %>%
  ungroup() %>%
  select(-pos, -first_c, -last_a_before_c, -valid)

s.df_marked

内容的提问来源于stack exchange,提问作者gregor-fausto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:37:44