Appraisal Process
Olivia Beck
18 October, 2023
Source:vignettes/appraisal-process.Rmd
appraisal-process.Rmd
Testing github pages deploy
The appraisal process consists of three steps:
- Option 1: Simple search using step 1 inputs to narrow search criteria
- Option 2: Detailed search & Manual Selection
Step 1: Attributes of Reference Nonprofit
The user needs to input the following attributes of their nonprofit: the U.S. state or territory the nonprofit is located in, if the non profit is located in a metropolitan or rural area, the total annual expense of the nonprofit in the most recent IRS filing year, and the NTEE code that best describes the mission of the nonprofit. We define the following values:
- \(State_{user}\) = the U.S. state or territory the nonprofit is located in.
- \(LocationType_{user}\) = “metro” if the user’s information is located in a metropolitan area, “suburban” if the user’s information is located in a suburban area, “town” if the user’s information is located in a small town, and “rural.” if the user’s information is located in a rural area.
- \(TotalExpense_{user}\) = the total annual expense of the user’s nonprofit in the most recent IRS filing year
- \(NTEE_{user}\) = the NTEE code that best describes the mission of the user’s nonprofit
- Let \(OrgType_{user}\) , \(BroadCategroy_{user}\) , \(MajorGroup_{user}\), \(Divisoin_{user}\) , and \(Subdivision_{user}\) be the respective attributes of the user’s reference organization using the disaggregated NTEE code described in the NTEE Codes vignette.
Step 2: Choosing the Comparison Set
The comparison set of nonprofits is the set of all nonprofits that will be used to obtain an appraisal for the user’s organization. Of all available nonprofits, we only include those in the comparison set that can “reasonably” be compared to the user’s organization. How “reasonable” is defined will vary for each user as it depends on the job market of their potential CEO candidate. We allow the user to default to general constraints to create their comparison set, or define their own set of constraints for a more customizable search.
We first define the following sets:
- \(SearchOrganizationType \subseteq \{RG, AA, MT, PS, RP, MS, MM, NS\}\) be the set of all organization types that potential comparison organizations can have in order to be in the comparison set.
- \(SearchBroadCategory \subseteq \{ART, EDU, ENV, HEL, HMS, IFA, PSB, REL, MMB, UNU, UNI, HOS\}\) be the set of all broad categories that potential comparison organizations can have in order to be in the comparison set.
- \(SearchMajorGroup \subseteq \{A, B, C, ..., Z\}\) be the set of all major groups that potential comparison organizations can have in order to be in the comparison set.
- \(SearchDivision \subseteq \{ 0, 2, 3, ... , 9\}\) be the set of all divisions that potential comparison organizations can have in order to be in the comparison set. Note, due to the nested structures, divisions are only interpretable inside a major group. Thus, we suggest that you do not constrain the division if \(SearchMajorGroup\) has two or more elements.
- \(SearchSubDivision \subseteq \{ 0, 1, 2, ... , 9\}\) be the set of all subdivisions that potential comparison organizations can have in order to be in the comparison set. Note, due to the nested structures, subdivisions are only interpretable inside a division. Thus, we suggest that you do not constrain the division if \(SearchDivision\) has two or more elements.
- \(SearchState \subseteq \{AL, AK, AZ, ..., WY\}\) be the set of all U.S. states and territories that potential comparison organizations can be located in order to be in the comparison set.
- \(SearchLocationType \subseteq \{Rural,Town, Suburban, Metro\}\) be the set of all location types that potential comparison organizations can be located in order to be in the comparison set.
- \(SearchTotalExpense = [MinExpense, MaxExpense]\) be the range of total annual expenses that potential comparison organizations can have in order to be in the comparison set.
Let \(ComparisonSet\) be the set of all nonprofits where every attribute is in the search criteria.
There are two options for selecting the search criteria to define the comparison set.
Option 1 : Simple Search
For a simple search for we use the the following formulas based on their inputs in Step 1 to define search criteria:
- If \(OrgType_{user} = RG\) , then \(SearchOrganizationType = \{RG\}\), else \(SearchOrganizationType = \{ AA, MT, PS, RP, MS, MM, NS\}\).
- If \(OrgType_{user} =RG\), then \(SearchBroadCategory = \{BroadCategory_{user}\}\) , else \(SearchBroadCategory = \{ART, EDU, ENV, HEL, HMS, IFA, PSB, REL, MMB, UNU, UNI, HOS\}\)
- If \(OrgType_{user} =RG\), then \(SearchMajorGroup\) is every major group inside \(BroadCategory_{user}\) using the list on the NTEE Codes Vignette, else, \(SearchMajorGroup = \{A, ..., Z\}\).
- \(SearchDivision = \{ 0, 2, 3, ... , 9\}\)
- \(SearchSubDivision = \{ 0, 1, 2, 3, ... , 9\}\)
- \(SearchState = \{AL, AK, AZ, ..., WY\}\)
- \(SearchLocationType = \{LocationTypeuser\}\)
- \(SearchTotalExpense = [0.1*TotalExpense_{user} , 10 * TotalExpense_{user} ]\)
Option 2: Detailed Search
For an advanced search we allow the user to define all of their search criteria sets as they see fit.
We do have a few suggestions to follow. First, you should check the size of your comparison set. There should be enough organizations in it to provide you a reasonable range estimate at the end of Step 3. We recommend you have at least 10 organizations in the comparison set. If you define a criteria and the comparison set is small, we recommend you broaden your criteria to make the comparison set larger.
DO NOT look at the CEO compensations of the organizations in your comparison set before you calculate the appraisal. Looking at the CEO compensations of the organizations in your comparison set is a form of data snooping. If we look at the CEO compensations before we generate an appraisal, as humans we are likely to inject our bias into the process and include only the nonprofits with compensations we find favorable and exclude those compensations we personally do not like.
Step 3: Obtaining a Suggested Compensation Range
Step 3.1: Distance Calculations
Upon the completion of Step 2, there will be \(N\) organization in \(ComparisonSet\). We label them Organization 1, Organization 2, … , Organization \(N\), indexed by \(n\). For \(n\) in 1 to \(N\), let \(TotalDist_n\) be the distance between Organization \(n\) in \(ComparisonSet\) and the user’s reference nonprofit according to the calculations outlined in the Distance Calculations Vignette.
Optional Step 3.1.1
At this step, there is an option to refine the \(ComparisonSet\) if it is too large. In the case where the \(ComparisonSet\) has many organizations that are very far from the appraisal nonprofit and some organizations that are very close. In order to get an appraisal based on organizations that are the most similar to the original nonprofit, we can remove organizations with large distances from the \(ComparisonSet\). We only recommend doing this when \(ComparisonSet\) when is very large, usually more than a few hundard organizations.
Step 3.2: Point Value Compensation Estimate
We calculate a point value expected compensation by finding the weighted average of CEO salaries for all organizations in the comparison, using weights inversely proportional to the distance calculated in Step 3.1. The point value compensation estimate is calculated according to Algorithm 1.
Intuitively, the CEO compensation of organizations in the comparison set that have many similar attributes to the reference nonprofit should be prioritized when creating an appraisal. Additionally, we would like to utilize the CEO compensation information of organizations that are less similar to the reference nonprofit, but would like to down-weight this compensation information due to this dissimilarity to the reference nonprofit. Since \(TotalDistance_n\) is small when Organization \(n\) and the reference nonprofit have similar attributes, and is large when Organization \(n\) and the reference nonprofit do not have similar attributes, we create weights inversely proportional to the total distance.
Algorithm 1: Calculate Point Value CEO Compensation Estimate
For every Organization \(n\) in \(ComparisonSet\), let \(TotalDist_n\) be the total distance be the total distance between Organization \(n\) and the reference nonprofit. Additionally, let \(CeoCompensation_n\) be the CEO total compensation for Organization \(n\).
Let \(MinDist = \min \{TotalDist_n: n \in \{1, 2, ... ,N\} \}\) and \(MaxDist = \max \{TotalDist_n: n \in \{1, 2, ... ,N\} \}\).
Scale the distances between 0 and 1. For \(n\) in 1 to \(N\), define \(d_n = \frac{TotalDistance_n - MinDist}{MaxDist - MinDist}\)
Calculate the weights as \(w_n = \frac{1- d_n }{\sum_n(1 - d_n)}\).
The point value CEO compensation estimate is the weighted average of all \(CeoCompensation_n\):
\(PointEstimate = \sum_n w_n CeoCompensation_n\).
Step 3.3 Suggested Compensation Range
NEED TO EDIT THIS
Adjust for controls (predictors) Conversion to % and back (p_n to v_n) Omitting outliers (the inner 90% of the data)
Algorithm 2: Calculate Suggested Range
Let \(PointEstimate\) be the result of Algorithm 1.
Using all organizations in \(ComparisonSet\), estimate a linear regression model with \(CeoCompensation\) as the response, and \(\log_{10}(TotalExpense)\), \(\log_{10}(TotalAssests)\), \(\log_{10}(GrossReciepts)\), \(\log_{10}(TotalEmployee)\), \(FormYear\), \(BroadCategory\), \(State\), \(LoactionType\), and \(Gender\) as predictors.
Let \(\hat{CEO}_n\) be the predicted CEO Compensation from this regression model for each Organization \(n\), and \(e_n = CeoCompensation_n -\hat{CEO}_n\) be the corresponding residual.
Calculate the residual as a proportion of the observed value: \(p_n = \frac{e_n}{CeoCompensation_n}\).
Let \(v_n = PointValue * (1 + p_n)\) be transformation of \(p_n\) centered at \(PointEstimate\).
Let \(q_{0.05}\) and \(q_{0.95}\) be the \(5^{th}\) and \(95^{th}\) quantile of the \(v_n\)’s, respectively.
Then [\(q_{0.05}\) , \(q_{0.95}\) ] is the suggested CEO compensation range.
Example of Apprasial Process
Here we will walk through an example of the appraisal step-by-step
using the package functions. At the end of this section, we also provide
an example of how the wrapper function get_appraisal()
is
used.
Step-by-Step Example
Say Nonprofit X is a wildlife preservation nonprofit located in Elko County, Nevada with annual expenses of ~$1,575,000. Their board is trying to hire a new CEO and they want an appraisal for a reasonable total compensation for their CEO candidates.
Step 1
Using the NTEE Dendogram on the NTEE Codes Vignette, we know that
Nonprofit X has an NTEE code of D30. We then use the
ntee.crosswalk
data set to obtain their disaggregated NTEE
code values. Thus, their input values are,
- \(State_{user} = NV\)
-
\(LocationType_{user} =
rural\)
- \(TotalExpense_{user} = 1,575,000\)
-
\(NTEE_{user} = D30\)
- \(OrgType_{user} = RG\)
- \(BroadCategroy_{user} = ENV\)
- \(MajorGroup_{user} = D\)
- \(Divisoin_{user} = 3\)
- \(Subdivision_{user} = 0\)
After defining our user input values, we use the
get_org_values()
function to define a list of all the need
attributes about Nonprofit X:
NonprofitX <- get_org_values(
state = "NV",
location.type = "rural",
total.expense = 1575000,
ntee = "D30")
Step 2
The board believes the job market of their CEO candidates is other environment and animal related nonprofits located in non-metropolitan areas in Nevada, Utah, Idaho, and California. They use the advanced search criteria option to obtain their \(ComparisonSet\) criteria as:
- \(SearchOrganizationType = \{RG\}\)
- \(SearchBroadCategory = \{ENV\}\)
- \(SearchMajorGroup = \{C, D\}\)
- \(SearchDivision = \{ 0, 2, 3, ... , 9\}\)
- \(SearchSubDivision = \{ 0, 1, 2, 3, ... , 9\}\)
- \(SearchState = \{NV, UT, ID, CA\}\)
- \(SearchLocationType = \{\text{rural}, \text{town}, \text{suburban}\}\)
- \(SearchTotalExpense = [0 , \infty]\)
After defining the above criteria, we define our search criteria and
obtain our \(ComparisonSet\) using the
select_sample()
function. (Note, for demonstration
purposes, the code chuck below is not actually run and we fabricate a
small comparison set to walk-through the appraisal process. )
#define search criteria
search.criteria <-
list(
type.org = "RG",
broad.category = "ENV",
major.group = c("C", "D"),
division = NA,
subdivision = NA,
univ = FALSE,
hosp = FALSE,
location.type = c("rural", "town", "subruban"),
state = c("NV", "UT", "CA", "ID"),
total.expense = c(0, Inf)
)
#obtain comparison set
comparison.set <- select_sample(NonprofitX, search.criteria)
Then the resulting (fabricated) comparison set is the following:
Name | State | Location Type | NTEE Code | Annual Expense | CEO Compensation |
---|---|---|---|---|---|
Organization A | CA | suburban | C34 | 2400000 | 189000 |
Organization B | UT | town | D32 | 1600000 | 202000 |
Organization C | NV | town | D20 | 1800000 | 96000 |
Organization D | NV | suburban | C36 | 1400000 | 119000 |
Organization E | ID | rural | D50 | 4300000 | 421000 |
Step 3.1 Distance Calculations
Using the method outlined in the Distance Calculations Vignette, we
next calculate the mission, geographic, and size distances to find the
total distance between each of the five above organizations and
Nonprofit X. We use the get_mission_dist
and
get_geo_dist
functions. (Note, when you use the
select_sample()
function, the distances are automatically
calculated. We calculate them by hand here for demonstration
purposes.)
# Get weights
w <- get_weights()
# Initialize Storage
comparison.set$m.dist <- comparison.set$g.dist <-
comparison.set$s.dist <- comparison.set$total.dist <- 0
# Loop through all organizations an calculate the distance
for(i in 1:5){
#get values of Organization i
temp.org <- get_org_values(
state = comparison.set$state[i],
location.type = comparison.set$location.type[i],
total.expense = comparison.set$total.expense[i],
ntee = comparison.set$old.code[i]
)
#Calculate distances
comparison.set$m.dist[i] <- get_mission_dist(NonprofitX, temp.org, w$mission)
comparison.set$g.dist[i] <- get_geo_dist(NonprofitX, temp.org, w$geo)
comparison.set$s.dist[i] <-
log(
abs(NonprofitX$total.expense - comparison.set$total.expense[i]),
base = 10)
}
#find minimum values of each distance category
min.miss <- min(comparison.set$m.dist)
min.geo <- min(comparison.set$g.dist)
min.size <- min(comparison.set$s.dist)
#Center and scale total distance
comparison.set$total.dist <-
100/3*( (comparison.set$m.dist - min.miss) +
(comparison.set$g.dist - min.geo ) +
(comparison.set$s.dist - min.size) )
Name | Mission Distance | Geographic Distance | Size Distance | Total Distance |
---|---|---|---|---|
Organization A | 0.845 | 0.602 | 5.916 | 78.787 |
Organization B | 0.301 | 0.477 | 4.398 | 5.870 |
Organization C | 0.602 | 0.301 | 5.352 | 41.842 |
Organization D | 0.845 | 0.477 | 5.243 | 52.175 |
Organization E | 0.602 | 0.301 | 6.435 | 77.949 |
Step 3.2 Point Value Compensation Estimate
We next use Algorithm 1 to calculate the point value compensation estimate. We first need to calculate the corresponding weights, then use the weights to calculate a weighted average of the CEO compensations of the organizations in the comparison set.
# Get minimum and maximum distances for scaling and centering
min.dist <- min(comparison.set$total.dist)
max.dist <- max(comparison.set$total.dist)
# Scale and center total distance
comparison.set$d <- (comparison.set$total.dist - min.dist) / (max.dist - min.dist)
# Calculate Weights
comparison.set$weight <- (1 - comparison.set$d) / sum(1 - comparison.set$d)
Our \(d\) and \(weight\) values are as follows:
Name | Total Distance | d | weight |
---|---|---|---|
Organization A | 78.787 | 1.000 | 0.000 |
Organization B | 5.870 | 0.000 | 0.531 |
Organization C | 41.842 | 0.493 | 0.269 |
Organization D | 52.175 | 0.635 | 0.194 |
Organization E | 77.949 | 0.989 | 0.006 |
Finally, we calcuate the weighted average to obtain the point value estimate.
# Get point value estimate
suggested.salary <-sum(comparison.set$weight * comparison.set$ceo.compensation)
suggested.salary
## [1] 158731.6
The suggested point value estimate is $158,732.
Step 3.3 Suggested Compensation Range
We obtain the suggested CEO compensation range according to Algorithm 2. (Here we fabricate \(\hat{CEO}_n\) for demonstration purposes as running a regression model with 5 data points and 9 predictors would lead to nonsensical results. Thus \(e_n\) is also fabricated, but we ensured \(\sum_n e_n =0\) to align with properties of a regression model.)
#fabricate ceo-hat predicted values
comparison.set$ceo.hat <- c(170000, 209000, 140000, 132000, 376000)
##get residuals
comparison.set$e <- comparison.set$ceo.compensation - comparison.set$ceo.hat
sum(comparison.set$e) #residuals sum to 0
## [1] 0
# get residuals as percent
comparison.set$p <- comparison.set$e / comparison.set$ceo.compensation
# get percent of suggested salary
comparison.set$v <- suggested.salary * (1 + comparison.set$p)
Our \(e\), \(p\), and \(v\) values are as follows:
Name | CEO Compensation | Predicted CEO Compensation | e | p | v |
---|---|---|---|---|---|
Organization A | 189000 | 170000 | 19000 | 0.101 | 174688.80 |
Organization B | 202000 | 209000 | -7000 | -0.035 | 153231.05 |
Organization C | 96000 | 140000 | -44000 | -0.458 | 85979.64 |
Organization D | 119000 | 132000 | -13000 | -0.109 | 141391.21 |
Organization E | 421000 | 376000 | 45000 | 0.107 | 175698.21 |
Finally, we calculate the suggested compensatoin range.
## 5% 95%
## 97061.96 175496.33
The suggested range for CEO compensation for Nonprofit X is $97,062 to $175,496.
Using the wrapper funciton
In a non-fabricated example, you can use the
get_appraisal()
wrapper function to do these calculations
automatically.
NonprofitX <- get_org_values(
state = "NV",
location.type = "rural",
total.expense = 1575000,
ntee = "D30")
search.criteria <-
list(
type.org = "RG",
broad.category = "ENV",
major.group = c("C", "D"),
division = NA,
subdivision = NA,
univ = FALSE,
hosp = FALSE,
location.type = c("rural", "town", "subruban"),
state = c("NV", "UT", "CA", "ID"),
total.expense = c(0, Inf)
)
final.apprasial <- get_appraisal(NonprofitX, search.criteria)