The following FAQ is based on an exchange that started on
Statalist.
Can you explain Chow tests?
| Title |
|
Chow tests |
| Author |
William Gould, StataCorp |
| Date |
January 2002; updated July 2011
|
Privately I was asked yet another question on Chow tests. The question
started out “Is a Chow test the correct test to determine whether data
can be pooled together?” and went on from there. Like many on the
list, I am tired of seeing and answering questions on Chow tests. I do not
blame the questioner for asking; I blame their teachers for confusing them
with what is, these days, unnecessary jargon.
In the past, I have always given in and cast my answer in Chow-test terms.
In this reply, I try a different approach and, I think, the result is more
useful.
This reply concerns linear regression (though the technique is really more
general than that), and I gloss over the detail of pooling the residuals and
whether the residual variances are really the same. For the last, I think I
can be forgiven.
Here is what I wrote:
Is a Chow test the correct test to determine whether data can be pooled
together?
A Chow test is simply a test of whether the coefficients estimated over one
group of the data are equal to the coefficients estimated over another, and
you would be better off to forget the word Chow and remember that
definition.
|
History:
In the days when statistical packages were not as sophisticated
as they are now, testing whether coefficients were equal was not so easy.
You had to write your own program, typically in FORTRAN. Chow showed a
way you could perform a Wald test based on statistics that were commonly
reported, and that would produce the same result as if you performed the
Wald test.
|
What does it mean “whether data can be pooled together”? Do you
often meet nonprofessionals who say to you, “I was wondering whether
the data could be pooled?” Forget that phrase, too: it is another
piece of jargon for testing whether the behavior is the same, as measured by
whether the coefficients are the same.
Let’s pretend that you have some model and two or more groups of data.
Your model predicts something about the behavior within the group based on
certain characteristics that vary within the group. Under the assumption
that each group's behavior is unique, you have
y_1 = X_1*b_1 + u_1 (equation for group 1)
y_2 = X_2*b_2 + u_2 (equation for group 2)
and so on. Now you want to test whether the behavior for one group is the
same as for another, which means you want to test
b_1 = b_2 = ...
How do you do that? Testing coefficients across separately fitted models
is difficult to impossible, depending on things we need not go into right
now. A trick is to “pool” the data to convert the multiple
equations into one giant equation
y = d1*(X_1*b1 + u1) + d2*(X_2*b2 + u2) + ...
where y is the set of all outcomes (y_1, y_2, ...), and d1 is a variable
that is 1 when the data are for group 1 and 0 otherwise, d2 is 1 when the
data are for group 2 and 0 otherwise, ....
Notice that from the above I can retrieve the original equations. Setting
d1=1 and d2=d3=...=0, I get the equation for group 1; setting d1=0 and d2=1
and d3=...=0, I get the equation for group 2; and so on.
Now let’s start with
y = d1*(X_1*b1 + u1) + d2*(X_2*b2 + u2) + ...
and rewrite it by a little algebraic manipulation:
y = d1*(X_1*b1 + u1) + d2*(X_2*b2 + u2) + ...
= d1*X_1*b1 + d1*u2 + d2*X_2*b2 + d2*u2 + ...
= d1*X_1*b1 + d2*X_2*b2 + ... + d1*u1 + d2*u2 + ...
= X_1*d1*b1 + X_2*d2*b2 + ... + d1*u1 + d2*u2 + ...
= (X_1*d1)*b1 + (X_2*d2)*b2 + ... + d1*u1 + d2*u2 + ...
By stacking the data, I can obtain estimates of b1, b2, ...
I include not X_1 in my model, but X_1*d1 (a set of variables equal to X_1
when group is 1 and 0 otherwise); I include not X_2 in my model, but X_2*d2
(a set of variables equal to X_2 when group is 2 and 0 otherwise); and so
on.
Let’s use auto.dta and pretend that I have two groups.
. sysuse auto
. generate group1=rep78==3
. generate group2=group1==0
I could fit the models separately:
. regress price mpg weight if group1==1
Source | SS df MS Number of obs = 30
-------------+------------------------------ F( 2, 27) = 16.20
Model | 196545318 2 98272658.8 Prob > F = 0.0000
Residual | 163826398 27 6067644.36 R-squared = 0.5454
-------------+------------------------------ Adj R-squared = 0.5117
Total | 360371715 29 12426610.9 Root MSE = 2463.3
------------------------------------------------------------------------------
price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
mpg | 13.14912 184.5661 0.07 0.944 -365.5492 391.8474
weight | 3.517687 1.015855 3.46 0.002 1.433324 5.60205
_cons | -5431.147 6599.898 -0.82 0.418 -18973.02 8110.725
------------------------------------------------------------------------------
. regress price mpg weight if group2==1
Source | SS df MS Number of obs = 44
-------------+------------------------------ F( 2, 41) = 5.16
Model | 54562909.6 2 27281454.8 Prob > F = 0.0100
Residual | 216614915 41 5283290.61 R-squared = 0.2012
-------------+------------------------------ Adj R-squared = 0.1622
Total | 271177825 43 6306461.04 Root MSE = 2298.5
------------------------------------------------------------------------------
price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
mpg | -170.5474 93.3656 -1.83 0.075 -359.103 18.0083
weight | .0527381 .8064713 0.07 0.948 -1.575964 1.68144
_cons | 9685.028 4190.693 2.31 0.026 1221.752 18148.3
------------------------------------------------------------------------------
I could fit the combined model:
. generate mpg1=mpg*group1
. generate weight1=weight*group1
. generate mpg2=mpg*group2
. generate weight2=weight*group2
. regress price group1 mpg1 weight1 group2 mpg2 weight2, noconstant
Source | SS df MS Number of obs = 74
-------------+------------------------------ F( 6, 68) = 91.38
Model | 3.0674e+09 6 511232168 Prob > F = 0.0000
Residual | 380441313 68 5594725.19 R-squared = 0.8897
-------------+------------------------------ Adj R-squared = 0.8799
Total | 3.4478e+09 74 46592355.7 Root MSE = 2365.3
------------------------------------------------------------------------------
price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
group1 | -5431.147 6337.479 -0.86 0.394 -18077.39 7215.096
mpg1 | 13.14912 177.2275 0.07 0.941 -340.5029 366.8012
weight1 | 3.517687 .9754638 3.61 0.001 1.571179 5.464194
group2 | 9685.028 4312.439 2.25 0.028 1079.69 18290.37
mpg2 | -170.5474 96.07802 -1.78 0.080 -362.2681 21.17334
weight2 | .0527381 .8299005 0.06 0.950 -1.603303 1.708779
------------------------------------------------------------------------------
What is this noconstant option? We must remember that when we fit
the separate models, each has its own intercept. There was an intercept in
X_1, X_2, and so on. What I have done above is literally translate
y = (X_1*d1)*b1 + (X_2*d2)*b2 + d1*u1 + d2*u2
and included the variables group1 and group2 (variables
equal to 1 for their respective groups) and told Stata to omit the overall
intercept.
I do not recommend you fit the model the way I have just illustrated because
of numerical concerns—we will get to that later. Fit the models
separately or jointly, and you will get the same estimates for b_1 and b_2.
Now we can test whether the coefficients are the same for the two groups:
. test _b[mpg1]=_b[mpg2], notest
( 1) mpg1 - mpg2 = 0
. test _b[weight1]=_b[weight2], accum
( 1) mpg1 - mpg2 = 0
( 2) weight1 - weight2 = 0
F( 2, 68) = 5.61
Prob > F = 0.0056
That is the Chow test. Something was omitted: the intercept. If we really
wanted to test whether the two groups were the same, we would would test
. test _b[mpg1]=_b[mpg2]
( 1) mpg1 - mpg2 = 0
. test _b[weight1]=_b[weight2], accum
( 1) mpg1 - mpg2 = 0
( 2) weight1 - weight2 = 0
. test _b[group1]=_b[group2], accum
( 1) mpg1 - mpg2 = 0
( 2) weight1 - weight2 = 0
( 3) group1 - group2 = 0
F( 3, 68) = 4.07
Prob > F = 0.0102
Using this approach, however, we are not tied down by what the “Chow
test” can test. We can formulate any hypothesis we want. We might
think that weight works the same way in both groups but that
mpg works differently, and each group has its own intercept. Then
we could test
. test _b[mpg1]=_b[mpg2]
( 1) mpg1 - mpg2 = 0
F( 1, 68) = 0.83
Prob > F = 0.3654
by itself. If we had more variables, we could test any subset of variables.
Is “pooling the data” justified? Of course it is: we just
established that pooling the data is just another way of fitting separate
models and that fitting separate models is certainly justified—we got
the same coefficients. That’s why I told you to forget the phrase
about whether pooling the data is justified. People who ask that
do not really mean to ask what they are saying; they mean to ask
whether the coefficients are the same. In that case, they should say that.
Pooling is always justified, and it corresponds to nothing more than the
mathematical trick of writing separate equations,
y_1 = X_1*b_1 + u_1 (equation for group 1)
y_2 = X_2*b_2 + u_2 (equation for group 2)
as one equation
y = (X_1*d1)*b1 + (X_2*d2)*b2 + d1*u1 + d2*u2
There are many ways I can write the above equation, and I want to write it a
little differently because of numerical concerns. Starting with
y = (X_1*d1)*b1 + (X_2*d2)*b2 + d1*u1 + d2*u2
let’s do some algebra to obtain
y = X*b1 + d2*X_2*(b2-b1) + d1*y1 + d2*u2
where X = (X_1, X_2). In this formulation, I measure not b1 and b2, but b1
and (b2−b1). This is numerically more stable, and I can still test
that b2==b1 by testing whether (b2−b1)=0.
Let’s fit this model
. regress price mpg weight mpg2 weight2 group2
Source | SS df MS Number of obs = 74
-------------+------------------------------ F( 5, 68) = 9.10
Model | 254624083 5 50924816.7 Prob > F = 0.0000
Residual | 380441313 68 5594725.19 R-squared = 0.4009
-------------+------------------------------ Adj R-squared = 0.3569
Total | 635065396 73 8699525.97 Root MSE = 2365.3
------------------------------------------------------------------------------
price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
mpg | 13.14912 177.2275 0.07 0.941 -340.5029 366.8012
weight | 3.517687 .9754638 3.61 0.001 1.571179 5.464194
mpg2 | -183.6965 201.5951 -0.91 0.365 -585.9733 218.5803
weight2 | -3.464949 1.280728 -2.71 0.009 -6.020602 -.9092956
group2 | 15116.17 7665.557 1.97 0.053 -180.2075 30412.56
_cons | -5431.147 6337.479 -0.86 0.394 -18077.39 7215.096
------------------------------------------------------------------------------
and, if I want to test whether the coefficients are the same, I can do
. test _b[mpg2]=0
( 1) mpg2 = 0
. test _b[weight2]=0, accum
( 1) mpg2 = 0
( 2) weight2 = 0
F( 2, 68) = 5.61
Prob > F = 0.0056
and that gives the same answer yet again. If I want to test whether *ALL*
the coefficients are the same (including the intercept), I can type
. test _b[mpg2]=0, notest
( 1) mpg2 = 0
. test _b[weight2]=0, accum notest
( 1) mpg2 = 0
( 2) weight2 = 0
. test _b[group2]=0, accum
( 1) mpg2 = 0
( 2) weight2 = 0
( 3) group2 = 0
F( 3, 68) = 4.07
Prob > F = 0.0102
Just as before, I can test any subset.
Using this difference formulation, if I had three groups, starting with
y = (X_1*d1)*b1 + (X_2*d2)*b2 + (X_3*d3)*b3 + d1*u1 + d2*u2 + d3*u3
as
y = X*b1 + (X_2*d2)*(b2-b1) + (X_3*d3)*(b3-b1) + d1*u1 + d2*u2 + d3*u3
Let’s create the group variables and fit this model:
. sysuse auto,clear
. generate group1=rep78==3
. generate group2=rep78==4
. generate group3=(group1+group2)==0
. generate mpg1=mpg*group1
. generate weight1=weight*group1
. generate mpg2=mpg*group2
. generate weight2=weight*group2
. generate mpg3=mpg*group3
. generate weight3=weight*group3
. regress price mpg weight mpg2 weight2 group2 ///
> mpg3 weight3 group3
Source | SS df MS Number of obs = 74
-------------+------------------------------ F( 8, 65) = 5.80
Model | 264415585 8 33051948.1 Prob > F = 0.0000
Residual | 370649811 65 5702304.78 R-squared = 0.4164
-------------+------------------------------ Adj R-squared = 0.3445
Total | 635065396 73 8699525.97 Root MSE = 2387.9
------------------------------------------------------------------------------
price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
mpg | 13.14912 178.9234 0.07 0.942 -344.1855 370.4837
weight | 3.517687 .9847976 3.57 0.001 1.55091 5.484463
mpg2 | 130.5261 336.6547 0.39 0.699 -541.8198 802.872
weight2 | -2.18337 1.837314 -1.19 0.239 -5.85274 1.486
group2 | 4560.193 12222.22 0.37 0.710 -19849.27 28969.66
mpg3 | -194.1974 216.3459 -0.90 0.373 -626.27 237.8752
weight3 | -3.160952 1.73308 -1.82 0.073 -6.622152 .3002481
group3 | 14556.66 9167.998 1.59 0.117 -3753.101 32866.41
_cons | -5431.147 6398.12 -0.85 0.399 -18209.07 7346.781
------------------------------------------------------------------------------
If I want to test whether the three groups were the same in the Wald-test
sense, I can type
. test (_b[mpg2]=0) (_b[weight2]=0) (_b[group2]=0) /*
> */ (_b[mpg3]=0) (_b[weight3]=0) (_b[group3]=0)
( 1) mpg2 = 0
( 2) weight2 = 0
( 3) group2 = 0
( 4) mpg3 = 0
( 5) weight3 = 0
( 6) group3 = 0
F( 6, 65) = 2.28
Prob > F = 0.0463
I could more easily type the above command as
. testparm mpg2 weight2 group2 mpg3 weight3 group3
( 1) mpg2 = 0
( 2) weight2 = 0
( 3) group2 = 0
( 4) mpg3 = 0
( 5) weight3 = 0
( 6) group3 = 0
F( 6, 65) = 2.28
Prob > F = 0.0463
Alternatively, we can use factor variables and
contrast
to perform the same test:
. generate group=cond(rep78==3,1,cond(rep78==4,2,3))
. regress price c.mpg##i.group c.weight##i.group
Source | SS df MS Number of obs = 74
-------------+------------------------------ F( 8, 65) = 5.80
Model | 264415585 8 33051948.1 Prob > F = 0.0000
Residual | 370649811 65 5702304.78 R-squared = 0.4164
-------------+------------------------------ Adj R-squared = 0.3445
Total | 635065396 73 8699525.97 Root MSE = 2387.9
------------------------------------------------------------------------------
price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
mpg | 13.14912 178.9234 0.07 0.942 -344.1855 370.4837
|
group |
2 | 4560.193 12222.22 0.37 0.710 -19849.27 28969.66
3 | 14556.66 9167.998 1.59 0.117 -3753.101 32866.41
|
group#c.mpg |
2 | 130.5261 336.6547 0.39 0.699 -541.8198 802.872
3 | -194.1974 216.3459 -0.90 0.373 -626.27 237.8752
|
weight | 3.517687 .9847976 3.57 0.001 1.55091 5.484463
|
group#|
c.weight |
2 | -2.18337 1.837314 -1.19 0.239 -5.85274 1.486
3 | -3.160952 1.73308 -1.82 0.073 -6.622152 .3002481
|
_cons | -5431.147 6398.12 -0.85 0.399 -18209.07 7346.781
------------------------------------------------------------------------------
. contrast group group#c.mpg group#c.weight, overall
Contrasts of marginal linear predictions
Margins : asbalanced
--------------------------------------------------
| df F P>F
---------------+----------------------------------
group | 2 1.29 0.2835
|
group#c.mpg | 2 0.78 0.4617
|
group#c.weight | 2 1.88 0.1602
|
Overall | 6 2.28 0.0463
|
Residual | 65
--------------------------------------------------
|