让我们假设我有以下变量:
a <- c('one','two','three')
b <- c('one|on','two|wo',"three|thre")
c <- c('there is one','there one is ','there is one three two')
我想要一个具有以下结果的新变量:
d
[1] "one" "one" "three"
我要做的是查找文本中是否有单词one
或on
,然后为新变量{{1}分配新值one
}}。此外,如果d
中有多个值,则层次结构应该来自最后一个值。
我能做的是以下几点:
a
同样可以在一个简单的循环中完成。但还有其他方式更优雅吗?
答案 0 :(得分:0)
它并不是那么优雅,但是这个功能可以满足您的需求:
funny_replace <- function(c, b, a) {
max_or_null <- function(x) {
if (length(x) != 0) max(x) else NULL
}
multi_grep <- function(b, x) {
which(sapply(b, grepl, x))
}
replace_one <- function(s, b, a) {
a[max_or_null(multi_grep(b, s))]
}
unlist(sapply(c, replace_one, b, a))
}
funny_replace(c, b, a)
# there is one there one is there is one three two
# "one" "one" "three"
它的工作原理如下:max_or_null
用于返回向量的最大值,如果向量为空则返回NULL
。稍后会使用此选项来确保正确处理c
中未匹配b
的模式的元素。
multi_grep
在单个字符串中搜索多个模式(通常grep执行相反的操作:多个字符串中的一个模式)并返回找到的模式的索引。
replace_one
只需一个字符串并检查,使用b
找到multi_grep
中的哪些模式。然后使用max_or_null
返回这些索引中最大的索引,如果没有匹配则返回NULL。最后,从a
中选择具有此索引的元素。
replace_one
应用于c
的每个元素以获得所需的结果。
我认为,它比你的或者for循环更具功能性,因为它避免了重复分配。另一方面,它看起来有点复杂。
顺便说一句:我在任何地方都使用了a
,b
和c
,以便更轻松地将我的代码与您的示例相匹配。但是,这不是一个好的做法。