计算不同日期范围内的平均日长

时间:2019-02-28 18:38:42

标签: r geospatial geosphere

我正在使用geosphere软件包中的daylength函数来计算两点之间某个位置的日长。根据具体的个人和位置,我平均每天的天数会有所不同。

当我对变量进行硬编码(即为lat和date提供特定值)时函数可以工作时,但是当我提供值的向量并得到以下错误和警告消息时,该函数就不起作用:

Error in mutate_impl(.data, dots) : Evaluation error: NA/NaN argument.
In addition: Warning messages:
1: In doy.prev:doy :
  numerical expression has 379 elements: only the first used
2: In doy.prev:doy :
  numerical expression has 379 elements: only the first used

我知道此错误与我的日长计算有关,因为省略该代码的另一部分可以正常运行。

我的代码和数据的子集(即前25个观察值):

df %>%
  mutate(mean.lat = if_else((ID == lag(ID) & site != lag(site)),
                          (lat + lag(lat))/2, NA_real_),
         doy.prev = if_else((ID == lag(ID) & 
                                site != lag(site)),
                             lag(yday(ts)), 
                             NA_real_),
         mean.day = if_else((ID == lag(ID) & 
                                site != lag(site) &
                                yday(ts) != yday(lag(ts)) & 
                                !is.na(mean.lat) & 
                                !is.na(doy.prev)),
                             mean(daylength(mean.lat, doy.prev:doy)), 
                             timeS))
dput(df)
structure(list(ID = structure(c(1L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 4L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 7L, 8L, 
8L), .Label = c("NB2014.12", "NB2014.13", "NB2014.14", "NB2014.15", 
"NB2014.16", "NB2014.42", "NB2014.43", "NB2014.44", "NB2014.45", 
"NB2014.47", "NB2014.48", "NB2014.49", "NB2014.70", "NB2014.71", 
"NB2014.72", "NB2014.73", "NB2014.74", "NB2014.75", "NB2014.76", 
"NB2014.77", "NB2014.78", "NB2014.79", "NB2014.80", "NB2014.81", 
"NB2015.156", "NB2015.157", "NB2015.158", "NB2015.159", "NB2015.160", 
"NB2015.312", "NB2015.313", "NB2015.314", "NB2015.315", "NB2015.316", 
"NB2015.317", "NB2015.318", "NB2015.320", "NB2015.321", "NB2015.322", 
"NB2015.323", "NB2015.324", "NB2015.325", "NB2015.326", "NB2015.327", 
"NB2015.328", "NB2015.329", "NB2015.330", "NB2015.331", "NB2015.332", 
"NB2015.333", "NB2015.334", "NB2015.335", "NB2015.336", "NB2015.337", 
"NB2015.338", "NB2015.339", "NB2015.340", "NB2015.341", "NB2015.342", 
"NB2015.343", "NB2015.344", "NB2015.345", "NB2015.346", "NB2015.347", 
"NB2015.348", "NB2015.349", "NB2015.350", "NB2015.351", "NB2018.10", 
"NB2018.11", "NB2018.12", "NB2018.13", "NB2018.14", "NB2018.15", 
"NB2018.16", "NB2018.17", "NB2018.18", "NB2018.19", "NB2018.20", 
"NB2018.21", "NB2018.22", "NB2018.23", "NB2018.24", "NB2018.25", 
"NB2018.26", "NB2018.27", "NB2018.28", "NB2018.29", "NB2018.30", 
"NB2018.31", "NB2018.32", "NB2018.33", "NB2018.34", "NB2018.35", 
"NB2018.37", "NB2018.38", "NB2018.39", "NB2018.40", "NB2018.41", 
"NB2018.42", "NB2018.43", "NB2018.44", "NB2018.45", "NB2018.46", 
"NB2018.47", "NB2018.48", "NB2018.49", "NB2018.5", "NB2018.50", 
"NB2018.51", "NB2018.52", "NB2018.53", "NB2018.54", "NB2018.55", 
"NB2018.56", "NB2018.57", "NB2018.58", "NB2018.59", "NB2018.6", 
"NB2018.60", "NB2018.61", "NB2018.62", "NB2018.63", "NB2018.64", 
"NB2018.7", "NB2018.8", "NB2018.9"), class = "factor"), site = c("Tantramar", 
"Tantramar", "HPWLR", "Tantramar", "Beaubassin", "Marsh Landings", 
"Eddie rd. ", "Marsh Landings", "Marsh Landings", "Marsh Landings", 
"Eddie rd. ", "Beaubassin", "AMHRST", "HPWLR", "Tantramar", "Tantramar", 
"Fork Field Farms", "WNERR", "GB_ferryway", "GB_thomas", "Tantramar", 
"HPWLR", "Tantramar", "Tantramar", "Marsh Landings"), lat = c(45.900303030303, 
45.900303030303, 45.83, 45.900303030303, 45.85, 45.85, 45.85, 
45.85, 45.85, 45.85, 45.85, 45.85, 45.79, 45.83, 45.900303030303, 
45.900303030303, 45.94, 43.34, 43.09, 43.08, 45.900303030303, 
45.83, 45.900303030303, 45.900303030303, 45.85), doy = c(213, 
206, 206, 217, 217, 217, 217, 217, 218, 218, 218, 218, 218, 218, 
194, 206, 207, 211, 211, 211, 220, 220, 207, 210, 210), ts = structure(c(1406899801.4133, 
1406297348.1112, 1406299522.4141, 1407276094.4158, 1407277417.7616, 
1407279028.1764, 1407279972.1813, 1407281880.08955, 1407285413.4387, 
1407314856.6032, 1407315906.52065, 1407316678.29125, 1407316887.28, 
1407319828.1424, 1405278154.7126, 1406330632.0613, 1406364501.8284, 
1406713079.0338, 1406716251.3933, 1406716449.5783, 1407490305.4993, 
1407491817.085, 1406370738.3239, 1406655731.0996, 1406673688.1819
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), timeS = c(NA, 
NA, 2174.30289983749, NA, 1323.34579992294, 1610.41479992867, 
944.004900217056, 1907.90824985504, NA, NA, 1049.91744995117, 
771.77060008049, 208.988749980927, 2940.86240005493, NA, NA, 
33869.7670998573, 348577.20539999, 3172.35950016975, 198.18499994278, 
NA, 1511.5857000351, NA, NA, 17957.0822999477)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -25L))

3 个答案:

答案 0 :(得分:1)

在普通R中:

d <- data.frame(
    meanLat = c(45.0, 44.6),
    doy = c(207,211),
    doy.prev = 206:207
)
library(geosphere)
# one row
sum(daylength(d$meanLat[1], d$doy.prev[1]:d$doy[1]))
#[1] 29.96547
# all rows
apply(d, 1, function(x) sum(daylength(x[1], x[3]:x[2])))
#[1] 29.96547 74.25768

# you could also first make a proper long matrix
x <- do.call(rbind, apply(d, 1, function(x) cbind(x[1], x[3]:x[2])))
# followed by
tapply(daylength(x[,1], x[,2]), x[,1], sum)
#    44.6       45
#74.25768 29.96547 

答案 1 :(得分:0)

我添加了其他过滤器,并给出了以下警告。有什么提示吗?

df %>%
  mutate(mean.lat = if_else((ID == lag(ID) & site != lag(site)),
                            (lat + lag(lat))/2, NA_real_),
         doy.prev = if_else((ID == lag(ID) & 
                               site != lag(site)),
                            lag(yday(ts)), 
                            NA_real_)) %>%
  filter(!is.na(doy.prev)) %>%
  mutate(mean.day = if_else(((ID == lag(ID) & 
                               site != lag(site) &
                               yday(ts) != yday(lag(ts))) & 
                               !is.na(mean.lat) & 
                               !is.na(doy.prev)),
                            mean(daylength(mean.lat, doy.prev:doy)), 
                            timeS)) 
12 NB2014.16 GB_ferryway       43.1   211 2014-07-30 10:30:51   3172.     43.2      211   3172. 
13 NB2014.16 GB_thomas         43.1   211 2014-07-30 10:34:09    198.     43.1      211    198. 
14 NB2014.42 HPWLR             45.8   220 2014-08-08 09:56:57   1512.     45.9      220   1512. 
15 NB2014.44 Marsh Landings    45.8   210 2014-07-29 22:41:28  17957.     45.9      210  17957. 
Warning messages:
1: In doy.prev:doy :
  numerical expression has 15 elements: only the first used
2: In doy.prev:doy :
  numerical expression has 15 elements: only the first used

答案 2 :(得分:0)

我无法找到一种方法来使Daylength函数在dplyr中工作。但是,这是一种解决方法:

df2 <- df %>%
    filter(!is.na(meanLat))

df2$timeHday = apply((df2 %>% select(meanLat, doy.local, doy.prev1)), 
                   1,
                   function(x) sum(daylength(x[1], x[3]:x[2])))

df <- df %>% left_join(df2, by = c("ID", "ts.mn"))

非常感谢Robert Hijmans的帮助!