@@ -545,3 +545,55 @@ RSquared
545545const rsq = RSquared ()
546546" $RSquaredDoc "
547547const rsquared = rsq
548+
549+ # -------------------------------------------------------------------------
550+ # Willmott index of agreement (d)
551+
552+ # type for measure without argument checks:
553+ struct _WillmottD end
554+
555+ function (:: _WillmottD )(yhat, y)
556+ μ = aggregate (y) # mean
557+ # numerator: Σ_i (ŷ_i - y_i)^2
558+ num = LPSumLoss (p= 2 )(yhat, y)
559+ # denominator: Σ_i (|ŷ_i - μ| + |y_i - μ|)^2
560+ den = multimeasure ((yhat, y) -> (abs (yhat - μ) + abs (y - μ))^ 2 ; mode= Sum ())(yhat, y)
561+ return den == 0 ? (num == 0 ? 1.0 : 0.0 ) : 1 - num/ den
562+ end
563+
564+ WillmottD () = _WillmottD () |> API. robust_measure |> API. fussy_measure
565+ const WillmottDType = API. FussyMeasure{<: API.RobustMeasure{<:_WillmottD} }
566+
567+ @trait (
568+ _WillmottD,
569+ consumes_multiple_observations = true ,
570+ kind_of_proxy = LearnAPI. Point (),
571+ observation_scitype = Union{Missing,Infinite},
572+ orientation = Score (),
573+ human_name = " Willmott index of agreement (d)" ,
574+ )
575+
576+ @fix_show WillmottD:: WillmottDType
577+
578+ register (WillmottD, " willmott_d" )
579+
580+ const WillmottDDoc = docstring (
581+ " WillmottD()" ,
582+ scitype= DOC_INFINITE,
583+ body=
584+ """
585+ Returns Willmott index of agreement (d)
586+
587+ ``d = 1 - \\ dfrac{\\ sum (ŷ_i - y_i)^2}{\\ sum (|ŷ_i - \\ bar y| + |y_i - \\ bar y|)^2}``,
588+
589+ where ``\\ bar y`` is the mean of the targets. The value lies in ``[0,1]`` with higher
590+ being better.
591+
592+ References: Willmott [(1981)](https://doi.org/10.1080/02723646.1981.10642213)
593+ """ ,
594+ )
595+
596+ " $WillmottDDoc "
597+ WillmottD
598+ " $WillmottDDoc "
599+ const willmott_d = WillmottD ()
0 commit comments