Stata simple key-value pairs

I am defining a categorical variable using a set of named rules. I want to put these rules in the preamble as "parameters" that I can easily change later. I am wondering how to do this. I feel like a reproducible example is not needed here, as I am asking - generally - what is a good way of setting parameters that are essentially key-value structured in Stata?

This is the code I am currently using to classify days in terms of weather event dummies.

preserve 
clear
input str12 key str40 val
"Clear"         "!(event_thunder|event_snow|event_rain)"
"Rain"          "event_rain & !(event_thunder|event_snow)"
"Snow"          "event_snow & !(event_thunder|event_rain)"
"Rain & Snow"   "(event_snow & event_rain) & !event_thunder"
"Thunder"       "event_thunder"
end

scalar N_events = _N

forvalues i = 1/`=N_events'{
    scalar  event_key`i' = key[`i']
    scalar  event_val`i' = val[`i']
}
restore

      

Later in the code, I can iterate over my "key" and "shaft" scalars to define my categorical variable.

gen byte event = 0
forvalues i = 1/`=N_events'{
    local event_condition `=event_val`i''
    replace event = `i' if `event_condition'
}

      

I still haven't figured out the correct code to apply the label with my scanners event_key*

. Any advice on this is also appreciated.

+3


source to share


1 answer


Your code with some tweaks is equivalent to this example:

clear
set more off

sysuse auto
keep make price foreign

preserve

    clear

    input str12 key str40 val
    "for_cheap"         "foreign & price < 10000"
    "hom_expen"         "!foreign & price >= 10000"
    end

    local numkeys = _N

    forvalues i = 1/`numkeys' {
        local  event_key`i' = key[`i']
        local  event_val`i' = val[`i']
    }

restore 

gen byte event = 0
forvalues i = 1/`numkeys' {
    replace event = `i' if `event_val`i''
}

save testing, replace

      

But you just want this, which gives the same result:

clear
set more off

sysuse auto
keep make price foreign

gen byte event = 0
replace event = 1 if foreign & price < 10000
replace event = 2 if !foreign & price >= 10000

// to test these results with previous
cf _all using testing, verbose

      

You can still put conditions in locals, for example, and use this:

<snip>

local for_cheap foreign & price < 10000
local hom_expen !foreign & price >= 10000

gen byte event = 0
replace event = 1 if `for_cheap'
replace event = 2 if `hom_expen'

      

Also, you can use loops instead of multiple replace

s:

<snip>

local for_cheap "foreign & price < 10000"
local hom_expen "!foreign & price >= 10000"

local allcond for_cheap hom_expen
local n : word count `allcond'

gen byte event = 0
forvalues i = 1/`n' {
    local cond `:word `i' of `allcond'' // extended macro function
    replace event = `i' if ``cond''

    // syntax for value labels
    local lbl `lbl' `i' "`cond'" 
}

label define lblevent `lbl'
label values event lblevent

list in 1/25

      



This puts each named condition in a different local name allcond

. Then use parallel lists to iterate over. I also added code for value labels.

See also help extended_fcn

for reading advanced macro functions (which I used).

If you only want to declare key / values ​​once, you can still do it using only locals:

clear

sysuse auto
keep make price foreign

local allcond for_cheap "foreign & price < 10000" ///
              hom_expen "!foreign & price >= 10000"

local n : word count `allcond'

gen byte event = 0
forvalues i = 2(2)`n' {

    // get label and condition (extended macro function)
    local condlbl `:word `=`i'-1' of `allcond''
    local cond `:word `i' of `allcond'' 

    // replace
    replace event = `=`i'/2' if `cond'

    // syntax for value labels
    local lbl `lbl' `=`i'/2' "`condlbl'"  
}

label define lblevent `lbl'
label values event lblevent

      

But for now, your database strategy (and my equivalent code) is easier to read.

By the way, depending on the rest of the code, you can probably avoid it preserve/restore

. You can input

enter the key / values first and then load the working database:

clear
set more off

// input key/val database

input str12 key str40 val
"for_cheap"         "foreign & price < 10000"
"hom_expen"         "!foreign & price >= 10000"
end

local numkeys = _N

forvalues i = 1/`numkeys' {
    local  event_key`i' = key[`i']
    local  event_val`i' = val[`i']
}

// load working database

clear

sysuse auto
keep make price foreign

gen byte event = 0
forvalues i = 1/`numkeys' {
    replace event = `i' if `event_val`i''
}

list

      

+4


source







All Articles