program  macroF ,rclass
*! version 0.1.0  Aug, 2021
    version 17.0
    syntax [if] [in], pred(str) true(str)

	// the variables pred and true must have integer values (not strings)
	confirm numeric variable `pred' `true'

	//  obs excluded by [if] [in]
	marksample touse , novarlist
	qui count if `touse'
	if r(N) == 0 {
		error 2000
	}
	local truth="`true'"

	preserve
	qui drop if !`touse'

	qui levelsof `truth'
	local mylevels = "`r(levels)'"
	local n_levels= wordcount("`mylevels'")
	local macroF=0

	tempvar true1 pred1
	qui gen `true1'=.
	qui gen `pred1'=.
	di "Level    F1"
	foreach i of numlist 1/`n_levels' {
		local level= word("`mylevels'",`i')
		// generate indicators for each level
		qui replace `true1'= `truth'==`level' if !missing(`truth')
		qui replace `pred1' = `pred'==`level' if !missing(`truth')
		qui evalcrit2, pred(`pred1')  true(`true1') // evalcrit is only for binary
		local macroF= `macroF' + `r(F)'
		di %5.0g `level' "   "   %8.5f `r(F)'
	}
	local macroF=`macroF'/`n_levels'
	di " "
	di "macroF=" `macroF'
	return scalar macroF=`macroF'
end
//////////////////////////////////////////////////////////////////////////////////
// This is a copy of a separate program, evalcrit.
// I have changed the name to evalcrit2 just to avoid confusion.
// I am including it in this file to make the macroF program independent.
program  evalcrit2 ,rclass
// version 0.3.1  Dec, 2020 added round
    version 13.1
    syntax [if] [in], pred(str) true(str) [ round(real 0.0001) ]

	//  obs excluded by [if] [in]
	marksample touse , novarlist
	qui count if `touse'
	if r(N) == 0 {
		error 2000
	}
	preserve

	local binary=1
	qui tab `pred' if `touse'
	if r(r)>2 local binary=0
	qui tab `true' if `touse'
	if r(r)>2 local binary=0

	tempname TP TN FN FP F jaccard
	if `binary' {
		qui count if `pred'==1 & `true'==1 & `touse'
		scalar `TP'=r(N)
		qui count if `pred'==0 & `true'==0 & `touse'
		scalar `TN'=r(N)
		qui count if `pred'==0 & `true'==1 & `touse'
		scalar `FN'=r(N)
		qui count if `pred'==1 & `true'==0 & `touse'
		scalar `FP'=r(N)
		scalar `F'= 2 *`TP' / (2* `TP' + `FP' + `FN' )
		scalar `jaccard' = `TP' / (`TP' + `FP' + `FN' )
		di "Sensitivity: " round(`TP'/(`TP'+`FN'),`round')
		di "Specificity: " round(`TN'/(`TN'+`FP'),`round')
		di "F:           " round(`F',`round')
		di "Jaccard:     " round(`jaccard',`round')
	}

	tempvar correct
	tempname acc
	qui gen `correct'= `pred' == `true' if `touse'
	qui sum `correct' if `touse'
        scalar `acc'= r(mean)
	di "Accuracy:    " round(`acc',`round')

	return scalar accuracy = `acc'

	if `binary' {
		return scalar sensitivity = `TP'/(`TP'+`FN')
		return scalar specificity = `TN'/(`TN'+`FP')
		return scalar F = `F'
		return scalar jaccard= `jaccard'
	}
end
/////////////////////////////////////////////////////////////////
// version history of macroF
* version 0.1.0  Aug , 2021