之前我已成功将 for loops 切换为 sapply loops 我知道一个事实(system.time())他们更快。
但我的思维仍然以循环方式运作......
请帮我转换这个循环案例:
names.list <- c("Anna", "Ana", "Albert", "Albort", "Rob", "Robb", "Tommy", "Tommie")
misspell.list <- c("Anna", "Albort", "Robb", "Tommie")
fix.list <- c("Ana", "Albert", "Rob", "Tommy")
for(i in 1:length(fix.list)) {
names.list[which(names.list == misspell.list[i])] <- fix.list[i]
}
names.list
给sapply()
到目前为止,我得到了:
sapply(seq_along(fix.list), function(x)
names.list[which(names.list == misspell.list[x])] <- fix.list[x]
)
但它只返回原始矢量。
谢谢!
编辑1:
misspell.list和fix.list是由adist()bellow自动创建的,原始names.list有665个元素。我的for()解决方案返回length(unique(names.list))
= 653个元素
# will do another sapply() substitution here soon
for(i in 1:(length(names.list)-1)) {
distancias[i] <- adist(names.list[i], names.list[i+1])
}
# fix list
misspell.list <- names.list[which(distancias < 2)]
fix.list <- names.list[which(distancias < 2) +1]
编辑2:多亏了你,现在我是一个 sapply霸主而我在这里只是为了展示我用adist()使用的其他 for-sapply 替换
nomes <- sort(unique(names.list))
distancias <- rep(10, length(nomes))
#adist() for finding misspelling
sapply(seq_along(nomes),
function(x) {
if(x<length(nomes)) {
distancias[x] <<- adist(nomes[x], nomes[x+1])
}
}
)
# fix list
misspell.list <- names.list[which(distancias < 2)]
fix.list <- names.list[which(distancias < 2) +1]
你已经知道的另一部分,再次感谢!
答案 0 :(得分:2)
如果misspell.list
和fix.list
之间存在一对一的对应关系,则可以使用match
函数取消循环
names.list[match(misspell.list,names.list)] <- fix.list
names.list
#[1] "Ana" "Ana" "Albert" "Albert" "Rob" "Rob" "Tommy" "Tommy"
答案 1 :(得分:2)
使用match
的解决方案要好得多,但就您尝试做的事情而言,这将有效。首先,您不需要which
。您还需要使用<<-
运算符来告诉循环中定义的内部函数使用全局环境而不是它自己的本地环境 - 否则它不会更改names.list
,只会更改它的副本。
sapply(seq_along(fix.list), function(x)
names.list[names.list == misspell.list[x]] <<- fix.list[x]
)
names.list
[1] "Ana" "Ana" "Albert" "Albert" "Rob" "Rob" "Tommy" "Tommy"
答案 2 :(得分:1)
我建议对整个设置进行一些小改动。在使用像您这样的索引时,您需要确保订单始终相同。如果添加或删除名称,整个事情就会崩溃。
使用命名列表和lapply
或sapply
,您的代码保持动态,您可以将多个拼写错误匹配到一个名称。
misspell.list <- list(
'Anna' = 'Ana',
'Albort' = 'Albert',
'Robb' = 'Rob',
'Tommie' = 'Tommy'
)
names.list <- c("Anna", "Ana", "Albert", "Albort", "Rob", "Robb", "Tommy", "Tommie")
> sapply(names.list,function(x) ifelse(x %in% names(misspell.list),misspell.list[[x]],x))
Anna Ana Albert Albort Rob Robb Tommy Tommie
"Ana" "Ana" "Albert" "Albert" "Rob" "Rob" "Tommy" "Tommy"
为了说明我的意思,我使用sample
来重新排列names.list
向量并将其扩展为20个名称。这表明顺序和长度没有影响。
sapply(names.list[sample(1:length(names.list),20,replace = T)],function(x) ifelse(x %in% names(misspell.list),misspell.list[[x]],x))
Albert Tommie Rob Tommie Rob Tommy Ana Robb Tommie Ana Tommie Albort Ana Albert Albert Albort
"Albert" "Tommy" "Rob" "Tommy" "Rob" "Tommy" "Ana" "Rob" "Tommy" "Ana" "Tommy" "Albert" "Ana" "Albert" "Albert" "Albert"
Tommy Tommy Tommy Ana
"Tommy" "Tommy" "Tommy" "Ana"