library(haven)       
library(tidyverse)   
library(knitr)       
library(kableExtra)  

file_path <- "C:\\Users\\JH\\Kitces.com\\DV - Research\\Anonymized Data and Codebooks - All Projects\\Productivity Studies\\2024\\fp24.dta"

df <- read_dta(file_path)

# define advice only 
advice_only <- df %>% 
  filter(grpadvice == 1)

med_rev <- median(advice_only$rvxmbr, na.rm = TRUE)

processed_data <- advice_only %>%
  filter(!is.na(rvxmbr)) %>%
  mutate(
    adv_seg = if_else(rvxmbr <= med_rev, "Below Median Revenue", "Above Median Revenue"),
    
    total_weekly_hrs = rowSums(across(c(
      hrsprospect, hrsmarket, hrsprep, hrscurrentcl, hrsfinplan, 
      hrsinvestres, hrsinvestmgt, hrsclserv, hrsadmin, hrsmgmt, 
      hrscompliance, hrsproffdev, hrsoth
    )), na.rm = TRUE),
    
    total_weekly_hrs = if_else(is.na(hrscurrentcl) & is.na(hrsfinplan), NA_real_, total_weekly_hrs),
    
    pct_current_cl = (hrscurrentcl / total_weekly_hrs) * 100,
    pct_current_cl = if_else(is.infinite(pct_current_cl) | is.nan(pct_current_cl), NA_real_, pct_current_cl),
    
    pct_fin_plan = (hrsfinplan / total_weekly_hrs) * 100,
    pct_fin_plan = if_else(is.infinite(pct_fin_plan) | is.nan(pct_fin_plan), NA_real_, pct_fin_plan)
  ) %>%
  mutate(
    missing_components = rowSums(across(c(
      pcvrretire, pcvrinvest, pcvrtxplan, pcvrlifeins, pcvrsave, pcvrcash, 
      pcvrestate, pcvrcollege, pcvr401k, pcvrltc, pcvrdisability, pcvroptions, 
      pcvrbenefits, pcvrcredit, pcvrproperty, pcvrhealth, pcvrstudent, pcvrbiz, 
      pcvrtxprep, pcvrcareer, pcvrestatedoc, pcvrheld401k, pcvrcharity, pcvrss, 
      pcvrmedicare, pcvrlifepl, pcvrrealestate, pcvroth
    ), is.na)),
    
    total_components = rowSums(across(c(
      pcvrretire, pcvrinvest, pcvrtxplan, pcvrlifeins, pcvrsave, pcvrcash, 
      pcvrestate, pcvrcollege, pcvr401k, pcvrltc, pcvrdisability, pcvroptions, 
      pcvrbenefits, pcvrcredit, pcvrproperty, pcvrhealth, pcvrstudent, pcvrbiz, 
      pcvrtxprep, pcvrcareer, pcvrestatedoc, pcvrheld401k, pcvrcharity, pcvrss, 
      pcvrmedicare, pcvrlifepl, pcvrrealestate, pcvroth
    )), na.rm = TRUE),
    
    total_components = if_else(missing_components == 28, NA_real_, total_components)
  )

 
#  SUMMARY STATISTICS  
 summary_metrics <- processed_data %>%
  group_by(adv_seg) %>%
  summarise(
    meet_pct     = median(pct_current_cl, na.rm = TRUE),
    plan_pct     = median(pct_fin_plan, na.rm = TRUE),
    comp_med     = median(total_components, na.rm = TRUE),
    team_tot     = mean(ftetot, na.rm = TRUE),
    role_senior  = mean(haslead == 1, na.rm = TRUE) * 100,
    role_service = mean(hassrv == 1, na.rm = TRUE) * 100,
    role_assoc   = mean(hasass == 1, na.rm = TRUE) * 100,
    role_para    = mean(haspara == 1, na.rm = TRUE) * 100,
    role_admin   = mean(hascsa == 1, na.rm = TRUE) * 100
  )

 #  MATRIX RESHAPING & LABELS
final_table_df <- summary_metrics %>%
  pivot_longer(
    cols = -adv_seg,
    names_to = "Metric",
    values_to = "Value"
  ) %>%
  pivot_wider(
    names_from = adv_seg,
    values_from = Value
  ) %>%
  mutate(
    Row_Order = case_when(
      Metric == "meet_pct"     ~ 1,
      Metric == "plan_pct"     ~ 2,
      Metric == "comp_med"     ~ 3,
      Metric == "team_tot"     ~ 4,
      Metric == "role_senior"  ~ 6, 
      Metric == "role_service" ~ 7,
      Metric == "role_assoc"   ~ 8,
      Metric == "role_para"    ~ 9,
      Metric == "role_admin"   ~ 10
    )
  ) %>%
  mutate(
    `Below Median Revenue` = case_when(
      Metric %in% c("meet_pct", "plan_pct", "role_senior", "role_service", "role_assoc", "role_para", "role_admin") 
        ~ sprintf("%.0f%%", round(`Below Median Revenue`)),
      Metric %in% c("comp_med", "team_tot") 
        ~ sprintf("%.0f", round(`Below Median Revenue`)),
      TRUE ~ as.character(`Below Median Revenue`)
    ),
    `Above Median Revenue` = case_when(
      Metric %in% c("meet_pct", "plan_pct", "role_senior", "role_service", "role_assoc", "role_para", "role_admin") 
        ~ sprintf("%.0f%%", round(`Above Median Revenue`)),
      Metric %in% c("comp_med", "team_tot") 
        ~ sprintf("%.0f", round(`Above Median Revenue`)),
      TRUE ~ as.character(`Above Median Revenue`)
    ),
    Metric = case_when(
      Metric == "meet_pct"     ~ "% Of Weekly Hours Spent On Meeting With Current Clients",
      Metric == "plan_pct"     ~ "% Of Weekly Hours Spent On Financial Plan Preparation",
      Metric == "comp_med"     ~ "Median Components Included In Financial Plans",
      Metric == "team_tot"     ~ "Mean Total Service Team Members (FTE)",
      Metric == "role_senior"  ~ "Senior Advisors",
      Metric == "role_service" ~ "Service Advisors",
      Metric == "role_assoc"   ~ "Associate Advisors",
      Metric == "role_para"    ~ "Paraplanners",
      Metric == "role_admin"   ~ "Admin / CSA"
    )
  ) %>%
  add_row(
    Metric = "% Of Teams With This Role Present", 
    `Below Median Revenue` = "", 
    `Above Median Revenue` = "", 
    Row_Order = 5
  ) %>%
  arrange(Row_Order) %>%
  select(Metric, `Below Median Revenue`, `Above Median Revenue`)

  
#  TABLE  
kable(
  final_table_df, 
  align = c("l", "c", "c"),
  col.names = c("Metric", "Below Median Revenue", "Above Median Revenue")
) %>%
   kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"), 
    full_width = FALSE,
    position = "left"
  ) %>%
   row_spec(
    0, 
    bold = TRUE, 
    color = "white", 
    background = "#1B365D"
  ) %>%
 
  row_spec(
    5, 
    bold =  FALSE,
    color = "#000000", 
    background = "#E8EEF5"
  ) %>%
    add_indent(c(6, 7, 8, 9, 10))
Metric Below Median Revenue Above Median Revenue
% Of Weekly Hours Spent On Meeting With Current Clients 11% 20%
% Of Weekly Hours Spent On Financial Plan Preparation 18% 17%
Median Components Included In Financial Plans 14 18
Mean Total Service Team Members (FTE) 1 3
% Of Teams With This Role Present
Senior Advisors 100% 100%
Service Advisors 0% 29%
Associate Advisors 0% 14%
Paraplanners 7% 14%
Admin / CSA 7% 21%