在数据框的条目中使用ifelse函数插入单个字符
我有一个数据框,想要修改条目,确保末尾的数字指示符为两位数,即使记录的数字在1 到9 之间。为了说明,起初是这样的:
data <- data.frame(
V1 = c(1, 2, 3, NA, NA, NA, 4),
V2 = c("ABC", "BCD", "CDE", "AB12", "AB5", "AB3", "DEF")
)
num <- as.character(c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
new_data <- data %>%
mutate(V2 = ifelse (
is.na(V1),
ifelse(
str_sub(data$V2, -2, -2) %in% num,
data$V2,
str_sub(data$V2, -2, -3) <- 0
),
data$V2
))
最终我希望数据框的样子是这样的:
ideal_data <- data.frame(
V1 = c(1, 2, 3, NA, NA, NA, 4),
V2 = c("ABC", "BCD", "CDE", "AB12", "AB05", "AB03", "DEF")
)
这是我尝试过的方法:
我的假设是,这会通过检查 V1 是否存在NA来改变列 V2,如果没有NA,就保持原样;如果有NA,就检查倒数第二个字符是否包含在 num 中。如果是这种情况,就保留它;如果不是,则在该位置补一个零。
然而,实际产生的是下面的数据框:
> new_data
V1 V2
1 1 A0BC
2 2 B0CD
3 3 C0DE
4 NA AB12
5 NA 0
6 NA 0
7 4 D0EF
我到底哪里做错了?这个问题的解决方案是什么?
解决方案
你的误解在于 ifelse 的工作方式。ifelse 函数会对向量中每个元素(数据框的行)完整求值 test、yes 和 no 这三个参数,然后在 yes 与 no 之间选择来生成结果。因此,当你在内部的 ifelse 中进行赋值时,它会把倒数第三个字符在每个实例中都替换为0(并非仅在匹配为 TRUE 的情形)。接着 <- 的返回值是 0,所以 no 变成了由 0 组成的向量,这些就被放到了 test 为 FALSE 的位置。
核心信息是,不要在 ifelse 的参数里进行赋值。
如果你想按你的逻辑来做,那么最好逐行遍历,使用常规的 if 与 else,而不是 ifelse 函数。也许比使用 str_sub 更好的是,使用正则表达式进行匹配与替换,使用 str_replace(或 sub 等)来实现。下面给出一个可能实现你需求的调用示例:
V2 <- c("ABC", "BCD", "CDE", "AB12", "AB5", "AB3", "DEF")
str_replace(V2, "([^0-9])([0-9])$", "\\10\\2")
这段代码是在查找一个非数字,紧接着一个数字,直到字符串的末尾。然后把匹配到的非数字、字面量 0 和匹配到的数字一起替换掉。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。