Skip to content

Commit

Permalink
added dt_setchars() and dt_vlasarray()
Browse files Browse the repository at this point in the history
  • Loading branch information
jrfiedler committed Apr 14, 2014
1 parent cb0b43f commit bd59a3f
Showing 1 changed file with 161 additions and 13 deletions.
174 changes: 161 additions & 13 deletions dt_st_chars.mata
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,51 @@ mata
/**
* @brief Get dataset characteristics from Stata as associative array
* @param evar (optional) scalar containing variable number, variable name, or "_dta"
* @param evarid (optional) scalar variable number, variable name, or "_dta"
* @returns associative array
* @demo
* stata("sysuse auto, clear")
* dtachars = dt_st_chars("_dta")
* asarray_keys(dtachars)
*/
transmorphic dt_st_chars(| transmorphic scalar evar)
transmorphic scalar dt_getchars(| transmorphic scalar evarid)
{
transmorphic scalar A, B
string vector evarlist, charnames
string scalar evarname, charnamei, cmdstub
real scalar i, j, nvar, evarnum
string scalar evarname, charnamei, idtype
real scalar i, j, nvar, evarnum, useall
nvar = st_nvar()
// checking for errors and get chars for specified evar if args() == 1
idtype = eltype(evarid)
// Mata doesn't short-circuit logical tests
useall = 1
if (args() == 1) {
if (eltype(evar) == "real") {
evarnum = round(evar)
if (evar < 1 | evar > nvar) {
useall = 0
if (evarid == "") {
useall == 1
}
else if (idtype == "real") {
useall = missing(evarid)
}
}
// if !useall check for errors and get chars for specified evarid
if (!useall) {
if (idtype == "real") {
evarnum = round(evarid)
if (evarid < 1 | evarid > nvar) {
_error(3300, "argument out of range")
}
evarname = st_varname(evarnum)
}
else if (eltype(evar) == "string") {
if (evar == substr("_dta", 1, strlen(evar))) {
else if (idtype == "string") {
if (evarid == substr("_dta", 1, strlen(evarid))) {
evarname = "_dta"
}
else {
evarnum = _st_varindex(evar, 1)
evarnum = _st_varindex(evarid, 1)
if (evarnum == .) {
_error(3500, "invalid Stata variable name")
}
Expand All @@ -43,14 +57,16 @@ transmorphic dt_st_chars(| transmorphic scalar evar)
_error(3255, "string or real required")
}
// It seems that charnames cannot contain binary.
// If they can, using a local macro as below is not safe.
stata("local _devtools_local : char " + evarname + "[]")
charnames = tokens(st_local("_devtools_local"))
// make associative array
A = asarray_create()
for (j = 1; j <= length(charnames); j++) {
charnamei = charnames[j]
for (i = 1; i <= length(charnames); i++) {
charnamei = charnames[i]
asarray(A, charnamei, st_global(evarname + "[" + charnamei + "]"))
}
Expand All @@ -69,6 +85,8 @@ transmorphic dt_st_chars(| transmorphic scalar evar)
for (i = 1; i <= length(evarlist); i++) {
evarname = evarlist[i]
// It seems that charnames cannot contain binary.
// If they can, using a local macro as below is not safe.
stata("local _devtools_local : char " + evarname + "[]")
charnames = tokens(st_local("_devtools_local"))
Expand All @@ -87,4 +105,134 @@ transmorphic dt_st_chars(| transmorphic scalar evar)
return(A)
}
/**
* @brief Set Stata dataset characteristics using associative array
* @param evarid scalar variable number, variable name, or "_dta". If setting all chars use "" or a missing value.
* @param chararry associative array from which to set characteristics
*/
void dt_setchars(transmorphic scalar evarid, transmorphic scalar chararray)
{
transmorphic B
string vector evarlist, charnames
string scalar evarname, charnamei, idtype
real scalar i, j, nvar, evarnum, useall
nvar = st_nvar()
idtype = eltype(evarid)
// Mata doesn't short-circuit logical tests
useall = 0
if (evarid == "") {
useall == 1
}
else if (idtype == "real") {
useall = missing(evarid)
}
// if !useall check for errors and get chars for specified evarid
if (!useall) {
if (idtype == "real") {
evarnum = round(evarid)
if (evarid < 1 | evarid > nvar) {
_error(3300, "argument out of range")
}
evarname = st_varname(evarnum)
}
else if (idtype == "string") {
if (evarid == substr("_dta", 1, strlen(evarid))) {
evarname = "_dta"
}
else {
evarnum = _st_varindex(evarid, 1)
if (evarnum == .) {
_error(3500, "invalid Stata variable name")
}
evarname = st_varname(evarnum)
}
}
else {
_error(3255, "string or real required")
}
charnames = asarray_keys(chararray)
for (i = 1; i <= length(charnames); i++) {
charnamei = charnames[i]
st_global(
evarname + "[" + charnamei + "]",
asarray(chararray, charnamei)
)
}
}
evarlist = J(1, nvar + 1, "")
evarlist[1] = "_dta"
for (i = 1; i <= nvar; i++) {
evarlist[i + 1] = st_varname(i)
}
for (i = 1; i <= length(evarlist); i++) {
evarname = evarlist[i]
B = asarray(chararray, evarname)
if (B == J(0,0,.)) continue
charnames = asarray_keys(B)
for (j = 1; j <= length(charnames); j++) {
charnamei = charnames[j]
st_global(
evarname + "[" + charnamei + "]",
asarray(B, charnamei)
)
}
}
}
/**
* @brief Get value label from Stata as associative array, or set value label from associative array
* @param vlname scalar containing value label name
* @param vlarray (optional) associative array with integer keys and string contents
* @returns J(0,0,.) (void) if setting value vabel, associative array if retreiving value label
*/
transmorphic dt_vlasarray(string scalar vlname, | transmorphic scalar vlarray)
{
transmorphic scalar A
string vector text
real vector values
real scalar i
// args() == 1 get associative array
if (args() == 1) {
A = asarray_create("real")
if (st_vlexists(vlname)) {
st_vlload(vlname, values, text)
for (i = 1; i <= length(values); i++) {
asarray(A, values[i], text[i])
}
}
return(A)
}
// if args() == 2 set value label
if (st_vlexists(vlname)) {
st_vldrop(vlname)
}
values = asarray_keys(vlarray)
text = J(rows(values), cols(values), "")
for (i = 1; i <= length(values); i++) {
text[i] = asarray(vlarray, floor(values[i]))
}
st_vlmodify(vlname, values, text)
}
end

0 comments on commit bd59a3f

Please sign in to comment.