@@ -412,3 +412,223 @@ add_mono_model_file = function(model_file,
412
412
return (list (model_file = model_file ,
413
413
model_data = model_data ))
414
414
}
415
+
416
+ # ' Evaluation of a monotonically increasing function
417
+ # ' These evaluation functions are needed so that gratia::draw methods work with mvgam
418
+ # ' monotonic smooths
419
+ # ' @importFrom gratia eval_smooth smooths by_variable smooth_label spline_values is_factor_by_smooth by_level smooth_dim
420
+ # ' @rdname monotonic
421
+ # ' @export
422
+ eval_smooth.moi.smooth = function (smooth ,
423
+ model ,
424
+ n = 100 ,
425
+ n_3d = NULL ,
426
+ n_4d = NULL ,
427
+ data = NULL ,
428
+ unconditional = FALSE ,
429
+ overall_uncertainty = TRUE ,
430
+ dist = NULL ,
431
+ ... ) {
432
+ model $ cmX <- model $ coefficients
433
+
434
+ # # deal with data if supplied
435
+ data <- process_user_data_for_eval(
436
+ data = data , model = model ,
437
+ n = n , n_3d = n_3d , n_4d = n_4d ,
438
+ id = which_smooth(
439
+ model ,
440
+ smooth_label(smooth )
441
+ )
442
+ )
443
+
444
+ by_var <- gratia :: by_variable(smooth ) # even if not a by as we want NA later
445
+ if (by_var == " NA" ) {
446
+ by_var <- NA_character_
447
+ }
448
+
449
+ # # values of spline at data
450
+ eval_sm <- gratia :: spline_values(smooth ,
451
+ data = data ,
452
+ unconditional = unconditional ,
453
+ model = model ,
454
+ overall_uncertainty = overall_uncertainty
455
+ )
456
+
457
+ # # add on info regarding by variable
458
+ eval_sm <- add_by_var_column(eval_sm , by_var = by_var )
459
+ # # add on spline type info
460
+ eval_sm <- add_smooth_type_column(eval_sm , sm_type = " Mono inc P spline" )
461
+
462
+ # set some values to NA if too far from the data
463
+ if (gratia :: smooth_dim(smooth ) == 2L && (! is.null(dist ) && dist > 0 )) {
464
+ eval_sm <- too_far_to_na(smooth ,
465
+ input = eval_sm ,
466
+ reference = model [[" model" ]],
467
+ cols = c(" .estimate" , " .se" ),
468
+ dist = dist
469
+ )
470
+ }
471
+ # # return
472
+ eval_sm
473
+ }
474
+
475
+ # ' Evaluation of a monotonically decreasing function
476
+ # ' @rdname monotonic
477
+ # ' @param model an object of class `"gam"`
478
+ # ' @param smooth a smooth object of class `"moi.smooth"` or `"mod.smooth"`
479
+ # ' @param n numeric; the number of points over the range of the covariate at
480
+ # ' which to evaluate the smooth.
481
+ # ' @param n_3d,n_4d numeric; the number of points over the range of last
482
+ # ' covariate in a 3D or 4D smooth. The default is `NULL` which achieves the
483
+ # ' standard behaviour of using `n` points over the range of all covariate,
484
+ # ' resulting in `n^d` evaluation points, where `d` is the dimension of the
485
+ # ' smooth. For `d > 2` this can result in very many evaluation points and slow
486
+ # ' performance. For smooths of `d > 4`, the value of `n_4d` will be used for
487
+ # ' all dimensions `> 4`, unless this is `NULL`, in which case the default
488
+ # ' behaviour (using `n` for all dimensions) will be observed.
489
+ # ' @param data a data frame of covariate values at which to evaluate the
490
+ # ' smooth.
491
+ # ' @param unconditional logical; should confidence intervals include the
492
+ # ' uncertainty due to smoothness selection? If `TRUE`, the corrected Bayesian
493
+ # ' covariance matrix will be used.
494
+ # ' @param overall_uncertainty logical; should the uncertainty in the model
495
+ # ' constant term be included in the standard error of the evaluate values of
496
+ # ' the smooth?
497
+ # ' @param dist numeric; if greater than 0, this is used to determine when
498
+ # ' a location is too far from data to be plotted when plotting 2-D smooths.
499
+ # ' The data are scaled into the unit square before deciding what to exclude,
500
+ # ' and `dist` is a distance within the unit square. See
501
+ # ' [mgcv::exclude.too.far()] for further details.
502
+ # ' @param ... ignored.
503
+ # ' @export
504
+ eval_smooth.mod.smooth = function (smooth ,
505
+ model ,
506
+ n = 100 ,
507
+ n_3d = NULL ,
508
+ n_4d = NULL ,
509
+ data = NULL ,
510
+ unconditional = FALSE ,
511
+ overall_uncertainty = TRUE ,
512
+ dist = NULL ,
513
+ ... ) {
514
+ model $ cmX <- model $ coefficients
515
+
516
+ # # deal with data if supplied
517
+ data <- process_user_data_for_eval(
518
+ data = data , model = model ,
519
+ n = n , n_3d = n_3d , n_4d = n_4d ,
520
+ id = which_smooth(
521
+ model ,
522
+ smooth_label(smooth )
523
+ )
524
+ )
525
+
526
+ by_var <- gratia :: by_variable(smooth ) # even if not a by as we want NA later
527
+ if (by_var == " NA" ) {
528
+ by_var <- NA_character_
529
+ }
530
+
531
+ # # values of spline at data
532
+ eval_sm <- gratia :: spline_values(smooth ,
533
+ data = data ,
534
+ unconditional = unconditional ,
535
+ model = model ,
536
+ overall_uncertainty = overall_uncertainty
537
+ )
538
+
539
+ # # add on info regarding by variable
540
+ eval_sm <- add_by_var_column(eval_sm , by_var = by_var )
541
+ # # add on spline type info
542
+ eval_sm <- add_smooth_type_column(eval_sm , sm_type = " Mono dec P spline" )
543
+
544
+ # set some values to NA if too far from the data
545
+ if (gratia :: smooth_dim(smooth ) == 2L && (! is.null(dist ) && dist > 0 )) {
546
+ eval_sm <- too_far_to_na(smooth ,
547
+ input = eval_sm ,
548
+ reference = model [[" model" ]],
549
+ cols = c(" .estimate" , " .se" ),
550
+ dist = dist
551
+ )
552
+ }
553
+ # # return
554
+ eval_sm
555
+ }
556
+
557
+ # ' Utility functions; full credit goes to Gavin Simpson, the developer and
558
+ # ' maintainer of the gratia package
559
+ # ' @noRd
560
+ `is.gamm` <- function (object ) {
561
+ inherits(object , " gamm" )
562
+ }
563
+
564
+ # ' @noRd
565
+ `is.gamm4` <- function (object ) {
566
+ is.list(object ) & (! is.null(object [[" gam" ]]))
567
+ }
568
+
569
+ # ' @noRd
570
+ `is.gam` <- function (object ) {
571
+ inherits(object , " gam" )
572
+ }
573
+
574
+ # ' @noRd
575
+ `is.bam` <- function (object ) {
576
+ inherits(object , " bam" )
577
+ }
578
+
579
+ # ' @noRd
580
+ `which_smooth` <- function (object , term ) {
581
+ if (is.gamm(object ) || is.gamm4(object )) {
582
+ object <- object [[" gam" ]]
583
+ }
584
+ smooths <- smooths(object )
585
+ which(term == smooths )
586
+ }
587
+
588
+ # ' @noRd
589
+ `process_user_data_for_eval` <- function (
590
+ data , model , n , n_3d , n_4d , id ,
591
+ var_order = NULL ) {
592
+ if (is.null(data )) {
593
+ data <- smooth_data(
594
+ model = model ,
595
+ n = n ,
596
+ n_3d = n_3d ,
597
+ n_4d = n_4d ,
598
+ id = id ,
599
+ var_order = var_order
600
+ )
601
+ } else {
602
+ smooth <- get_smooths_by_id(model , id )[[1L ]]
603
+ vars <- smooth_variable(smooth )
604
+ by_var <- by_variable(smooth )
605
+ if (! identical(by_var , " NA" )) {
606
+ vars <- append(vars , by_var )
607
+ }
608
+ # # if this is a by variable, filter the by variable for the required
609
+ # # level now
610
+ if (gratia :: is_factor_by_smooth(smooth )) {
611
+ data <- data %> % filter(.data [[by_var ]] == gratia :: by_level(smooth ))
612
+ }
613
+ }
614
+ data
615
+ }
616
+
617
+ # ' @importFrom tibble add_column
618
+ # ' @noRd
619
+ `add_by_var_column` <- function (object , by_var , n = NULL ) {
620
+ if (is.null(n )) {
621
+ n <- NROW(object )
622
+ }
623
+ insight :: check_if_installed(" tibble" )
624
+ tibble :: add_column(object , .by = rep(by_var , times = n ), .after = 1L )
625
+ }
626
+
627
+ # ' @noRd
628
+ `add_smooth_type_column` <- function (object , sm_type , n = NULL ) {
629
+ if (is.null(n )) {
630
+ n <- NROW(object )
631
+ }
632
+ insight :: check_if_installed(" tibble" )
633
+ tibble :: add_column(object , .type = rep(sm_type , times = n ), .after = 1L )
634
+ }
0 commit comments