目的:我想自动化(循环)下面的代码,而不必为每个示例手动运行它。我有一个很烂的习惯,就是在基础上写很多东西,并且需要开始使用循环,我发现很难实现。
数据:我有两个数据帧:一个样本数据(sample)和一个参考数据(ref)。它们都包含相同的变量(x,y,z)。
代码说明:对于每个样本(sample $ sample_name),我想计算它与参考数据中每种情况的欧几里得距离。然后将结果用于对参考数据进行重新排序,以显示欧几里德(3维)空间中哪些点“最接近”样本数据点。
我当前的代码使我可以简单地替换示例名称(即“ s1”),然后重新运行代码,对.csv文件的文件名进行最后更改。输出是按最接近样品的顺序(在欧几里得空间中)的参考数据列表。
我想自动执行该过程(进入循环?),以便可以使用示例名称列表(samples $ sample_name)在两个数据帧上简单地运行该过程,并希望还可以自动将其导出到.csv文件。
任何帮助将不胜感激!
# Reference data
country<-c("Austria","Austria","Italy","Italy","Turkey","Romania","France")
x<-c(18.881,18.881,18.929,19.139,19.008,19.083,18.883)
y<-c(15.627,15.627,15.654,15.772,15.699,15.741,15.629)
z<-c(38.597,38.597,38.842,39.409,39.048,39.224,38.740)
pb_age<-c(-106,-106,-87,-6,-55,-26,-104)
ref<-data.frame(country,x,y,z,pb_age) # Reference data
# Sample data (for euclidean measurements against Reference data)
sample_name<-c("s1","s2","s3")
x2<-c(18.694,18.729,18.731)
y2<-c(15.682,15.683,15.677)
z2<-c(38.883,38.989,38.891)
pb_age2<-c(120,97,82)
samples<-data.frame(sample_name,x2,y2,z2,pb_age2) # Sample data
colnames(samples)<-c("sample_name","x","y","z","pb_age") # To match Reference data headings
# Euclidean distance measurements
library(fields) # Need package for Euclidean distances
# THIS IS WHAT I WANT TO AUTOMATE/LOOP (BELOW)...
# Currently, I have to update the 'id' for each sample to get a result (for each sample)
id<-"s1" # Sample ID - this is simply changed so the following code can be re-run for each sample
# The code
x1<-samples[which(samples$sample_name==id),c("x","y","z")]
x2<-ref[,c("x","y","z")]
result_distance<-rdist(x1,x2) # Computing the Euclidean distance
result_distance<-as.vector(result_distance) # Saving the results as a vector
euclid_ref<-data.frame(result_distance,ref) # Creating a new data.frame adding the Euclidean distances to the original Reference data
colnames(euclid_ref)[1]<-"euclid_distance" # Updating the column name for the result
# Saving and exporting the results
results<-euclid_ref[order(euclid_ref$euclid_distance),] # Re-ordering the data.frame by the euclide distances, smallest to largest
write.csv(results, file="s1.csv") # Ideally, I want the file name to be the same as the SAMPLE id, i.e. s1, s2, s3...
循环将非常简单,但是更像R的解决方案将是利用矢量化和函数的apply-family:
result_distances <- data.frame(t(rdist(samples[, 2:4], ref[, 2:4])), ref)
colnames(result_distances)[1:3] <- rep("euclid_distance", 3)
# str(result_distances)
# 'data.frame': 7 obs. of 8 variables:
# $ euclid_distance: num 0.346 0.346 0.24 0.695 0.355 ...
# $ euclid_distance: num 0.424 0.424 0.25 0.594 0.286 ...
# $ euclid_distance: num 0.334 0.334 0.205 0.666 0.319 ...
# $ country : chr "Austria" "Austria" "Italy" "Italy" ...
# $ x : num 18.9 18.9 18.9 19.1 19 ...
# $ y : num 15.6 15.6 15.7 15.8 15.7 ...
# $ z : num 38.6 38.6 38.8 39.4 39 ...
# $ pb_age : num -106 -106 -87 -6 -55 -26 -104
通常,我们不会给多个列使用相同的名称,但是我们计划下一步将它们拔出:
results <- lapply(1:3, function(i) data.frame(result_distances[order(result_distances[, i]), c(i, 4:8)]))
names(results) <- samples$sample_name
现在,我们有了一个列表,results
其中包含名为“ s1”,“ s2”和“ s3”的三个数据帧。列表使将功能轻松应用于许多类似组织的数据集变得容易。例如results[["s1"]]
或results[[1]]
打印第一个样本的数据框。现在我们写出结果:
sapply(names(results), function(x) write.csv(results[[x]], file=paste0(x, ".csv")))
这将创建3个文件,“ s1.csv”,“ s2.csv”,“ s3.csv”。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句