📄 labelbook.ado
字号:
*! version 1.2.12 01feb2005
program define labelbook, rclass
version 8
syntax [anything(id=lblnamelist name=names)] [using/] [, ///
Alpha Detail LEngth(int 12) LIst(int 32000) Problems ]
local strlen = c(maxstrvarlen)
if !inrange(`length',1,`strlen') {
// max string length
dis as err "length() should be in range [1,`strlen']"
exit 198
}
loc sh `length' // length of shortened vallabels
if `list' < 0 {
dis as err "list() should be positive"
exit 198
}
if "`problems'" == "" {
loc detail detail
}
// parsing is ready
preserve
if `"`using'"' != "" {
use `"`using'"' , clear
}
// the option -var- of -uselabel- specifies that
// varlists that "use" the labels are saved in r(labname)
//
// If the data contains labels in more than one language
// the varlists for the non-active languages are returned
// in r(labname_ln)
uselabel `names' , var clear
if _N==0 {
exit
}
local labnames `r(__labnames__)'
local cln `r(__current_language__)'
local olns `r(__other_languages__)'
local nlns = `:list sizeof olns' + 1
local vl_notused
foreach lbn of local labnames {
local lbused 0
local xx `"`cln' `"`r(`lbn')'"'"'
if ("`r(`lbn')'" != "") {
local lbused 1
}
foreach ln of local olns {
local xx `"`xx' `ln' `"`r(`lbn'_`ln')'"'"'
if ("`r(`lbn'_`ln')'" != "") {
local lbused 1
}
}
local v_`lbn' `"`xx'"'
if !`lbused' {
local vl_notused `vl_notused' `lbn'
}
}
local vl_notused : list sort vl_notused
confirm exist lname value label
confirm string var lname
confirm string var label
confirm numeric var value
// value should be integer valued
capt assert value==round(value)
if _rc {
dis as err "labelbook: this should not happen"
dis as err "value is not integer-valued"
exit 9999
}
// sysmiss cannot be labeled
capt assert value != .
if _rc {
dis as err "labelbook: this should not happen"
dis as err "sysmiss (.) seems to be value labeled"
exit 9999
}
// labels that can be interpreted as numbers
gen numlabel = !missing(real(label))
bys lname (numlabel): gen label_num = numlabel[_N]
// blank labels (yes, this allowed in Stata!)
gen null = trim(label) == ""
bys lname (null) : gen L_null = null[_N]
// leading/trailing blanks
gen ltblanks = trim(label) != label
bys lname (ltblanks) : gen L_ltblanks = ltblanks[_N]
// truncated labels
bys lname (trunc) : gen L_trunc = trunc[_N]
// statistics on length of labels
gen labellen = length(label)
bys lname (labellen): gen l_min = labellen[1]
bys lname (labellen): gen l_max = labellen[_N]
// non-truncated labels are unique within VL ?
bys lname label : gen N = _N == 1
bys lname (N) : gen Unique = (N[1]==1 | L_trunc)
drop N
// truncated labels are unique within VL ?
bys lname label : gen N = _N == 1
bys lname (N) : gen TrUnique = (N[1]==1 | !L_trunc)
drop N
// shortened_labels are unique within VL ?
qui gen str`sh' shlabel = substr(label,1,`sh')
bys lname shlabel: gen N = _N == 1
bys lname (N) : gen shUnique = N[1]==1
drop N
// statistics on values
bys lname : gen nmiss = sum(missing(value))
qui bys lname : replace nmiss = nmiss[_N]
bys lname (value) : gen v_n = _N
bys lname (value) : gen v_min = value[1]
bys lname (value) : gen v_max = value[_N-nmiss[_N]]
bys lname (value) : gen v_gap = (v_max-v_min+1) - (v_n-nmiss)
// random selection of labels within VLs
if `list' != 32000 {
gen rnd = uniform()
bys lname (rnd) : gen show = _n <= `list'
}
else {
gen byte show = 1
}
// details for display info on vlabels
if "`alpha'" != "" {
sort lname label value
}
else {
sort lname value label
}
loc alablist // list of labels in alpha order
loc n2 = 0
while `n2' < _N { // loop over all value labels
loc n1 = `n2' + 1
loc vlabel = lname[`n1']
loc alablist `alablist' `vlabel'
loc nlab = v_n[`n1']
loc n2 = `n1' + `nlab' - 1
if !Unique[`n1'] {
loc vl_nuniq `vl_nuniq' `vlabel'
}
if !TrUnique[`n1'] {
loc vl_ntruniq `vl_ntruniq' `vlabel'
}
if !shUnique[`n1'] {
loc vl_nuniq_sh `vl_nuniq_sh' `vlabel'
}
if L_null[`n1'] {
loc vl_null `vl_null' `vlabel'
}
if L_ltblanks[`n1'] {
loc vl_ltblanks `vl_ltblanks' `vlabel'
}
if v_gap[`n1'] > 0 {
loc vl_gaps `vl_gaps' `vlabel'
}
if label_num[`n1'] > 0 {
loc vl_numeric `vl_numeric' `vlabel'
}
if "`detail'" != "" {
#del ;
LabelDetail "`n1'"
"`n2'"
"`vlabel'"
"`sh'"
"`list'"
"`varlabel'"
"`nlns'"
`"`v_`vlabel''"' ;
#del cr
}
}
restore
if "`problems'" != "" {
#del ;
Problems "`alablist'"
"`sh'"
"`vl_numeric'"
"`vl_gaps'"
"`vl_ltblanks'"
"`vl_null'"
"`vl_nuniq'"
"`vl_ntruniq'"
"`vl_nuniq_sh'"
"`vl_notused'" ;
#del cr
}
ret loc names `alablist'
ret loc gaps `vl_gaps'
ret loc numeric `vl_numeric'
ret loc blanks `vl_ltblanks'
ret loc null `vl_null'
ret loc nuniq `vl_nuniq'
ret loc ntruniq `vl_ntruniq'
ret loc nuniq_sh `vl_nuniq_sh'
ret loc notused `vl_notused'
end
program define LabelDetail
args n1 n2 vlabel sh list varlabel nlang vlist
local trunc = L_trunc[`n1']
dis _n as txt "{hline}" _n "value label " ///
as res "`vlabel' "
if (`trunc') {
dis as txt "(note: label has values longer than " ///
"`c(maxstrvarlen)'; values truncated for analysis below)"
}
dis as txt "{hline}" _n
#del ;
dis _col(7) as txt "{hi:values}"
_col(49) "{hi:labels}" ;
dis _col(8) as txt "range: [" as res v_min[`n1']
as txt "," as res v_max[`n1'] as txt "]"
_col(42) as txt "string length: [" as res l_min[`n1']
as txt "," as res l_max[`n1'] as txt "]" ;
if (`trunc') { ;
local c2 = 38 - length("`c(maxstrvarlen)'") ;
dis _col(12) as txt "N: " as res v_n[`n1']
_col(`c2') as txt "unique at length `c(maxstrvarlen)': "
as res cond(TrUnique[`n1'],"yes","no") ;
} ;
else { ;
dis _col(12) as txt "N: " as res v_n[`n1']
_col(34) as txt "unique at full length: "
as res cond(Unique[`n1'],"yes","no") ;
} ;
dis _col(9) as txt "gaps: "
as res cond(v_gap[`n1'],"yes","no")
_col(36) as txt "{ralign 20:unique at length `sh':} "
as res cond(shUnique[`n1'],"yes","no") ;
dis _col(3) as txt "missing .*: "
as res nmiss[`n1']
_col(44) as txt "null string: "
as res cond(L_null[`n1'],"yes","no") ;
dis _col(32) as txt "leading/trailing blanks: "
as res cond(L_ltblanks[`n1'],"yes","no") ;
dis _col(37) as txt "numeric -> numeric: "
as res cond(label_num[`n1'],"yes","no") ;
#del cr
if `list' > 0 {
dis " {hi:definition}"
loc nlab = `n2'-`n1'+1
if `nlab' > `list' {
dis as txt _col(8) ///
"`list' random examples out of `nlab' labels" _n
}
forvalues i = `n1'/`n2' {
if !show[`i'] {
continue
}
if null[`i'] {
dis as txt %12.0f value[`i']
// as res " {it:empty string/blanks}"
continue
}
local v = value[`i']
local sp = 12 - length("`v'")
dis as txt "{p 0 15 2}{space `sp'}`v'{space 2}"
if length(trim(label[`i'])) > `sh' {
// underline chars 1..sh
loc ul 1
local vl1 = substr(label[`i'],1,`sh')
dis as res `" {ul:`macval(vl1)'}"' substr(label[`i'],`sh'+1,.)
}
else {
dis as res label[`i']
}
dis "{p_end}"
}
/*
if "`ul'" != "" {
dis as txt "underlining `sh' chars of longer labels"
dis as txt "red underscores are leading/trailing blanks"
}
*/
}
// variables to which value label is attached in the different languages
if `nlang' == 1 {
gettoken ln vlist : vlist
dis _n as txt `"{p 3 15}variables:{space 2}"' as res `vlist'
dis
}
else {
local rest `vlist'
local used = 0
forvalues i = 1/`nlang' {
gettoken ln rest : rest
gettoken vlist rest : rest
if "`vlist'" != "" {
dis _n as txt "{p 3 23}in {res:`ln'} attached to " ///
as res "`vlist'"
local used 1
}
}
if !`used' {
dis as txt _n " not attached to any variable in any language"
}
dis
}
end
program define Problems
args alablist sh numeric gaps ltblanks null ///
nuniq ntruniq nuniq_sh notused
if `"$S_FN"' == "" {
loc dataset "[unnamed]"
}
else {
_shortenpath `"$S_FN"' , len(`=c(linesize)-35')
loc dataset `"`r(pfilename)'"'
}
loc vlen 0
foreach source in numeric gaps ltblanks null ///
nuniq ntruniq nuniq_sh notused {
loc vlen = max(`vlen', `:length local `source'')
}
dis
if `vlen' == 0 {
dis `"{txt}no potential problems in dataset {res}`dataset'"'
exit
}
dis `"{txt} Potential problems in dataset {res}`dataset'"' _n
dis as txt _col(16) "potential problem value labels"
loc hlen = clip(35+`vlen', 50, `c(linesize)')
dis as txt "{hline `hlen'}"
Msg "`numeric'" `"numeric -> numeric"'
Msg "`gaps'" `"gaps in mapped values"'
Msg "`ltblanks'" `"leading or trailing blanks"'
Msg "`null'" `"numeric -> null str"'
Msg "`nuniq'" `"duplicate labels"'
Msg "`ntruniq'" `"duplicate lab. at length `c(maxstrvarlen)'"'
Msg "`nuniq_sh'" `"duplicate lab. at length `sh'"'
Msg "`notused'" `"not used by variables"'
dis as txt "{hline `hlen'}"
end
program define Msg
args mac txt
if "`mac'" == "" {
exit
}
loc len = 32-length(`"`txt'"')
dis as txt "{p 0 35}{space `len'}`txt'{space 3}" as res "`mac'" "{p_end}"
end
exit
HISTORY
1.2.12 long label (> maxstrvarlen) changes
1.2.9 language support
1.2.5 bug fix - order of output could be random
1.2.4 bug fix - gaps
1.2.3 Stata/SE
1.2.2 shortening long paths
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -