在 mutate 中使用 maptools::sunriset()

use maptools::sunriset() inside mutate

我正在尝试使用 dplyr 计算一组 lon/lat/timestamp 坐标的日出时间,使用 maptools 中的 sunriset 函数。这是一个可重现的例子。

library(maptools)
library(dplyr)

pts <- tbl_df(data.frame(
  lon=c(12.08752,12.08748,12.08754,12.08760,12.08746,12.08748),
  lat=c(52.11760,52.11760,52.11747,52.11755,52.11778,52.11753),
  timestamp=as.POSIXct(
    c("2011-08-12 02:00:56 UTC","2011-08-12 02:20:22 UTC",
      "2011-08-12 02:40:15 UTC","2011-08-12 03:00:29 UTC",
      "2011-08-12 03:20:26 UTC","2011-08-12 03:40:30 UTC"))
))

pts %>% mutate(sunrise=sunriset(as.matrix(lon,lat),
                                timestamp,POSIXct.out=T,
                                direction='sunrise')$time)

当我 运行 这段代码时,我收到错误

"Error: invalid subscript type 'closure'"

我猜这意味着我没有正确地将变量传递给 sunriset

这个方法确实有效,如果我没有dplyr

pts$sunrise<-sunriset(as.matrix(select(pts,lon,lat)), 
                    pts$timestamp, POSIXct.out=T, 
                    direction='sunrise')$time

但是,我有很多行(大约 6500 万行),即使只有一小部分,上述方法也非常慢。我希望 dplyr 会更快。如果有人对哪种方法可能最快有其他建议,我很乐意听取他们的意见。

sunr <- function(lon, lat, ts, dir='sunrise') {
  # can also do matrix(c(pts$lon, pts$lat), ncol=2, byrow=TRUE) vs 
  # as.matrix(data.frame…
  sunriset(as.matrix(data.frame(lon, lat)), ts, POSIXct.out=TRUE, direction=dir)$time
}

pts %>% mutate(sunrise = sunr(lon, lat, timestamp))

是一种处理方法(并且具有清洁 mutate 管道的副作用)但我不确定您为什么认为它会更快。无论哪种方式,瓶颈(很可能)是为调用 sunriset 创建矩阵,这将以任何一种方式发生。

maptools 源代码很容易理解,并且有一个非导出函数 maptools:::.sunrisetUTC() 可以:

".sunrisetUTC" <- function(jd, lon, lat, direction=c("sunrise", "sunset")) {
## Value: Numeric, UTC time of sunrise or sunset, in minutes from zero
## Z.
## --------------------------------------------------------------------
## Arguments: jd=julian day (real);
## lon=lat=longitude and latitude, respectively, of the observer in
## degrees;
## sunrise=logical indicating whether sunrise or sunset UTC should be
## returned.

您可以尝试将儒略日、经度、纬度和方向传递给它,而不是导出函数,以避免数据复制。但是,如果性能很关键,我会使用 Rcpp 编写基于 this.

的内联矢量化 C/C++ 函数