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

基于特定字符位置截取字符串创建新变量的R语言技术问题

解决subscript out of bounds错误并生成landowner_code变量

错误原因

  • 全局引用而非逐行处理:代码中调用str_locate_all(df2$site_name, "-")时,引用的是整个数据集的site_name列,而非当前行的单个值。即便用head(3)过滤了数据,逻辑仍关联完整的df2,其中包含无分隔符的ABCDE——该值的str_locate_all返回空矩阵,尝试提取[2,2]自然触发下标越界。
  • 逻辑错位:str_locate_all返回的是每个字符串的分隔符位置集合,需要针对每行的site_name单独计算,而非对整个数据集的结果列表做批量map操作。

正确实现方法

方法1:修正逐行处理逻辑

使用rowwise()强制逐行计算,针对每行的site_name单独获取分隔符位置:

library(tidyverse)

df2 %>%
  rowwise() %>%
  mutate(
    region_code = case_when(
      site_name == "ABCDE" ~ "ABCDE",
      TRUE ~ str_sub(site_name, start = 2, end = str_locate(site_name, "-")[1,1] - 1)
    ),
    landowner_code = case_when(
      site_name == "ABCDE" ~ "ABCDE",
      TRUE ~ str_sub(site_name, start = 2, end = str_locate_all(site_name, "-")[[1]][2,1] - 1)
    )
  ) %>%
  ungroup()

方法2:字符串拆分后重组(更简洁)

用str_split将每个site_name拆分为字符向量,直接提取所需部分组合,逻辑更直观:

df2 %>%
  mutate(
    parts = str_split(site_name, "-"),
    region_code = case_when(
      site_name == "ABCDE" ~ "ABCDE",
      TRUE ~ map_chr(parts, ~ .x[2])
    ),
    landowner_code = case_when(
      site_name == "ABCDE" ~ "ABCDE",
      TRUE ~ map_chr(parts, ~ str_c(.x[2], .x[3], sep = "-"))
    )
  ) %>%
  select(-parts)

方法3:用separate拆分列(可读性强)

借助tidyr::separate将site_name按分隔符拆分,再按需组合目标变量:

df2 %>%
  # 保留原始列用于最终输出
  mutate(original_site = site_name) %>%
  separate(site_name, into = c("prefix", "region", "landowner_part"), sep = "-", fill = "right") %>%
  mutate(
    region_code = case_when(
      is.na(prefix) ~ original_site,
      TRUE ~ region
    ),
    landowner_code = case_when(
      is.na(prefix) ~ original_site,
      TRUE ~ str_c(region, landowner_part, sep = "-")
    )
  ) %>%
  select(site_name = original_site, region_code, landowner_code)

以上三种方法均能生成符合预期的结果,其中方法2和3的逻辑更清晰,也避免了手动处理字符位置的繁琐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:50:31