@@ -75,29 +75,43 @@ slather.layer_residual_quantiles <-
75
75
function (object , components , the_fit , the_recipe , ... ) {
76
76
if (is.null(object $ probs )) return (components )
77
77
78
-
79
78
s <- ifelse(object $ symmetrize , - 1 , NA )
80
- r <- dplyr :: bind_cols(
81
- r = grab_residuals(the_fit , components ),
82
- geo_value = components $ mold $ extras $ roles $ geo_value ,
83
- components $ mold $ extras $ roles $ key )
79
+ r <- grab_residuals(the_fit , components )
84
80
85
81
# # Handle any grouping requests
86
82
if (length(object $ by_key ) > 0L ) {
87
- common <- intersect(object $ by_key , names(r ))
88
- excess <- setdiff(object $ by_key , names(r ))
83
+ key_cols <- dplyr :: bind_cols(
84
+ geo_value = components $ mold $ extras $ roles $ geo_value ,
85
+ components $ mold $ extras $ roles $ key
86
+ )
87
+ common <- intersect(object $ by_key , names(key_cols ))
88
+ excess <- setdiff(object $ by_key , names(key_cols ))
89
89
if (length(excess ) > 0L ) {
90
- cli_warn(" Requested residual grouping key(s) {excess} unavailable " ,
91
- " in the original data. Grouping by the remainder {common}." )
92
-
90
+ rlang :: warn(
91
+ " Requested residual grouping key(s) {excess} are unavailable " ,
92
+ " in the original data. Grouping by the remainder: {common}."
93
+ )
94
+ }
95
+ if (length(common ) > 0L ) {
96
+ r <- r %> % dplyr :: select(tidyselect :: any_of(c(common , " .resid" )))
97
+ common_in_r <- common [common %in% names(r )]
98
+ if (length(common_in_r ) != length(common )) {
99
+ rlang :: warn(
100
+ " Some grouping keys are not in data.frame returned by the" ,
101
+ " `residuals()` method. Groupings may not be correct."
102
+ )
103
+ }
104
+ r <- dplyr :: bind_cols(key_cols , r ) %> %
105
+ dplyr :: group_by(!!! rlang :: syms(common ))
93
106
}
94
- if (length(common ) > 0L )
95
- r <- r %> % dplyr :: group_by(!!! rlang :: syms(common ))
96
107
}
97
108
98
109
r <- r %> %
99
- dplyr :: summarise(
100
- q = list (quantile(c(r , s * r ), probs = object $ probs , na.rm = TRUE ))
110
+ dplyr :: summarize(
111
+ q = list (quantile(
112
+ c(.resid , s * .resid ),
113
+ probs = object $ probs , na.rm = TRUE
114
+ ))
101
115
)
102
116
103
117
estimate <- components $ predictions $ .pred
@@ -112,13 +126,40 @@ slather.layer_residual_quantiles <-
112
126
grab_residuals <- function (the_fit , components ) {
113
127
if (the_fit $ spec $ mode != " regression" )
114
128
rlang :: abort(" For meaningful residuals, the predictor should be a regression model." )
115
- r_generic <- attr(utils :: methods(class = class(the_fit )[1 ]), " info" )$ generic
116
- if (" residuals" %in% r_generic ) {
117
- r <- residuals(the_fit )
118
- } else {
119
- yhat <- predict(the_fit , new_data = components $ mold $ predictors )
120
- r <- c(components $ mold $ outcomes - yhat )[[1 ]]
129
+ r_generic <- attr(utils :: methods(class = class(the_fit $ fit )[1 ]), " info" )$ generic
130
+ if (" residuals" %in% r_generic ) { # Try to use the available method.
131
+ cl <- class(the_fit $ fit )[1 ]
132
+ r <- residuals(the_fit $ fit )
133
+ if (inherits(r , " data.frame" )) {
134
+ if (" .resid" %in% names(r )) { # success
135
+ return (r )
136
+ } else { # failure
137
+ rlang :: warn(c(
138
+ " The `residuals()` method for objects of class {cl} results in" ,
139
+ " a data frame without a column named `.resid`." ,
140
+ i = " Residual quantiles will be calculated directly from the" ,
141
+ i = " difference between predictions and observations." ,
142
+ i = " This may result in unexpected behaviour."
143
+ ))
144
+ }
145
+ } else if (is.vector(drop(r ))) { # also success
146
+ return (tibble(.resid = drop(r )))
147
+ } else { # failure
148
+ rlang :: warn(c(
149
+ " The `residuals()` method for objects of class {cl} results in an" ,
150
+ " object that is neither a data frame with a column named `.resid`," ,
151
+ " nor something coercible to a vector." ,
152
+ i = " Residual quantiles will be calculated directly from the" ,
153
+ i = " difference between predictions and observations." ,
154
+ i = " This may result in unexpected behaviour."
155
+ ))
156
+ }
121
157
}
158
+ # The method failed for one reason or another and a warning was issued
159
+ # Or there was no method available.
160
+ yhat <- predict(the_fit , new_data = components $ mold $ predictors )
161
+ r <- c(components $ mold $ outcomes - yhat )[[1 ]] # this will be a vector
162
+ r <- tibble(.resid = r )
122
163
r
123
164
}
124
165
0 commit comments