r语言 删除循环数据
在我的上一篇博客文章中,我展示了似然函数从Think Bayes到R的转换,并且在我第一次尝试此函数时,我使用了两个嵌套的for循环。
likelihoods = function(names, mixes, observations) {
scores = rep(1, length(names))
names(scores) = names
for(name in names) {
for(observation in observations) {
scores[name] = scores[name] * mixes[[name]][observation]
}
}
return(scores)
}
Names = c("Bowl 1", "Bowl 2")
bowl1Mix = c(0.75, 0.25)
names(bowl1Mix) = c("vanilla", "chocolate")
bowl2Mix = c(0.5, 0.5)
names(bowl2Mix) = c("vanilla", "chocolate")
Mixes = list("Bowl 1" = bowl1Mix, "Bowl 2" = bowl2Mix)
Mixes
Observations = c("vanilla", "vanilla", "vanilla", "chocolate")
l = likelihoods(Names, Mixes, Observations)
> l / sum(l)
Bowl 1 Bowl 2
0.627907 0.372093
我们传入一个碗矢量,一个嵌套的字典,描述每个碗中的曲奇混合以及我们所做的观察。 该函数告诉我们,来自碗1的曲奇几乎有2/3的可能性,而来自碗2的曲奇的可能性刚好超过1/3。
在这种情况下,摆脱循环可能不会带来很多性能改进,但是我们应该能够编写出更简洁,更希望成为习惯用法的东西。
让我们从摆脱内部for循环开始。 可以通过调用Reduce函数来代替,如下所示:
likelihoods2 = function(names, mixes, observations) {
scores = rep(0, length(names))
names(scores) = names
for(name in names) {
scores[name] = Reduce(function(acc, observation) acc * mixes[[name]][observation], Observations, 1)
}
return(scores)
}
l2 = likelihoods2(Names, Mixes, Observations)
> l2 / sum(l2)
Bowl 1 Bowl 2
0.627907 0.372093
很好,我们仍然拥有与以前相同的概率。 现在摆脱外部for循环。 地图功能可以帮助我们:
likelihoods3 = function(names, mixes, observations) {
scores = rep(0, length(names))
names(scores) = names
scores = Map(function(name)
Reduce(function(acc, observation) acc * mixes[[name]][observation], Observations, 1),
names)
return(scores)
}
l3 = likelihoods3(Names, Mixes, Observations)
> l3
$`Bowl 1`
vanilla
0.1054688
$`Bowl 2`
vanilla
0.0625
我们得到一个列表,而不是一个矢量,我们需要使用unlist函数来修复它:
likelihoods3 = function(names, mixes, observations) {
scores = rep(0, length(names))
names(scores) = names
scores = Map(function(name)
Reduce(function(acc, observation) acc * mixes[[name]][observation], Observations, 1),
names)
return(unlist(scores))
}
l3 = likelihoods3(Names, Mixes, Observations)
> l3 / sum(l3)
Bowl 1.vanilla Bowl 2.vanilla
0.627907 0.372093
现在,我们有了这个令人讨厌的“香草”名称。 这很容易解决:
likelihoods3 = function(names, mixes, observations) {
scores = rep(0, length(names))
names(scores) = names
scores = Map(function(name)
Reduce(function(acc, observation) acc * mixes[[name]][observation], Observations, 1),
names)
result = unlist(scores)
names(result) = names
return(result)
}
l3 = likelihoods3(Names, Mixes, Observations)
> l3 / sum(l3)
Bowl 1 Bowl 2
0.627907 0.372093
稍微干净一点的替代方法利用了sapply函数:
likelihoods3 = function(names, mixes, observations) {
scores = rep(0, length(names))
names(scores) = names
scores = sapply(names, function(name)
Reduce(function(acc, observation) acc * mixes[[name]][observation], Observations, 1))
names(scores) = names
return(scores)
}
l3 = likelihoods3(Names, Mixes, Observations)
> l3 / sum(l3)
Bowl 1 Bowl 2
0.627907 0.372093
那是我目前为止最好的,但是我想知道我们是否可以使用矩阵运算以某种方式编写此版本–但这是下一次!
翻译自: https://www.javacodegeeks.com/2015/04/r-removing-for-loops.html
r语言 删除循环数据