将循环转换为应用,iris示例
我有一段代码可以通过使用“iris”数据集来编写(不过我的数据集要大得多) 其思想是计算一个物种的所有元素与其他物种的所有元素之间的所有可能距离 使用几何距离计算元素1和元素2的距离,如下所示: 距离=((萼片宽度元素1-萼片宽度元素2)^2+(花瓣长度元素1-花瓣长度元素2)^2)^0.5 如果该距离低于阈值,则存储该值以供进一步分析 我能够使用for循环编写任务,但我相信其中一个“apply”函数可以加快代码的速度并使其更具可读性 代码如下:将循环转换为应用,iris示例,r,for-loop,optimization,apply,R,For Loop,Optimization,Apply,我有一段代码可以通过使用“iris”数据集来编写(不过我的数据集要大得多) 其思想是计算一个物种的所有元素与其他物种的所有元素之间的所有可能距离 使用几何距离计算元素1和元素2的距离,如下所示: 距离=((萼片宽度元素1-萼片宽度元素2)^2+(花瓣长度元素1-花瓣长度元素2)^2)^0.5 如果该距离低于阈值,则存储该值以供进一步分析 我能够使用for循环编写任务,但我相信其中一个“apply”函数可以加快代码的速度并使其更具可读性 代码如下: threshold=20 lsp_names=u
threshold=20
lsp_names=unique(iris$Species) #define a vector of names for each unique species
for(n1 in 1:(length(lsp_names)-1) ){
for(n2 in (n1+1):length(lsp_names)){
n_spec1=lsp_names[n1] ## name of the species 1
n_spec2=lsp_names[n2] ## name of the species 2
## generate a data frame for the species with name n_spec1
gph1=iris[iris$Species==n_spec1,]
## generate a data frame for the species with name n_spec2
gph2=iris[iris$Species==n_spec2,]
dist_values=NULL
## loop trough all possible couples between the species n_spec1 and n_spec2,
## evaluate the distance and store it if it is lower than the threshold
for(i in 1:nrow(gph1)){
for(j in 1:nrow(gph2)){
d=((gph1$Sepal.Width[i]-gph2$Sepal.Width[j])^2 + (gph1$Petal.Length[i]-gph2$Petal.Length[j])^2)^0.5
if(d<=threshold){
dist_values=c(dist_values,d)
}
}
}
## print a summary
a_std=sd(dist_values)
a_mean=mean(dist_values)
message(sprintf("distance between:%s %s mean:%f sigma:%f\n", n_spec1, n_spec2, a_mean, a_std))
}
}
我已经重写了您的代码,以消除物种循环和个体循环中的for循环 首先,不需要通过个人来计算距离。因为向量化的
dist()
函数可以找到矩阵中所有行对之间的欧几里德距离,就像您正在做的那样
其次,我们可以使用combn()
函数列出所有物种对,然后找到每个物种对中所有个体之间的平均距离
代码
这是代码(我没有包括您的摘要打印消息)
跨物种距离的平均值和标准偏差列表:
[[1]]
mean sd
2.9239210 0.4424981
[[2]]
mean sd
4.1465515 0.5578919
[[3]]
mean sd
1.3891000 0.7034196
我已经重写了您的代码,以消除物种循环和个体循环中的for循环 首先,不需要通过个人来计算距离。因为向量化的
dist()
函数可以找到矩阵中所有行对之间的欧几里德距离,就像您正在做的那样
其次,我们可以使用combn()
函数列出所有物种对,然后找到每个物种对中所有个体之间的平均距离
代码
这是代码(我没有包括您的摘要打印消息)
跨物种距离的平均值和标准偏差列表:
[[1]]
mean sd
2.9239210 0.4424981
[[2]]
mean sd
4.1465515 0.5578919
[[3]]
mean sd
1.3891000 0.7034196
这个怎么样?您可以将数据集连接到自身,然后过滤出物种相同的行,以便获得物种不同的宽数据框:
ii <- merge(iris, iris, by = NULL, all = TRUE)
ii <- ii[with(ii, as.numeric(ii$Species.x) < as.numeric(ii$Species.y)), ]
但是,我没有得到你得到的值,我也不知道为什么。这个怎么样?您可以将数据集连接到自身,然后过滤出物种相同的行,以便获得物种不同的宽数据框:
ii <- merge(iris, iris, by = NULL, all = TRUE)
ii <- ii[with(ii, as.numeric(ii$Species.x) < as.numeric(ii$Species.y)), ]
但是,我没有得到你得到的值,我也不知道为什么。这也是一个很好的解决方案,你得到不同值的唯一原因是你使用花瓣宽度和萼片长度,但问题是使用花瓣长度和萼片宽度:-DAha-很好!我看的是问题文本中的公式,而不是代码。我的坏:-)我的坏事实上,我会纠正这个问题。谢谢你的代码,我将尝试调整它以适应我的问题。这也是一个很好的解决方案,你得到不同值的唯一原因是你使用花瓣宽度和萼片长度,但问题使用花瓣长度和萼片宽度:-DAha-很好!我看的是问题文本中的公式,而不是代码。我的坏:-)我的坏事实上,我会纠正这个问题。谢谢你的代码,我将尝试调整它以适应我的问题。对不起,但是阈值呢?没错,对于iris的例子来说并不重要,但对于我的数据来说,这是至关重要的。在计算平均值之前,我添加了一行删除所有高于阈值的值。对不起,阈值呢?没错,对于iris的例子来说并不重要,但对于我的数据来说,这是至关重要的。在计算平均值之前,我添加了一行删除所有高于阈值的值。
ii <- merge(iris, iris, by = NULL, all = TRUE)
ii <- ii[with(ii, as.numeric(ii$Species.x) < as.numeric(ii$Species.y)), ]
ii$dist <- sqrt((ii$Petal.Width.x - ii$Petal.Width.y)^2 + (ii$Sepal.Length.x - ii$Sepal.Length.y)^2)
aggregate(ii[, 'dist'], by = list(ii$Species.x, ii$Species.y), mean)
Group.1 Group.2 x
1 setosa versicolor 1.497375
2 setosa virginica 2.441457
3 versicolor virginica 1.166729