作为一个R新手,我认为是时候从for循环到apply函数了。我正在努力解决这些代码问题,并且想知道是否有人可以提供帮助。
我有一个功能:
earth.dist <- function (long1, lat1, long2, lat2)
{
rad <- pi/180
a1 <- lat1 * rad
a2 <- long1 * rad
b1 <- lat2 * rad
b2 <- long2 * rad
dlon <- b2 - a2
dlat <- b1 - a1
a <- (sin(dlat/2))^2 + cos(a1) * cos(b1) * (sin(dlon/2))^2
c <- 2 * atan2(sqrt(a), sqrt(1 - a))
R <- 6378.145
d <- R * c
return(d)
}
现在我有两个不同的数据集,一个包含预定的大城市列表及其长/纬度坐标,另一个包含美国随机位置的长/纬坐标。我写的for循环基本上计算随机位置的每个长/纬度坐标与预定大城市的长/纬度坐标之间的差异,并将随机位置放在最近城市所在的州。每个城市在预定列表中,它旁边有一个State,它插入随机城市电子表格的新列中。
有没有办法可以使用apply执行此循环?这个循环实际上可以做到这一点,但它太长而且笨重,我知道应用函数可以做得更好。
这是循环:
for(i in 1:nrow(randomlocations)){
vec<-vector()
for(j in 1:nrow(predeterminedcities)){
a<-earth.dist(randomlocations$long[i],randomlocations$lat[i], predeterminedcities$long[j], predeterminedcities$lat[j])
vec[[j]]<-a
}
ind<- as.numeric(which.min(vec))
randomlocations$state[i]<-as.character(predeterminedcities$STATE[ind])
print(i)
}
答案 0 :(得分:1)
由于您的函数已经过矢量化,因此您可以使用outer
通过将索引传递到数据框来计算距离矩阵。通过max.col
弹出结果以找到最小距离的索引,然后使用它来查找州名:
#fake test data
randomlocations <- data.frame(lon=runif(100, -80,-70), lat=runif(100, 45,75))
predeterminedcities <- head(randomlocations, 50)
predeterminedcities$STATE <- state.name
randomlocations$state <- predeterminedcities[
max.col( -
outer(1:nrow(randomlocations), 1:nrow(predeterminedcities),
function(i,j) earth.dist(randomlocations$lon[i], randomlocations$lat[i],
predeterminedcities$lon[j], predeterminedcities$lat[j])
)
), "STATE"]
如果变量名称较短,这很容易适合一行。