为何apply函数丢失CRS?如何高效计算点向量地理函数?
问题:apply处理sf对象丢失CRS,求点向量地理计算的最优方法
问题复现
使用apply遍历sf格式的点数据时,会丢失CRS属性,导致地理函数(如st_distance)报错。复现代码如下:
library(tidyverse) library(sf) # 生成1000个经纬度点,转为sf格式并设置CRS df1 <- data.frame(lat = runif(1000, 30, 33.4), long = runif(1000, -95, -82)) %>% st_as_sf(coords = c("long", "lat"), crs = 4326) # 单个参考点,设置相同CRS df2 <- data.frame(lat = 32, long = -96) %>% st_as_sf(coords = c("long", "lat"), crs = 4326) # 运行此代码会报错 apply(df1, 1, function(x) st_distance(x, df2))
运行后报错:Error in st_distance(x, df2) : st_crs(x) == st_crs(y) is not TRUE
但以下两种方式可正常运行:
# 直接取单行计算 st_distance(df1[1,], df2) # for循环遍历计算 final.df <- NULL for(i in 1:nrow(df1)){ ith.distance <- st_distance(df1[i,], df2) final.df <- rbind(final.df, ith.distance) }
for循环效率较低,求最优处理方法。
解决方案
报错原因
apply会将sf对象强制转换为普通矩阵/数据框,丢失了sf对象特有的CRS元数据,导致st_distance无法校验两个对象的CRS一致性。
最优方法
直接利用st_distance的向量化特性,无需手动遍历:
# 批量计算df1所有点到df2的距离 distances <- st_distance(df1, df2)
st_distance原生支持批量计算,传入两个sf对象时,会自动计算第一个对象中每个点与第二个对象中每个点的距离,返回矩阵结果。若仅需单个参考点的距离,结果会是列向量,可直接转为数据框:
final.df <- as.data.frame(distances) colnames(final.df) <- "distance_to_ref_point"
若确实需要逐行处理sf对象,不要用apply,改用sf兼容的purrr系列函数保留属性:
library(purrr) distances <- map_dbl(df1, ~st_distance(.x, df2))
内容的提问来源于stack exchange,提问作者Alex Krohn
相关产品推荐
相关产品推荐

