*! version 1.2.1 14nov2019 daniel klein program elabel_cmd_compare // , rclass version 11.2 if (_caller() >= 16) local f f elabel parse elblnamelist [ if`f' ] [ , ASSERTIDENTICAL ] : `0' tokenize `lblnamelist' if (("`2'"=="") | ("`3'"!="")) { local fewmany = cond("`2'"=="", "few", "many") display as err "too `fewmany' names specified" exit 198 } gettoken ifword iff : if`f' mata : elabel_cmd_compare() end version 11.2 if (c(stata_version)>=14) local ud ud local TS transmorphic scalar local SR string rowvector local RC real colvector local RR real rowvector local RS real scalar local SS string scalar local EC struct elabel_cmd_compare__ rowvector mata : mata set matastrict on struct elabel_cmd_compare__ { `TS' vl `SR' maps `RC' tag } void elabel_cmd_compare() { `EC' ec ec = elabel_cmd_compare__(2) elabel_cmd_compare_load(ec) elabel_cmd_compare_assert(ec) elabel_cmd_compare_stats(ec) if (ec[1].maps!=ec[2].maps) { elabel_cmd_compare_diffs(ec[1], ec[2]) elabel_cmd_compare_diffs(ec[2], ec[1]) elabel_cmd_compare_joint(ec) } else { printf("{txt} value labels {res}%s{txt}" , elabel_vlname(ec[1].vl)) printf(" and {res}%s{txt} are identical\n", elabel_vlname(ec[2].vl)) } elabel_cmd_compare_return(ec) } void elabel_cmd_compare_load(`EC' ec) { `RS' i for (i=1; i<=2; ++i) { ec[i].vl = elabel_vlinit(st_local(strofreal(i))) elabel_vlmarkif(ec[i].vl, st_local("iff")) ec[i].maps = (strofreal(elabel_vlvalues(ec[i].vl)) + elabel_vllabels(ec[i].vl))' } } void elabel_cmd_compare_assert(`EC' ec) { if (st_local("assertidentical") == "") return st_rclear() st_global("r(name1)", elabel_vlname(ec[1].vl)) st_global("r(name2)", elabel_vlname(ec[2].vl)) st_numscalar("r(identical)", (ec[1].maps==ec[2].maps)) if (ec[1].maps==ec[2].maps) exit(0) // NotReached errprintf("value labels {bf}%s{sf} and ", elabel_vlname(ec[1].vl)) errprintf("{bf}%s{sf} are not identical\n", elabel_vlname(ec[2].vl)) exit(9) } void elabel_cmd_compare_stats(`EC' ec) { `RR' len `RS' col `SS' fmt len = (max((6, `ud'strlen(elabel_vlname(ec[1].vl)))), max((6, `ud'strlen(elabel_vlname(ec[2].vl))))) col = rowsum(len)+3 fmt = sprintf("%%%fs%%%fs", (len[1]+1), (len[2]+2)) printf("\n{txt} {hline 10}{c TT}{hline %f}", col) printf("\n{col 13}{c |}") printf(fmt, elabel_vlname(ec[1].vl), elabel_vlname(ec[2].vl)) printf("\n{txt} {hline 10}{c +}{hline %f}", col) printf("\n{txt}{col 9}min {c |}{res}") printf(fmt, strofreal(min(elabel_vlvalues(ec[1].vl))), strofreal(min(elabel_vlvalues(ec[2].vl)))) printf("\n{txt}{col 9}max {c |}{res}") printf(fmt, strofreal(max(elabel_vlvalues(ec[1].vl))), strofreal(max(elabel_vlvalues(ec[2].vl)))) printf("\n{txt}{col 5}missing {c |}{res}") printf(fmt, strofreal(elabel_vlnemiss(ec[1].vl)), strofreal(elabel_vlnemiss(ec[2].vl))) printf("\n{txt}{col 11}k {c |}{res}") printf(fmt, strofreal(elabel_vlk(ec[1].vl)), strofreal(elabel_vlk(ec[2].vl))) printf("\n{txt} {hline 10}{c BT}{hline %f}\n", col) } void elabel_cmd_compare_diffs(`EC' a, `EC' b) { `TS' avl if (!any(a.tag=(!_aandb(a.maps, b.maps))')) return printf("\n{txt} only defined in {res}%s{txt}\n", elabel_vlname(a.vl)) pragma unset avl elabel_vlcopy(a.vl, avl) elabel_vlmark(avl, a.tag) elabel_vllistmappings(avl) } void elabel_cmd_compare_joint(`EC' ec) { `TS' vl if (!any(!ec[1].tag)) return printf("\n{txt} defined in both {res}%s{txt} and {res}%s{txt}\n", elabel_vlname(ec[1].vl), elabel_vlname(ec[2].vl)) pragma unset vl elabel_vlcopy(ec[1].vl, vl) elabel_vlmark(vl, !ec[1].tag) elabel_vllistmappings(vl) } void elabel_cmd_compare_return(`EC' ec) { `TS' vl `SS' v, t `RS' k, i pragma unset vl pragma unset v pragma unset t st_rclear() if ((ec[1].maps==ec[2].maps) | (any(!ec[1].tag))) { elabel_vlcopy(ec[1].vl, vl) if (any(!ec[1].tag)) elabel_vlmark(vl, !ec[1].tag) elabel_vllist(vl, v, t, 0) k = elabel_vlk(vl) st_global("r(labels)", t) st_global("r(values)", v) } for (i=1; i<=2; ++i) { st_numscalar(sprintf("r(min%f)", i), min(elabel_vlvalues(ec[i].vl))) st_numscalar(sprintf("r(max%f)", i), max(elabel_vlvalues(ec[i].vl))) st_numscalar(sprintf("r(nemiss%f)", i), elabel_vlnemiss(ec[i].vl)) st_numscalar(sprintf("r(k%f)", i), elabel_vlk(ec[i].vl)) st_global(sprintf("r(name%f)", i), elabel_vlname(ec[i].vl)) if (!any(ec[i].tag)) continue elabel_vlcopy(ec[i].vl, vl) elabel_vlmark(vl, ec[i].tag) elabel_vllist(vl, v, t, 0) st_global(sprintf("r(labels%f)", i), t) st_global(sprintf("r(values%f)", i), v) } st_numscalar("r(k)", (missing(k) ? 0 : k)) st_numscalar("r(identical)", (ec[1].maps==ec[2].maps)) } end exit /* --------------------------------------- 1.2.1 14nov2019 use new vl.listmappings() 1.2.0 23oct2019 new option -assertidentical- 1.1.1 15jul2019 respect matastrict setting 1.1.0 03jun2019 use -iff- in place of -if- 1.0.1 24may2019 allow identical label names 1.0.0 09feb2019 first version