R sapply循环替换for循环
R sapply loop to replace for loop
我之前已经成功将for循环切换到sapply循环,
我知道一个事实 (system.time()) 它们更快。
但我的思维仍然以 for 循环的方式工作...
请帮我转换这个 for 循环案例:
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]
)
但它只是 returns 我的原始向量。
谢谢!
编辑 1:
misspell.list 和 fix.list 是由下面的 adist() 自动创建的,原始的 names.list 有 665 个元素。我的 for() 解决方案 returns 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 霸主 我来这里只是为了展示我的另一个 for-sapply 与 adist()
一起使用的替换
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]
另一部分你已经知道了,再次感谢!
如果 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"
使用 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"
我建议对您的整个设置进行一些小改动。当像您一样使用索引时,您需要确保顺序始终相同。如果你添加或删除一个名字,整个事情就会分崩离析。
使用命名列表和 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"
我之前已经成功将for循环切换到sapply循环, 我知道一个事实 (system.time()) 它们更快。
但我的思维仍然以 for 循环的方式工作...
请帮我转换这个 for 循环案例:
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]
)
但它只是 returns 我的原始向量。
谢谢!
编辑 1:
misspell.list 和 fix.list 是由下面的 adist() 自动创建的,原始的 names.list 有 665 个元素。我的 for() 解决方案 returns 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 霸主 我来这里只是为了展示我的另一个 for-sapply 与 adist()
一起使用的替换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]
另一部分你已经知道了,再次感谢!
如果 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"
使用 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"
我建议对您的整个设置进行一些小改动。当像您一样使用索引时,您需要确保顺序始终相同。如果你添加或删除一个名字,整个事情就会分崩离析。
使用命名列表和 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"