From 09e50865be882ff11d4d269905a821dcfd5d8e42 Mon Sep 17 00:00:00 2001 From: Billy Buchanan Date: Thu, 29 Feb 2024 06:05:45 -0500 Subject: [PATCH] Upgraded the function signature for the metric functions to allow passing optional arguments to the functions. If options are not supported by the underlying function, nothing is done with the optional argument. Updated help files to reflect that change and added titles to each of the help files. Added some more robustness checks for syntax for the xv and xvloo commands. Updated validate it to handle parsing optional arguments passed to metrics/monitors (still need to test). Added tests for libxv to check that passing optional arguments would not affect existing functions that do not support them. Updated helpfiles for the main commands to include titles. Updated the README. Updated the distribution date for the package file. Recompiled the Mata library in Stata 15. --- README.md | 7 ++- crossvalidate.mata | 147 +++++++++++++++++++++++++++++--------------- crossvalidate.pkg | 2 +- crossvalidate.sthlp | 27 ++++---- fitit.sthlp | 3 +- libxv.mlib | Bin 314604 -> 318856 bytes predictit.sthlp | 3 +- splitit.sthlp | 3 +- test/libxvtests.do | 4 ++ test/xvlootests.do | 50 ++++++++++++++- test/xvtests.do | 49 +++++++++++++-- validateit.ado | 10 ++- validateit.sthlp | 76 ++++++++++++++--------- xv.ado | 6 +- xv.sthlp | 1 + xvloo.ado | 6 +- xvloo.sthlp | 3 +- 17 files changed, 282 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index f365673..d81a6f1 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ collections for Stata >= 17 and modify help files related to collections. - [x] Modify the replay option to adjust for the collection thing above - [x] Write a function that can do the same thing as `assertnested` and will work in Stata 15 +- [x] Update function signature to provide support for optional arguments +- [x] Compile Mata library in Stata 15 - [ ] Standardize language in help files - [ ] Finish writing test cases for Mata functions - [ ] Finish writing test cases for ADO commands @@ -78,11 +80,12 @@ The program will allow users to define their own metrics/monitors that are not contained in libcrossvalidate. In order to do this, users must implement a specific method/function signature: -`real scalar metric(string scalar pred, string scalar obs, string scalar touse)` +`real scalar metric(string scalar pred, string scalar obs, string scalar touse, | transmorphic matrix opts)` The function must return a real valued scalar and take three arguments. The three arguments are used to access the data that would be used to compute the -metrics/monitors. +metrics/monitors and to provide a method to pass optional arguments to the +underlying functions if supported. ### Data access Within the function body, we recommend using the following pattern to access diff --git a/crossvalidate.mata b/crossvalidate.mata index 987b127..6402507 100644 --- a/crossvalidate.mata +++ b/crossvalidate.mata @@ -243,9 +243,14 @@ struct Crosstab scalar xtab(string scalar pred, string scalar obs, /// // Gets the total number of cases observed in the ith class colm[1, i] = rows(selectindex(y :== vals[i, 1])) - // Loop over the values of the observed variable and count the number of - // cases with the ith predicted value that have the jth observed value - for(j = 1; j <= levs; j++) conf[i, j] = rows(selectindex(y[idx, 1] :== vals[j, 1])) + // Loop over the values of the observed variable + for(j = 1; j <= levs; j++) { + + // count the number of cases with the ith predicted value that have + // the jth observed value + conf[i, j] = rows(selectindex(y[idx, 1] :== vals[j, 1])) + + } // End Loop over the observed variable values } // End Loop over the rows of the confusion matrix @@ -333,7 +338,8 @@ mata: // For sensitivity, specificity, prevalence, ppv, and npv see: // https://yardstick.tidymodels.org/reference/ppv.html // For others in this section see other pages from above -real scalar sens(string scalar pred, string scalar obs, string scalar touse) { +real scalar sens(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -358,7 +364,8 @@ real scalar sens(string scalar pred, string scalar obs, string scalar touse) { // Function to compute precision from a confusion matrix. See: // https://yardstick.tidymodels.org/reference/precision.html for the formula -real scalar prec(string scalar pred, string scalar obs, string scalar touse) { +real scalar prec(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -383,7 +390,8 @@ real scalar prec(string scalar pred, string scalar obs, string scalar touse) { // Function to compute recall, which appears to be a synonym for sensitivity. // See https://yardstick.tidymodels.org/reference/precision.html for formula -real scalar recall(string scalar pred, string scalar obs, string scalar touse) { +real scalar recall(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Declares a scalar to store the result real scalar result @@ -398,8 +406,8 @@ real scalar recall(string scalar pred, string scalar obs, string scalar touse) { // Defines function to compute specificity from a confusion matrix. // See: https://yardstick.tidymodels.org/reference/ppv.html for the formula -real scalar spec(string scalar pred, string scalar obs, /// - string scalar touse) { +real scalar spec(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -424,7 +432,8 @@ real scalar spec(string scalar pred, string scalar obs, /// // Defines a function to compute prevalence. // See: https://yardstick.tidymodels.org/reference/ppv.html for the formula -real scalar prev(string scalar pred, string scalar obs, string scalar touse) { +real scalar prev(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -449,7 +458,8 @@ real scalar prev(string scalar pred, string scalar obs, string scalar touse) { // Defines a function to compute positive predictive value. // See: https://yardstick.tidymodels.org/reference/ppv.html for the formula -real scalar ppv(string scalar pred, string scalar obs, string scalar touse) { +real scalar ppv(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a scalar to store the resulting metric, sensitivity, // specificity, and prevalence (used to compute the metric) @@ -474,7 +484,8 @@ real scalar ppv(string scalar pred, string scalar obs, string scalar touse) { // Defines a function to compute negative predictive value. // See: https://yardstick.tidymodels.org/reference/ppv.html for the formula -real scalar npv(string scalar pred, string scalar obs, string scalar touse) { +real scalar npv(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a scalar to store the resulting metric, sensitivity, // specificity, and prevalence (used to compute the metric) @@ -498,7 +509,8 @@ real scalar npv(string scalar pred, string scalar obs, string scalar touse) { } // End of function definition for negative predictive value // Defines a function to compute accuracy. -real scalar acc(string scalar pred, string scalar obs, string scalar touse) { +real scalar acc(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -519,7 +531,8 @@ real scalar acc(string scalar pred, string scalar obs, string scalar touse) { // Defines a function to compute "balanced" accuracy. // See https://yardstick.tidymodels.org/reference/bal_accuracy.html for more info -real scalar bacc(string scalar pred, string scalar obs, string scalar touse) { +real scalar bacc(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a scalar to store the resulting metric, sensitivity, // specificity, and prevalence (used to compute the metric) @@ -541,7 +554,8 @@ real scalar bacc(string scalar pred, string scalar obs, string scalar touse) { // Defines function to compute the F1 statistic // Based on second equation here: https://www.v7labs.com/blog/f1-score-guide -real scalar f1(string scalar pred, string scalar obs, string scalar touse) { +real scalar f1(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a scalar to store the resulting metric, precision, and recall real scalar result, prec, rec @@ -562,7 +576,8 @@ real scalar f1(string scalar pred, string scalar obs, string scalar touse) { // Defines J-index (Youden's J statistic) // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-j_index.R -real scalar jindex(string scalar pred, string scalar obs, string scalar touse) { +real scalar jindex(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Return the micro averaged detection prevalence return(sens(pred, obs, touse) + spec(pred, obs, touse) - 1) @@ -570,7 +585,8 @@ real scalar jindex(string scalar pred, string scalar obs, string scalar touse) { } // End of function definition for j-index // Defines a binary R^2 (tetrachoric correlation) -real scalar binr2(string scalar pred, string scalar obs, string scalar touse) { +real scalar binr2(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Call the tetrachoric command in Stata stata("cap: qui: tetrachoric " + pred + " " + obs + " if " + touse + ", ed") @@ -582,7 +598,8 @@ real scalar binr2(string scalar pred, string scalar obs, string scalar touse) { // Defines Matthews correlation coefficient // based on: https://en.wikipedia.org/wiki/Phi_coefficient#Multiclass_case -real scalar mcc(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcc(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -651,7 +668,8 @@ mata: // Defines multiclass specificity // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-spec.R -real scalar mcspec(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcspec(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -692,7 +710,8 @@ real scalar mcspec(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass sensitivity // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-sens.R -real scalar mcsens(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcsens(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -707,7 +726,8 @@ real scalar mcsens(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass recall // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-recall.R -real scalar mcrecall(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcrecall(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Return the micro averaged recall return(mcsens(pred, obs, touse)) @@ -716,7 +736,8 @@ real scalar mcrecall(string scalar pred, string scalar obs, string scalar touse) // Defines multiclass precision // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-precision.R -real scalar mcprec(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcprec(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -731,7 +752,8 @@ real scalar mcprec(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass positive predictive value // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-ppv.R -real scalar mcppv(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcppv(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Return the micro averaged PPV // Lines 176-178 indicate that multiclass PPV should be equal to precision @@ -744,7 +766,8 @@ real scalar mcppv(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass negative predictive value // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-npv.R -real scalar mcnpv(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcnpv(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -788,7 +811,8 @@ real scalar mcnpv(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass F1 statistic // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-f_meas.R -real scalar mcf1(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcf1(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares scalars to store intermediate results real scalar prec, sens @@ -806,7 +830,8 @@ real scalar mcf1(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass Detection Prevalence // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-detection_prevalence.R -real scalar mcdetect(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcdetect(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -821,7 +846,8 @@ real scalar mcdetect(string scalar pred, string scalar obs, string scalar touse) // Defines multiclass J-index (Youden's J statistic) // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-j_index.R -real scalar mcjindex(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcjindex(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Return the micro averaged detection prevalence return(mcsens(pred, obs, touse) + mcspec(pred, obs, touse) - 1) @@ -830,7 +856,8 @@ real scalar mcjindex(string scalar pred, string scalar obs, string scalar touse) // Defines multiclass accuracy // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-accuracy.R -real scalar mcacc(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcacc(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Return the accuracy return(acc(pred, obs, touse)) @@ -839,7 +866,8 @@ real scalar mcacc(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass Balanced Accuracy // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-bal_accuracy.R -real scalar mcbacc(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcbacc(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Declares scalars to store the intermediate results real scalar rec, sens @@ -858,7 +886,8 @@ real scalar mcbacc(string scalar pred, string scalar obs, string scalar touse) { // Defines multiclass Kappa // similar to accuracy, but normalized by accuracy expected by random chance // based on: https://github.com/tidymodels/yardstick/blob/main/R/class-kap.R -real scalar mckappa(string scalar pred, string scalar obs, string scalar touse) { +real scalar mckappa(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Creates the struct that gets returned struct Crosstab scalar c @@ -888,7 +917,8 @@ real scalar mckappa(string scalar pred, string scalar obs, string scalar touse) // Defines multiclass Mathews correlation coefficient // based on: https://github.com/tidymodels/yardstick/blob/main/src/mcc-multiclass.c -real scalar mcmcc(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcmcc(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Call the other implementation return(mcc(pred, obs, touse)) @@ -896,7 +926,8 @@ real scalar mcmcc(string scalar pred, string scalar obs, string scalar touse) { } // End of function definition for multiclass MCC // Defines a multiclass R^2 (polychoric correlation) -real scalar mcordr2(string scalar pred, string scalar obs, string scalar touse) { +real scalar mcordr2(string scalar pred, string scalar obs, /// + string scalar touse, | transmorphic matrix opts) { // Call the tetrachoric command in Stata stata("cap: qui: polychoric " + pred + " " + obs + " if " + touse) @@ -921,7 +952,8 @@ mata: // Defines function to compute mean squared error from predicted and observed // outcomes -real scalar mse(string scalar pred, string scalar obs, string scalar touse) { +real scalar mse(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Column vector to store the squared difference of pred - obs real colvector sqdiff @@ -942,7 +974,8 @@ real scalar mse(string scalar pred, string scalar obs, string scalar touse) { // Defines function to compute mean absolute error from predicted and observed // outcomes -real scalar mae(string scalar pred, string scalar obs, string scalar touse) { +real scalar mae(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Column vector to store the absolute difference of pred - obs real colvector absdiff @@ -963,7 +996,8 @@ real scalar mae(string scalar pred, string scalar obs, string scalar touse) { // Metric based on definition here: // https://developer.nvidia.com/blog/a-comprehensive-overview-of-regression-evaluation-metrics/ -real scalar bias(string scalar pred, string scalar obs, string scalar touse) { +real scalar bias(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the sum of residuals return(sum(st_data(., obs, touse) - st_data(., pred, touse))) @@ -972,7 +1006,8 @@ real scalar bias(string scalar pred, string scalar obs, string scalar touse) { // Metric based on definition here: // https://developer.nvidia.com/blog/a-comprehensive-overview-of-regression-evaluation-metrics/ -real scalar mbe(string scalar pred, string scalar obs, string scalar touse) { +real scalar mbe(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the sum of residuals return(sum(st_data(., obs, touse) - st_data(., pred, touse)) / /// @@ -982,7 +1017,8 @@ real scalar mbe(string scalar pred, string scalar obs, string scalar touse) { // Metric based on definition here: // https://github.com/tidymodels/yardstick/blob/main/R/num-rsq.R -real scalar r2(string scalar pred, string scalar obs, string scalar touse) { +real scalar r2(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the correlation between the predicted and observed variable return(corr(variance((st_data(., pred, touse), /// @@ -991,7 +1027,8 @@ real scalar r2(string scalar pred, string scalar obs, string scalar touse) { } // End of function definition for R^2 // Creates function for root mean squared error -real scalar rmse(string scalar pred, string scalar obs, string scalar touse) { +real scalar rmse(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the square root of the mean squared error return(sqrt(mse(pred, obs, touse))) @@ -1000,7 +1037,8 @@ real scalar rmse(string scalar pred, string scalar obs, string scalar touse) { // Metric based on definition of mean absolute percentage error here: // https://developer.nvidia.com/blog/a-comprehensive-overview-of-regression-evaluation-metrics/ -real scalar mape(string scalar pred, string scalar obs, string scalar touse) { +real scalar mape(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Allocates a column vector to store the differences real colvector diff @@ -1017,7 +1055,8 @@ real scalar mape(string scalar pred, string scalar obs, string scalar touse) { // Metric based on definition of symmetric mean absolute percentage error here: // https://github.com/tidymodels/yardstick/blob/main/R/num-smape.R -real scalar smape(string scalar pred, string scalar obs, string scalar touse) { +real scalar smape(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Allocates a column vector to store the differences real colvector num, denom @@ -1038,7 +1077,8 @@ real scalar smape(string scalar pred, string scalar obs, string scalar touse) { // Defines function to compute mean squared log error from predicted and observed // outcomes. Based on definition here: // https://developer.nvidia.com/blog/a-comprehensive-overview-of-regression-evaluation-metrics/ -real scalar msle(string scalar pred, string scalar obs, string scalar touse) { +real scalar msle(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Column vector to store the squared difference of pred - obs real colvector sqdiff @@ -1060,7 +1100,8 @@ real scalar msle(string scalar pred, string scalar obs, string scalar touse) { // Defines function to compute the root mean squared log error. Based on // definition here: // https://developer.nvidia.com/blog/a-comprehensive-overview-of-regression-evaluation-metrics/ -real scalar rmsle(string scalar pred, string scalar obs, string scalar touse) { +real scalar rmsle(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the square root of the mean squared log error return(sqrt(msle(pred, obs, touse))) @@ -1069,7 +1110,8 @@ real scalar rmsle(string scalar pred, string scalar obs, string scalar touse) { // Defines function for the ratio of performance to deviation // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-rpd.R -real scalar rpd(string scalar pred, string scalar obs, string scalar touse) { +real scalar rpd(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the ratio of the SD of predicted to the RMSE return(sqrt(variance(st_data(., pred, touse))) / rmse(pred, obs, touse)) @@ -1078,7 +1120,8 @@ real scalar rpd(string scalar pred, string scalar obs, string scalar touse) { // Defines function for the Index of ideality of correlation // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-iic.R -real scalar iic(string scalar pred, string scalar obs, string scalar touse) { +real scalar iic(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares some columnvectors real colvector neg, pos, delta @@ -1111,7 +1154,8 @@ real scalar iic(string scalar pred, string scalar obs, string scalar touse) { // Defines function for the Concordance Correlation Coefficient // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-ccc.R -real scalar ccc(string scalar pred, string scalar obs, string scalar touse) { +real scalar ccc(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares scalars needed real scalar mupred, muobs, varpred, varobs, cov @@ -1138,7 +1182,8 @@ real scalar ccc(string scalar pred, string scalar obs, string scalar touse) { // Defines function for Pseudo-Huber Loss // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-pseudo_huber_loss.R -real scalar phl(string scalar pred, string scalar obs, string scalar touse) { +real scalar phl(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a column vector to store the errors real colvector a @@ -1153,7 +1198,8 @@ real scalar phl(string scalar pred, string scalar obs, string scalar touse) { // Defines function for Huber Loss // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-huber_loss.R -real scalar huber(string scalar pred, string scalar obs, string scalar touse) { +real scalar huber(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a column vector to store the errors and absolute errors real colvector a, absa @@ -1172,7 +1218,8 @@ real scalar huber(string scalar pred, string scalar obs, string scalar touse) { // Defines function for Poisson Log Loss // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-poisson_log_loss.R -real scalar pll(string scalar pred, string scalar obs, string scalar touse) { +real scalar pll(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Returns the mean of the negative log poisson density return(mean(-dpois(st_data(., obs, touse), st_data(., pred, touse), 1))) @@ -1181,7 +1228,8 @@ real scalar pll(string scalar pred, string scalar obs, string scalar touse) { // Defines function for ratio of performance to interquartile range // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-rpiq.R -real scalar rpiq(string scalar pred, string scalar obs, string scalar touse) { +real scalar rpiq(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares scalar to store the iqr real scalar iqr @@ -1199,7 +1247,8 @@ real scalar rpiq(string scalar pred, string scalar obs, string scalar touse) { // Defines function for "Traditional" R^2 // based on: https://github.com/tidymodels/yardstick/blob/main/R/num-rsq_trad.R -real scalar r2ss(string scalar pred, string scalar obs, string scalar touse) { +real scalar r2ss(string scalar pred, string scalar obs, string scalar touse, /// + | transmorphic matrix opts) { // Declares a scalar to store the mean of the observed values real scalar mu diff --git a/crossvalidate.pkg b/crossvalidate.pkg index 22edda3..a9f2eac 100644 --- a/crossvalidate.pkg +++ b/crossvalidate.pkg @@ -20,7 +20,7 @@ d KW: evaluation d d Requires: Stata version 15 d -d Distribution-Date: 20240228 +d Distribution-Date: 20240229 d d Author: Billy Buchanan, Ph.D. d Sr. Research Scientist, SAG Corporation diff --git a/crossvalidate.sthlp b/crossvalidate.sthlp index d326f9d..1308dd2 100644 --- a/crossvalidate.sthlp +++ b/crossvalidate.sthlp @@ -1,5 +1,5 @@ {smcl} -{* *! version 0.0.1 17feb2024}{...} +{* *! version 0.0.2 29feb2024}{...} {vieweralsosee "[R] predict" "mansection R predict"}{...} {vieweralsosee "[R] estat classification" "mansection R estat_classification"}{...} {vieweralsosee "[P] creturn" "mansection P creturn"}{...} @@ -8,9 +8,9 @@ {viewerjumpto "Commands" "crossvalidate##cmds"}{...} {viewerjumpto "Additional Information" "crossvalidate##additional"}{...} {viewerjumpto "Contact" "crossvalidate##contact"}{...} +{title:Cross-Validation in Stata} -{marker overview} -{title:Overview} +{marker overview}{title:Overview} {pstd} The crossvalidate package includes several commands and a Mata library that @@ -27,25 +27,24 @@ This help file provides an overview of the commands included in the crossvalidat package. We leave detailed information to the documentation for each of the individual commands. -{marker cmds} -{title:Commands} +{marker cmds}{title:Commands} {synoptset 15 tabbed}{...} {synoptline} {synopthdr:Command Name} {synoptline} {syntab:Prefix Commands} -{synopt :{opt xv}}Cross-Validation{p_end} -{synopt :{opt xvloo}}Leave-One-Out Cross-Validation{p_end} +{synopt :{opt {help xv}}}Cross-Validation{p_end} +{synopt :{opt {help xvloo}}}Leave-One-Out Cross-Validation{p_end} {syntab:Lower Level Commands} -{synopt :{opt splitit}}Splits the dataset into train/test or train/validation/test splits{p_end} -{synopt :{opt fitit}}Calls the estimation command on the appropriate split{p_end} -{synopt :{opt predictit}}Predicts the outcome on the appropriate split{p_end} -{synopt :{opt validateit}}Computes {p_end} +{synopt :{opt {help splitit}}}Splits the dataset into train/test or train/validation/test splits{p_end} +{synopt :{opt {help fitit}}}Calls the estimation command on the appropriate split{p_end} +{synopt :{opt {help predictit}}}Predicts the outcome on the appropriate split{p_end} +{synopt :{opt {help validateit}}}Computes {p_end} {syntab:Utility Commands} -{synopt :{opt classify}}Used to manage {p_end} -{synopt :{opt cmdmod}}Used for metaprogramming tasks in commands above{p_end} -{synopt :{opt state}}Retrieves current settings and binds to the dataset{p_end} +{synopt :{opt {help classify}}}Used to manage {p_end} +{synopt :{opt {help cmdmod}}}Used for metaprogramming tasks in commands above{p_end} +{synopt :{opt {help state}}}Retrieves current settings and binds to the dataset{p_end} {synoptline} {dlgtab:Prefix Commands} diff --git a/fitit.sthlp b/fitit.sthlp index be6f926..5dfb661 100644 --- a/fitit.sthlp +++ b/fitit.sthlp @@ -1,5 +1,5 @@ {smcl} -{* *! version 0.0.6 28feb2024}{...} +{* *! version 0.0.7 29feb2024}{...} {vieweralsosee "[R] estat classification" "mansection R estat_classification"}{...} {vieweralsosee "" "--"}{...} {viewerjumpto "Syntax" "fitit##syntax"}{...} @@ -9,6 +9,7 @@ {viewerjumpto "Returned Values" "fitit##retvals"}{...} {viewerjumpto "Additional Information" "fitit##additional"}{...} {viewerjumpto "Contact" "fitit##contact"}{...} +{title:Model Fitting for Cross-Validation in Stata} {marker syntax}{...} {title:Syntax} diff --git a/libxv.mlib b/libxv.mlib index 8cc271be615ebe5dd881b223792140d97c2d5c51..19eeb2af1dffd20c32cdf666c67418109ec1909e 100644 GIT binary patch literal 318856 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 HISBqg5q)T_ literal 314604 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 BM4