基于特定字符位置截取字符串创建新变量的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
相关产品推荐
相关产品推荐

