{smcl}
{* *! version 13.0 31dec2020}{...}
{findalias asfradohelp}{...}
{vieweralsosee "" "--"}{...}
{vieweralsosee "[R] help" "help help"}{...}
{viewerjumpto "Syntax" "scale_transformationfile##syntax"}{...}
{viewerjumpto "Description" "scale_transformationfile##description"}{...}
{viewerjumpto "Options" "scale_transformationfile##options"}{...}
{viewerjumpto "References" "scale_transformationfile##references"}{...}
{viewerjumpto "Examples" "scale_transformationfile##examples"}{...}
{viewerjumpto "Author" "scale_transformationfile##author"}{...}
{title:Title}
{phang}
{bf:scale_transformation} {hline 1} Finds a 6th-degree monotonic polynomial transformation
for a test score scale, which optimizes a specific objective function (see Description section for details).
The optimization object includes scores at two points of time (e.g. year 1 and 2) and two comparison groups (e.g. male vs female).
This program uses the Stata mata function {manhelp optimize M-5} to perform a grid search from multiple random initial
parameters to find the desired values. The main use of this program is to estimate the maximum and minimum gap difference for an (ordinal) test score scale
between two groups across two points of time. Other optimization objects (i.e. correlation, R-squared and controls) are available to run robustness checks.
{p_end}
{marker syntax}{...}
{title:Syntax}
{p 8 17 2}
{cmd:scale_transformation}
{cmd:,} {it:options}
{synoptset 30 tabbed}{...}
{synopthdr}
{synoptline}
{syntab:Main (Required)}
{synopt:{opt t:ype(integer)}}indicates the type of optimization (i.e. max or min)
to be performed as well as the objective function (i.e. Gap Growth,
Correlation, R-squared, or Controls Explanation - see details below).{p_end}
{synopt:{opt score1(varname)}}numeric variable that contains test scores at (initial) period 1.{p_end}
{synopt:{opt score2(varname)}}numeric variable that contains test scores at (final) period 2.{p_end}
{syntab:Secondary (Optional)}
{synopt:{opt compg:roup(varname)}}numeric variable that contains a group classification; {bf: required} if type
is 1, 2 or 7 only.{p_end}
{synopt:{opt cont:rols(varlist)}}include varlist as controls to the baseline model at BOTH periods 1 and 2.{p_end}
{synopt:{opt controls1(varlist)}}include varlist as controls at period 1 ONLY (i.e. period-specific controls).{p_end}
{synopt:{opt controls2(varlist)}}include varlist as controls at period 2 ONLY (i.e. period-specific controls).{p_end}
{synopt:{opt w:eights(varname)}}uses varname as inverse probability weights.{p_end}
{synopt:{opt iter:ations(integer)}}specifies number of times that the program will find optimal values
using unique random-generated initial parameters;
default is {cmd:iterations(1000)}.{p_end}
{synopt:{opt maxoptiter:ations(integer)}}specifies maximum number of iterations before
each optimization stops and return results as if convergence was achieved;
default is {cmd:maxoptiterations(25)}; see {manhelp mf_optimize##i_maxiter M-5}.{p_end}
{synopt:{opt singhmet:hod(integer)}}specifies what the optimizer should do when, at an iteration
step, it finds that H is singular; default is {cmd:singhmethod(1)} for "hybrid";
see {manhelp mf_optimize##i_singularH M-5}.{p_end}
{synopt:{opt boundd:own(integer)}}specifies lower bound for the random-generated initial
parameters for the optimization; default is {cmd:bounddown(-1500)}.{p_end}
{synopt:{opt boundu:p(integer)}}specifies upper bound for the random-generated initial
parameters for the optimization; default is {cmd:boundup(1500)}.{p_end}
{synopt:{opt mono:tonicity(integer)}}specifies the type of monotonicity check to be
applied; default is {cmd:monotonicity(1)} for "Standard" - see below for details.{p_end}
{synopt:{opt monofile(filename)}}specifies the file to be used when monotonicity
type is set to "External"; should only be used with monotonicity(3).{p_end}
{synopt:{opt timeroff}}turn off the timer; default is set to include timer.{p_end}
{synopt:{opt save(filename)}}save optimization results using filename once program is done.{p_end}
{synopt:{opt seed(integer)}}set seed for replication.{p_end}
{synopt:{opt robust(integer)}}activates option to use first {it:K} iterations (in addition to
N specified by {it:iterations}) to check for a possible change of sign in Max/Min Gap Growth optimizations.{p_end}
{synoptline}
{p2colreset}{...}
{marker description}{...}
{title:Description}
{pstd}
{cmd:scale_transformation} finds a 6th degree polynomial monotonic transformation for a test score scale
that optimizes one of the following:{p_end}
{phang}a) {ul on}{bf:Gap Growth}{ul off}: gap difference between the bottom and top groups from the compgroup variable in period 2, minus the same gap difference in period 1. In other words,
it is the difference between the regression coefficient of the top compgroup indicator (controlling for groups in the middle) in period 2, MINUS the same regression coefficient
of the top compgroup indicator (also controlling for other groups in the middle) in period 1. In both, the coefficient of the top compgroup indicator measures the difference between the top and bottom groups.
Note that the Gap Growth is positive when the Gap widens and negative when the Gap shrinks. Thus, the Gap Growth will always be negative when the coefficient changes
signs between period 1 and 2 (regardless of whether it is from + to -, or from - to +). Conversely, it will be positive when the gap widens, for instance, from -.1 to -.3;{p_end}
{phang}b) {ul on}{bf:Correlation}{ul off}: coefficient from regressing test scores from period 1 on test scores from period 2 (no controls allowed);{p_end}
{phang}c) {ul on}{bf:R-squared}{ul off}: from regressing test scores from period 1 on test scores from period 2 (no controls allowed); or{p_end}
{phang}d) {ul on}{bf:Controls Explanation}{ul off}: measures how much Gap Growth coefficients change when including controls in
{it:{bf:controls1}(varlist)} and {it:{bf:controls2}(varlist)} - {bf:NOT} in {it:{bf:controls}(varlist)}. This allows to test the explanatory
power of only a subset of desired control variables. That means that, if you want to measure how much Gap Growth coefficients change by
introducing time-invariant controls, you must include these variables in {ul on}both{ul off} {it:{bf:controls1}(varlist)} and {it:{bf:controls2}(varlist)}.
The Controls Explanation term is estimated by taking the distance (i.e. absolute value of the difference) between the Gap Growth calculated without variables included in
controls1 and constrols2, minus the Gap Growth calculated with these two controls varlists. To make the interpretation easier, both Gap Growths coefficients - with and without
controls - are included in the results.{p_end}
{pstd}The {ul on}{bf:scale_transformation}{ul off} command is designed to verify the robustness of your results by finding plausible
test score scale transformations that maximize or minimize one of the above using a dataset in wide-format (i.e. one observation per row).
All the transformations found by this command are theoretically possible given the ordinal nature of test scores. Thus, the command helps to
verify that any results you obtained by comparing test scores using panel data (and potentially across different groups)
are robust to any arbitrary choice of scale by finding bounds for your estimations.
{pstd}The methodology was originally developed in the {ul on}{bf:Bond and Lang (2013)}{ul off} {it: RESTAT} paper, which also explains more in detail
the challenges posed by the ordinal nature of test scores and choice of scale. The current program builds on this
methodology, adjusts coefficient signs to allow for more flexibility, includes one more coefficient in the calculations and makes the optimization process more efficient,
precise and accessible.{p_end}
{pstd}A 6th-degree polynomial monotonic transformation is used because it provides flexibility to approach numerous continuous functions.
Nevertheless, a monotonicity checks needs to be applied to these transformations. These two characteristics yield a very complex optimization
problem that does not have a closed form solution. Furthermore, the monotonicity restriction introduces a discontinuity into the objective
function that creates multiple local maxima and minima. Considering all the above, this program takes advantage of the mata {manhelp optimize M-5} function and
performs a grid search to find multiple solutions from several different initial parameters. The results are reported in a dataset format that
includes the values of the evaluated objective functions, the resulting parameters of each optimization iteration and the initial parameters
that yielded that result.{p_end}
{marker options}{...}
{title:Options}
{dlgtab:Main (Required)}
{phang}
{opt t:ype(integer)} indicates the type of optimization and the objective function to be performed. The options are as follows:{p_end}
1. Gap Growth Maximization
2. Gap Growth Minimization
3. Correlation Maximization
4. Correlation Minimization
5. R-squared Maximization
6. R-squared Minimization
7. Controls Explanation Maximization
{phang}
{opt score1(varname)} specifies the variable that contains scores at (initial) period 1. In order to
improve processing speed, this variable is automatically scaled to be between 0 and 1 prior to running the program.
The transformation used for this process is the same for variables {it:score1} and {it:score2}, and does not affect
the resulting estimations in any way.
{phang}
{opt score2(varname)} specifies the variable that contains scores at (final) period 2. In order to
improve processing speed, this variable is automatically scaled to be between 0 and 1 prior to running the program.
The transformation used for this process is the same for variables {it:score1} and {it:score2}, and does not affect
the resulting estimations in any way.
{dlgtab:Secondary (Optional)}
{phang}
{opt compg:roup(varname)} specifies the variable that contains the group classification to be analyzed
and from which the program will compare the top and bottom groups. This variable
needs to be numeric. The program will take the lowest and highest values (i.e. groups) and compare them,
while controlling for all other groups in the middle at the same time. Note that the variable compgroup
should only take on integers greater or equal to 0 (all missings will be ignored). Only allowed
when optimizing Gap Growth or Controls Explanation (i.e. type 1, 2 or 7).
{phang}
{opt cont:rols(varlist)} include varlist as controls at BOTH period 1 and 2. Variables should be numeric as they
will be used directly in regressions. Only allowed when optimizing Gap Growth or Controls Explanation (i.e. type 1, 2 or 7).
{phang}
{opt controls1(varlist)} include varlist as controls at period 1 ONLY. Variables should be numeric as they
will be used directly in regressions. Only allowed when optimizing Gap Growth or Controls Explanation (i.e. type 1, 2 or 7).
{phang}
{opt controls2(varlist)} include varlist as controls at period 2 ONLY. Variables should be numeric as they
will be used directly in regressions. Only allowed when optimizing Gap Growth or Controls Explanation (i.e. type 1, 2 or 7).
{phang}
{opt w:eights(varname)} uses varname as inverse probability weights. If not specified, weights are set to 1.
{phang}
{opt iter:ations(integer)} specifies number of times that the program will find optimal values using unique
random-generated initial parameters. The default is set to {cmd:iterations(1000)}. The more iterations,
the longer it will take the program to run and finish. Note that by default, if the program is stopped before
ending, the results will not be stored. It is recommended that you test your program with a low number of iterations.
{phang}
{opt maxoptiter:ations(integer)} specifies maximum number of iterations before the optimization program stops
and return results as if convergence was achieved. The default is set to {cmd:maxoptiterations(25)}, which in
practice should be enough to achieve 'convergence' with a fair degree of accuracy. This limit is necessary as
the monotonicity restriction and complexity of the objective functions cause the optimization program to run indefinitely otherwise.
See {manhelp mf_optimize##i_maxiter M-5} for more details.
{phang}
{opt singhmet:hod(integer)} specifies what the optimizer should do when, at an iteration step, it finds that H is singular.
The default is set to {cmd:singhmethod(1)} for "hybrid" but can be changed to 2 for "modified Marquardt algorithm".
See {manhelp mf_optimize##i_singularH M-5} for more details.
{phang}
{opt boundd:own(integer)} specifies lower bound for the random-generated initial parameters for the optimization. This program
creates random initial values and then uses them to find all the different local maxima or minima, accordingly. The default is
set to {cmd:bounddown(-1500)}.
{phang}
{opt boundu:p(integer)} specifies upper bound for the random-generated initial parameters for the optimization. This program
creates random initial values and then uses them to find all the different local maxima or minima accordingly. The default is
set to {cmd:boundup(1500)}.
{phang}
{opt mono:tonicity(integer)} specifies the type of monotonicity check to be applied. The default is set to {opt monotonicity(1)}
for {bf:"Standard"}, which checks for monotonicity at every possible score value (up to 4 decimals within the plausible range) in the original scale that was
transformed to be between 0 and 1. When less precision is needed, monotonicity can be set to {cmd:2} for {bf:"Sample"}, which only checks for monotonicity at the unique
scores values present in the sample data. If the test scores come from a larger dataset that have scores for multiple years, it is possible to do a more
thorough check (but more time consuming) by putting together an external file with all theoretical or observed plausible scores where you want the
program to check for monotonicity. For the latter, you must set monotonicity to {cmd:3} for {bf:"External"} and include the filename in {opt monofile(filename)}. The
plausible test scores in the {bf:"External"} file should be in the original scale since the program will automatically transform them to the new scale and check
for monotonicity at each of these transformed scores.
{phang}
{opt monofile(filename)} specifies the file to be used when monotonicity type is set to {cmd:3} for {bf:"External"}. This
option should only be used with {cmd:monotonicity(3)}. You can use .dta, .csv, .xls or .xlsx files. Make sure that .csv,
.xls and .xlsx files have the name of the variable on the first row.
{phang}
{opt timeroff} turn off the timer. The default is set to include the time (in minutes) that the program took to run, which
is reported only if the program finishes.
{phang}
{opt save(filename)} save optimization results using {it:filename} once program is done.
{phang}
{opt seed(integer)} set seed for replication, where {it:0 <= integer <= 2,147,483,647}. If missing, the seed is randomly generated and included in the header of the program.
Always save the log file to ensure you are able to recover the seed number for replication.
{phang}
{opt robust(integer)} Since the optimization problem for the Max/Min Gap Growth options (i.e. type 1 or 2) is complex and does not have a closed-solution,
in some specific cases the maximization could yield the solutions for the minimization problem (and vice versa). In order to address this issue, the user could
activate the {it:robust} option to use the first {it:K=integer (where 20<=K<=300; K=even)} iterations (in addition to N specified by the {it:iterations} option)
to check for a possible change of sign in Max/Min Gap Growth optimization results. Half of the {it:K} iterations are used to find the maximization solution while
the other half {it:K} iterations are used for the minimization problem. Once the correct approach is selected, the program keeps the solutions for the correct specification
and runs the remaining N iterations indicated in the {opt iterations()} option.{p_end}
{marker references}{...}
{title:References}
{pstd}
{it: Bond, T. N., & Lang, K. (2013)}. The evolution of the Black-White test score gap in grades Kâ3: The fragility of results. Review of Economics and Statistics, 95, 1468â1479. doi:10.1162/REST_a_00370
{marker examples}{...}
{title:Examples}
{pstd}
Gap Growth maximization between scores in year 1 and 2 by comparing males vs females: {p_end}
{phang}{cmd:. sysuse timss_testscores.dta, clear}{p_end}
{phang}{cmd:. scale_transformation, type(1) score1(score1) score2(score2) /// }{p_end}
{phang}{cmd: compgroup(sex) iterations(20) maxoptiterations(15) mono(2) /// }{p_end}
{phang}{cmd: seed(562) robust(20) }{p_end}
{pstd}
Note that, given the above command, the program will run 40 times from different initial parameters and each time, the program will
report convergence after 15 iterations, performing a "Sample" monotonicity check. Given the option {opt robust(20)}, the program will
use the first 20 simulations to check that the sign of the gap is correct by carrying out 10 maximizations and 10 minimizations.
Once the correct direction is confirmed, the correct half is kept and the other discarded. Thus, in this example, the resulting dataset
will contain only 30 observations.
{p_end}
{marker author}{...}
{title:Author}
{pstd}Andres Yi Chang{p_end}
{pstd}andresyichang@gmail.com{p_end}
{marker version}{...}
{title:Version}
{pstd}Last Updated on: December 31, 2020{p_end}
{pstd}This commnad was build with Stata Version 13{p_end}