R sapply循环替换for循环

时间:2017-07-04 13:57:39

标签: r for-loop sapply

之前我已成功将 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]

你已经知道的另一部分,再次感谢!

3 个答案:

答案 0 :(得分:2)

如果misspell.listfix.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)

我建议对整个设置进行一些小改动。在使用像您这样的索引时,您需要确保订单始终相同。如果添加或删除名称,整个事情就会崩溃。

使用命名列表和lapplysapply,您的代码保持动态,您可以将多个拼写错误匹配到一个名称。

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"