*! version 0.2.1 2009-05-20 scott long

* TO ADD:   automatically run predict and return results in a matrix?
* TO ADD:   copy row of existing data to new row

capture program drop addobs
program define addobs, rclass

//  DECODE OPTIONS & SETUP PRINTING PARAMETERS

    syntax [if] [in] [, x(passthru) ///
        mean(varlist) min(varlist) max(varlist) med(varlist) ///
        one(varlist) zero(varlist) ///
        add1(varlist) addsd(varlist) addhalf(varlist) addhalfsd(varlist) ///
        sub1(varlist) subsd(varlist) subhalf(varlist) subhalfsd(varlist) ///
        NOList test svy ///
        /// adjust for squares and cubics
        LINear(varlist)             /// linear terms of quadratic
        SQUared(varlist)            /// squared terms
        CUBed(varlist)              /// cubic terms
        row(integer 0) /// if 0, create new row
/// copyrow(integer 0) if 0, no copy
        ]

//  SURVEY and MED INCOMPATIBLE

    if "`svy'"=="svy" {
        if "`med'"!="" {
            di in red "med() option does not work with svy"
            exit
        }
    }

//  ROW NUMBER

    local currentN = _N
    if `row'==0 {
        local rowN = `currentN' + 1
    }
    else {
        local rowN = `row'
    }
    if `rowN' > `currentN' {
        qui set obs `rowN'
    }

//  PARSE X()

    tokenize `x', parse("()")
    local x "`3'"
    tokenize `x', parse(" =")
    while "`1'" != "" {
        * remove ='s
        while "`2'"=="=" | "`2'"=="==" {
            local temp1 "`1'"
            macro shift 1
            local 1 "`temp1'"
        }
        if "`2'"=="" {
            di _newline in red "Odd number of arguments in x()"
            exit
            error 198
        }
        local var "`1'"
        local val "`2'"
        if "`2'"=="mean" {
            if "`svy'"=="svy" {
                qui svy: mean `var' `if' `in'
                mat temp = e(b)
                local val = temp[1,1]
            }
            else {
                qui sum `var' `if' `in'
                local val = r(mean)
            }
        }
        if "`2'"=="min" {
            if "`svy'"=="svy" | "`svy'"!="svy" {
                qui sum `var' `if' `in'
                local val = r(min)
            }
        }
        if "`2'"=="max" {
            if "`svy'"=="svy" | "`svy'"!="svy" {
                qui sum `var' `if' `in'
                local val = r(max)
            }
        }
        if "`2'"=="med" {
            sum `var' `if' `in', detail
            local val = r(p50)
        }
        * make sure variable is in dataset?
        local found "no"
        capture confirm numeric variable `1'
        if _rc!=0 {
            di in red "error: `1' not in dataset"
            exit
            error 198
        }
        qui replace `var' = `val' in `rowN'
        local varset "`varset' `1'"
        macro shift 2
    } // end of x()

//  MEAN
    if "`mean'"!="" {
        foreach var in `mean' {
            if "`svy'"=="svy" {
                qui svy: mean `var' `if' `in'
                mat temp = e(b)
                local val = temp[1,1]
            }
            else {
                qui sum `var' `if' `in'
                local val = r(mean)
            }
            qui replace `var' = `val' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  MIN
    if "`min'"!="" {
        foreach var in `min' {
            qui sum `var' `if' `in'
            local val = r(min)
            qui replace `var' = `val' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  MAX
    if "`max'"!="" {
        foreach var in `max' {
            qui sum `var' `if' `in'
            local val = r(max)
            qui replace `var' = `val' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  ONE
    if "`one'"!="" {
        foreach var in `one' {
            local val = 1
            * replace variable
            qui replace `var' = `val' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  ZERO
    if "`zero'"!="" {
        foreach var in `zero' {
            local val = 0
            qui replace `var' = `val' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  MEDIAN if not svy
    if "`med'"!="" {
        foreach var in `med' {
            qui sum `var' `if' `in', detail
            local val = r(p50)
            qui replace `var' = `val' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  -----------------------------------------------------------------------------
//  ADD TO CURRENT value

//  ADDSD
    if "`addsd'"!="" {
        foreach var in `addsd' {
            if "`svy'"=="svy" {
                qui svy: mean `var' `if' `in'
                qui estat sd
                mat tempsd = r(sd)
                local tempsd = tempsd[1,1]
            }
            else {
                qui sum `var' `if' `in'
                local tempsd = r(sd)
            }
            qui replace `var' = `var' + `tempsd' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  ADDHALFSD
    if "`addhalfsd'"=="" {
        foreach var in `addhalfsd' {
            if "`svy'"=="svy" {
                qui svy: mean `var' `if' `in'
                qui estat sd
                mat tempsd = r(sd)
                local tempsd = tempsd[1,1]
            }
            else {
                qui sum `var' `if' `in'
                local tempsd = r(sd)
            }
            qui replace `var' = `var' + (`tempsd'/2) in `rowN'
            local varset "`varset' `var'"
        }
    }

//  ADD1
    if "`add1'"!="" {
        foreach var in `add1' {
            qui replace `var' = `var' + 1 in `rowN'
            local varset "`varset' `var'"
        }
    }

//  ADDHALF
    if "`addhalf'"!="" {
        foreach var in `addhalf' {
            qui replace `var' = `var' + .5 in `rowN'
            local varset "`varset' `var'"
        }
    }

//  -----------------------------------------------------------------------------
//  SUBTRACT

//  SUBSD
    if "`subsd'"!="" {
        foreach var in `subsd' {
            if "`svy'"=="svy" {
                qui svy: mean `var' `if' `in'
                qui estat sd
                mat tempsd = r(sd)
                local tempsd = tempsd[1,1]
            }
            else {
                qui sum `var' `if' `in'
                local tempsd = r(sd)
            }
            qui replace `var' = `var' - `tempsd' in `rowN'
            local varset "`varset' `var'"
        }
    }

//  SUBHALFSD
    if "`subhalfsd'"=="" {
        foreach var in `subhalfsd' {
            if "`svy'"=="svy" {
                qui svy: mean `var' `if' `in'
                qui estat sd
                mat tempsd = r(sd)
                local tempsd = tempsd[1,1]
            }
            else {
                qui sum `var' `if' `in'
                local tempsd = r(sd)
            }
            qui replace `var' = `var' - (`tempsd'/2) in `rowN'
            local varset "`varset' `var'"
        }
    }

//  SUB1
    if "`sub1'"!="" {
        foreach var in `sub1' {
            qui replace `var' = `var' - 1 in `rowN'
            local varset "`varset' `var'"
        }
    }

//  SUBHALF
    if "`subhalf'"!="" {
        foreach var in `subhalf' {
            qui replace `var' = `var' - .5 in `rowN'
            local varset "`varset' `var'"
        }
    }

//  LINEAR, QUADRATIC AND CUBIC

    if "`linear'"!="" {
        if "`squared'"!="" {
            qui replace `squared' = `linear'^2 in `rowN'
            local varset "`varset' `linear' `squared'"
        }
        if "`cubed'"!="" {
            qui replace `cubed' = `linear'^3 in `rowN'
            local varset "`varset' `linear' `cubed'"
        }
    }

//  LIST NEW OBSERVATION

    if "`nolist'"=="" {
        local temp "modified among "
        if `row'==0 {
            local temp "added to"
        }
        di _new in green "Row " in white "`rowN'" ///
                in green " `temp' " in white "`currentN'" ///
                in green " rows. Changed values are:"
        local varset2 : list uniq varset
        list `varset2' in `rowN', clean nolab
    }
*    if "`nolist'"=="" {
*        list _all in `rowN', nolab
*    }

end

exit

HISTORY

2006-07-25 - initial version.
2009-05-19 - version 0.2.0 which ignores spost; added to scottlong.pkg
2009-05-21 - v0.2.1 - cleanup code