tidyfun / tf

S3 classes and methods for tidy functional data
https://tidyfun.github.io/tf/
GNU Affero General Public License v3.0
6 stars 2 forks source link

extrema of functions and zero crossings of their derivatives don't match #59

Open fabian-s opened 5 months ago

fabian-s commented 5 months ago

see below --

possible fix: include interior extrema arg-values x_extrema in spec for derivatives?
also: check constant regions

library(tf)
#> 
#> Attaching package: 'tf'
#> The following objects are masked from 'package:stats':
#> 
#>     sd, var

set.seed(13)
x <- tf_rgp(5, scale = .05)
d_x <- tf_derive(x)
layout(1:2)
plot(x, col = 1:5)
plot(d_x, col = 1:5)


x_extrema <- tf_where(x, 
                      sign(c(diff(value)[1], diff(value))) !=
                      sign(c(diff(value), tail(diff(value), 1))))
# these should all be zero... :(
purrr::map2(d_x, x_extrema, ~ tf_evaluate(tfd(.x, tf_arg(d_x)), .y))
#> [[1]]
#> [[1]][[1]]
#> [1] -0.99823878 -0.98448442 -0.07617700 -0.05619386  1.53349281  0.36034955
#> 
#> 
#> [[2]]
#> [[2]][[1]]
#> [1] -0.37188925 -0.02696727  0.56522443  0.61006232  0.43615128 -0.13845337
#> [7]  0.69429250
#> 
#> 
#> [[3]]
#> [[3]][[1]]
#> [1]  1.59084942 -0.01399218 -0.08644659  0.65002436 -0.21639766 -1.27084706
#> 
#> 
#> [[4]]
#> [[4]][[1]]
#> [1]  0.3902644  0.2593921 -0.6235914 -0.5674999
#> 
#> 
#> [[5]]
#> [[5]][[1]]
#> [1] -0.4115175  0.6502406  2.6486481 -0.2960393  2.0080231

tf_domain(d_x) <- c(0,1)
# extrapolate on a very fine grid & look for "zeros"
(dx_zeros <- tfd(d_x, seq(0, 1, l = 901)) |> tf_where(abs(value) < 1e-3))  # :(
#> Warning in tfd.tf(d_x, seq(0, 1, l = 901)): 90 evaluations were NA, returning
#> irregular tfd.
#> [[1]]
#> numeric(0)
#> 
#> [[2]]
#> numeric(0)
#> 
#> [[3]]
#> numeric(0)
#> 
#> [[4]]
#> numeric(0)
#> 
#> [[5]]
#> numeric(0)
(dx_zeros <- tfd(d_x, seq(0, 1, l = 901)) |> tf_where(abs(value) < 1e-2))  # :(
#> Warning in tfd.tf(d_x, seq(0, 1, l = 901)): 90 evaluations were NA, returning
#> irregular tfd.
#> [[1]]
#> numeric(0)
#> 
#> [[2]]
#> [1] 0.07666667 0.07777778
#> 
#> [[3]]
#> numeric(0)
#> 
#> [[4]]
#> numeric(0)
#> 
#> [[5]]
#> [1] 0.4344444
(dx_zeros <- tfd(d_x, seq(0, 1, l = 901)) |> tf_where(abs(value) < 1e-1))  # :(
#> Warning in tfd.tf(d_x, seq(0, 1, l = 901)): 90 evaluations were NA, returning
#> irregular tfd.
#> [[1]]
#>  [1] 0.03666667 0.26555556 0.35666667 0.35777778 0.35888889 0.36000000
#>  [7] 0.60000000 0.60111111 0.86888889 0.87111111 0.87222222 0.87333333
#> [13] 0.87444444
#> 
#> [[2]]
#>  [1] 0.02555556 0.02666667 0.02777778 0.02888889 0.07000000 0.07111111
#>  [7] 0.07222222 0.07333333 0.07444444 0.07555556 0.07666667 0.07777778
#> [13] 0.07888889 0.08000000 0.08111111 0.08222222 0.08333333 0.08444444
#> [19] 0.08555556 0.08666667 0.09111111 0.09222222 0.12888889 0.13000000
#> [25] 0.43777778 0.62555556 0.62666667 0.62777778 0.62888889 0.63000000
#> [31] 0.85555556
#> 
#> [[3]]
#>  [1] 0.1866667 0.2000000 0.2011111 0.2377778 0.2388889 0.2400000 0.4733333
#>  [8] 0.4744444 0.6177778 0.6188889 0.9266667
#> 
#> [[4]]
#> [1] 0.3822222 0.6388889 0.9511111 0.9522222 0.9866667 0.9877778
#> 
#> [[5]]
#> [1] 0.1622222 0.1888889 0.1900000 0.4333333 0.4344444 0.4355556 0.7511111

# derivation/integration should be more reversible...
plot(x, col = 1:5)
plot(tf_integrate(tf_derive(x), definite = FALSE) + x[ , 0, matrix = TRUE],  col = 1:5)

Created on 2024-02-07 with reprex v2.0.2