Thanks for the post and glad you enjoyed the read!
It's difficult to help with this extensive of an example - you will have more luck here and elsewhere if you create a smaller version of your problem and render it with the reprex package. The main feature of this is that all I have to do to help you is copy your code and run it (way faster for me). In your case, it would look like this:
library(tidyverse)
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
truelove <- tibble(
date = as.Date(c("1961-09-10", "1961-09-10", "1961-09-10", "1961-09-10",
"1961-10-25", "1961-10-25", "1961-10-25", "1961-10-25",
"1961-11-21", "1961-11-21", "1961-11-21", "1961-11-21", "1962-01-10",
"1962-01-10", "1962-01-10")),
depth = c(0, 2, 4, 6, 1, 2, 4, 6, 1, 2, 4, 6, 2, 4, 6),
oxygen_mL = c(9.75, 9.69, 9.63, 9.56, 10.8, 10.5, 9.67, 6.62, 10.3, 10,
8.36, 6.39, 9.58, 8.31, 5.09)
)
estimate_oxy_by_date <- function(target_date, target_depth) {
data_for_date <- truelove %>%
filter(date == target_date) %>%
arrange(depth)
approx(data_for_date$depth, data_for_date$oxygen_mL, xout = target_depth)$y
}
oxy_interp_depth <- crossing(
tibble(date = unique(truelove$date)),
tibble(depth = seq(0, 6, length.out = 24))
) %>%
group_by(date) %>%
mutate(oxygen_mL = estimate_oxy_by_date(date[1], depth))
estimate_oxy_by_depth <- function(target_depth, target_date) {
data_for_depth <- oxy_interp_depth %>%
filter(depth == target_depth) %>%
arrange(date)
approx(data_for_depth$date, data_for_depth$oxygen_mL, xout = target_date)$y
}
oxy_raster <- crossing(tibble(date = seq(ymd("1961-09-10"), ymd("1962-05-07"), by = 2)),
tibble(depth = unique(oxy_interp_depth$depth))) %>%
group_by(depth) %>%
mutate(oxygen_mL = estimate_oxy_by_depth(depth[1], date))
#> Error in approx(data_for_depth$date, data_for_depth$oxygen_mL, xout = target_date): need at least two non-NA values to interpolate
Created on 2020-05-18 by the reprex package (v0.3.0)
As you suspected, the error is because there's only one measurement at zero depth, so approx() really is trying to interpolate where there isn't enough data to do so. The solution is to limit the depth in oxy_raster to only depth where this makes sense (greater than one). I'd insert filter(depth > 1) to make this work:
library(tidyverse)
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
truelove <- tibble(
date = as.Date(c("1961-09-10", "1961-09-10", "1961-09-10", "1961-09-10",
"1961-10-25", "1961-10-25", "1961-10-25", "1961-10-25",
"1961-11-21", "1961-11-21", "1961-11-21", "1961-11-21", "1962-01-10",
"1962-01-10", "1962-01-10")),
depth = c(0, 2, 4, 6, 1, 2, 4, 6, 1, 2, 4, 6, 2, 4, 6),
oxygen_mL = c(9.75, 9.69, 9.63, 9.56, 10.8, 10.5, 9.67, 6.62, 10.3, 10,
8.36, 6.39, 9.58, 8.31, 5.09)
)
estimate_oxy_by_date <- function(target_date, target_depth) {
data_for_date <- truelove %>%
filter(date == target_date) %>%
arrange(depth)
approx(data_for_date$depth, data_for_date$oxygen_mL, xout = target_depth)$y
}
oxy_interp_depth <- crossing(
tibble(date = unique(truelove$date)),
tibble(depth = seq(0, 6, length.out = 24))
) %>%
group_by(date) %>%
mutate(oxygen_mL = estimate_oxy_by_date(date[1], depth))
estimate_oxy_by_depth <- function(target_depth, target_date) {
data_for_depth <- oxy_interp_depth %>%
filter(depth == target_depth) %>%
arrange(date)
approx(data_for_depth$date, data_for_depth$oxygen_mL, xout = target_date)$y
}
oxy_raster <- crossing(tibble(date = seq(ymd("1961-09-10"), ymd("1962-05-07"), by = 2)),
tibble(depth = unique(oxy_interp_depth$depth))) %>%
filter(depth > 1) %>%
group_by(depth) %>%
mutate(oxygen_mL = estimate_oxy_by_depth(depth[1], date))
oxy_raster
#> # A tibble: 2,400 x 3
#> # Groups: depth [20]
#> date depth oxygen_mL
#> <date> <dbl> <dbl>
#> 1 1961-09-10 1.04 9.72
#> 2 1961-09-10 1.30 9.71
#> 3 1961-09-10 1.57 9.70
#> 4 1961-09-10 1.83 9.70
#> 5 1961-09-10 2.09 9.69
#> 6 1961-09-10 2.35 9.68
#> 7 1961-09-10 2.61 9.67
#> 8 1961-09-10 2.87 9.66
#> 9 1961-09-10 3.13 9.66
#> 10 1961-09-10 3.39 9.65
#> # … with 2,390 more rows
Created on 2020-05-18 by the reprex package (v0.3.0)