我开始了一个“免费”开源项目,为地球海洋的pH创建一个新的数据集。
我从NOAA的开放数据集开始,用这些列创建了一个245万行数据集:
colnames(NOAA_NODC_OSD_SUR_pH_7to9)
[1] "Year" "Month" "Day" "Hour" "Lat" "Long" "Depth" "pH" 方法文档这里。
数据集这里.
我现在的目标是“合格”每一行(2.45米).为此,我需要计算Lat/Long的每个点到最近的海岸的距离。
因此,我正在寻找一种可以接受的方法: Lat/Long Out:距离海岸(距离海岸公里)。
有了这个,我就可以确定数据点是否会受到海岸污染的影响,比如附近的城市污水。
我已经在寻找一种方法来做这件事,但所有的一切似乎都需要我没有的软件包/软件。
如果有人愿意帮忙,我会很感激的。或者如果你知道一个简单的(免费)方法来完成这个任务,请告诉我.
我可以在R编程,壳牌脚本之类的工作,但不是专家.
发布于 2014-12-30 19:59:59
所以这里发生了几件事。首先,您的数据集似乎有pH和深度。因此,虽然有大约2.5MM的行,但只有大约20万行与depth=0 -仍然很多。
第二,要到达最近的海岸,你需要一个海岸线的形状文件。幸运的是,这是可用的这里,在优秀的自然地球网站。
第三,你的数据是长/拉(所以,单位=度),但是你想要距离公里,所以你需要转换你的数据(上面的海岸线数据也是长/拉,也需要转换)。转换的一个问题是,您的数据显然是全局的,任何全局转换都必然是非平面的。因此,准确与否将取决于实际的位置。正确的方法是对数据进行网格化,然后使用一组适合于任意网格的平面转换。这超出了这个问题的范围,所以我们将使用一个全局转换(mollweide)来让您了解它是如何在R.
library(rgdal) # for readOGR(...); loads package sp as well
library(rgeos) # for gDistance(...)
setwd(" < directory with all your files > ")
# WGS84 long/lat
wgs.84 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
# ESRI:54009 world mollweide projection, units = meters
# see http://www.spatialreference.org/ref/esri/54009/
mollweide <- "+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
df <- read.csv("OSD_All.csv")
sp.points <- SpatialPoints(df[df$Depth==0,c("Long","Lat")], proj4string=CRS(wgs.84))
coast <- readOGR(dsn=".",layer="ne_10m_coastline",p4s=wgs.84)
coast.moll <- spTransform(coast,CRS(mollweide))
point.moll <- spTransform(sp.points,CRS(mollweide))
set.seed(1) # for reproducible example
test <- sample(1:length(sp.points),10) # random sample of ten points
result <- sapply(test,function(i)gDistance(point.moll[i],coast.moll))
result/1000 # distance in km
# [1] 0.2185196 5.7132447 0.5302977 28.3381043 243.5410571 169.8712255 0.4182755 57.1516195 266.0498881 360.6789699
plot(coast)
points(sp.points[test],pch=20,col="red")

因此,这将读取数据集,提取Depth==0所在的行,并将其转换为SpatialPoints对象。然后,我们将从上面的链接下载到一个SpatialLines对象的海岸线数据库。然后用spTransform(...)变换到Mollweide投影,然后在rgeos包中用gDistance(...)计算出每个点与最近海岸之间的最小距离。
同样重要的是要记住,尽管有小数位,但这些距离只是近似的。
一个非常大的问题是速度:这个过程需要2分钟的距离(在我的系统上),所以所有的200,000公里运行大约需要6.7小时。理论上,一种选择是找到分辨率较低的海岸线数据库。
下面的代码将计算所有201,000段距离。
## not run
## estimated run time ~ 7 hours
result <- sapply(1:length(sp.points), function(i)gDistance(sp.points[i],coast))编辑:OP关于内核的评论让我认为这可能是一个从并行化中获得改进值得付出的努力的实例。下面是如何使用并行处理在Windows上运行这个程序。
library(foreach) # for foreach(...)
library(snow) # for makeCluster(...)
library(doSNOW) # for resisterDoSNOW(...)
cl <- makeCluster(4,type="SOCK") # create a 4-processor cluster
registerDoSNOW(cl) # register the cluster
get.dist.parallel <- function(n) {
foreach(i=1:n, .combine=c, .packages="rgeos", .inorder=TRUE,
.export=c("point.moll","coast.moll")) %dopar% gDistance(point.moll[i],coast.moll)
}
get.dist.seq <- function(n) sapply(1:n,function(i)gDistance(point.moll[i],coast.moll))
identical(get.dist.seq(10),get.dist.parallel(10)) # same result?
# [1] TRUE
library(microbenchmark) # run "benchmark"
microbenchmark(get.dist.seq(1000),get.dist.parallel(1000),times=1)
# Unit: seconds
# expr min lq mean median uq max neval
# get.dist.seq(1000) 140.19895 140.19895 140.19895 140.19895 140.19895 140.19895 1
# get.dist.parallel(1000) 50.71218 50.71218 50.71218 50.71218 50.71218 50.71218 1使用4个核可以提高大约3倍的处理速度。因此,由于1000段距离大约需要1分钟,所以100,000次应该需要不到2小时。
请注意,使用times=1实际上是对microbenchmark(...)的滥用,因为关键是要多次运行该过程,并将结果平均化,但我只是没有耐心。
https://stackoverflow.com/questions/27697504
复制相似问题