*! NJC 1.2.2 26 January 1999
* 1.2.1  13 January 1998
program define tabchii
        version 5.0
        parse "`*'", parse(",\ ")

        local r 1
        local c 1
        local cols .
        while "`1'" != "" & "`1'" != "," {
                if "`1'" == "\" {
                        local r = `r' + 1
                        if `cols' == . {
                                if `c' <= 2 {
                                        di in red "too few columns"
                                        exit 198
                                }
                                local cols `c'
                        }
                        else if `c' != `cols' { error 198 }
                        local c 1
                }
                else {
                        conf integer num `1'
                        if `1' < 0 { error 411 }
                        local n`r'`c' `1'
                        local c = `c' + 1
                }
                mac shift
        }
        if `c' != `cols' { error 198 }
        local cols = `cols' - 1
        local rows = `r'

        local options "REPLACE Raw Pearson Adjust Cont noO noE *"
        parse "`*'"
        quietly {
                if "`replace'" != "" {  drop _all }
                preserve
                drop _all
                local obs 1
                set obs 1
                gen byte row = .
                gen byte col = .
                gen long observed = .
                local r 1
                while `r' <= `rows' {
                        local c 1
                        while `c' <= `cols' {
                                set obs `obs'
                                replace row = `r' in l
                                replace col = `c' in l
                                replace observed = `n`r'`c'' in l
                                local obs = `obs' + 1
                                local c = `c' + 1
                        }
                        local r = `r' + 1
                }
                sort col
                by col: gen double colsum = sum(observed)
                by col: replace colsum = colsum[_N]
                sort row col
                by row: gen double rowsum = sum(observed)
                by row: replace rowsum = rowsum[_N]
                su observed, meanonly
                local tabsum = _result(18)
                gen double expected = (rowsum * colsum) / `tabsum'
                count if exp < 5
                local lt5 = _result(1)
                count if exp < 1
                local lt1 = _result(1)
                gen double raw = observed - expected
                gen double Pearson = (observed - exp) / sqrt(exp)
                gen double cont = ((observed - exp)^2) / exp
                gen double adjusted = Pearson / sqrt((1 - rowsum / `tabsum') /*
                 */                                 *(1 - colsum/`tabsum'))
                format exp raw Pear cont adj %9.3f
                noi di
                noi if "`o'" != "noo" {
                        di in g _dup(10) " " "observed frequency"
                }
                noi if "`e'" != "noe" {
                        di in g _dup(10) " " "expected frequency"
                }
                noi if "`raw'" == "raw" {
                        di in g _dup(10) " " "raw residual"
                        local res "raw"
                }
                noi if "`pearson'" == "pearson" {
                        di in g _dup(10) " " "Pearson residual"
                        local res "`res' Pearson"
                }
                noi if "`cont'" == "cont" {
                        di in g _dup(10) " " "contribution to chi-square"
                        local res "`res' cont"
                }
                if "`adjust'" == "adjust" {
                        di in g _dup(10) " " "adjusted residual"
                        local res "`res' adjusted"
                }
                if "`o'" != "noo" { local show "obs" }
                if "`e'" != "noe" { local show "`show' exp" }
                noi {
                        if "`show'`res'" != "" {
                                tabdisp row col, c(`show' `res') `options'
                        }
                        if `lt5' > 1 {
                                di _n in g /*
                                 */ "`lt5' cells with expected frequency < 5"
                        }
                        else if `lt5' == 1 {
                                di _n in g /*
                                 */ "1 cell with expected frequency < 5"
                        }
                        if `lt1' > 1 {
                                di in g /*
                                 */ "`lt1' cells with expected frequency < 1"
                        }
                        else if `lt1' == 1 {
                                di in g /*
                                 */ "1 cell with expected frequency < 1"
                        }
                }
                tabulate row col [fw=obs], chi2 lrchi2
                local df = (`rows' - 1) * (`cols' - 1)
                noi di _n in g _dup(9) " " "Pearson chi2(" in y "`df'"   /*
                */ in g ") = " in y %8.4f _result(4) in g "   Pr = "     /*
                */ in y %5.3f _result(5)
                noi di in g "likelihood-ratio chi2(" in y "`df'"         /*
                */ in g ") = " in y %8.4f _result(6) in g "   Pr = "     /*
                */ in y %5.3f _result(7)

                if "`replace'"!="" {
                        drop rowsum colsum
                        label var observed "observed frequency"
                        label var expected "expected frequency"
                        label var raw "raw residual"
                        label var Pearson "Pearson residual"
                        label var cont "contribution to chi-square"
                        label var adjusted "adjusted residual"
                        restore, not
                }
        }
end