Probit e Logit

Introduzione

Questo documento descrive l’analisi del dataset Hmda, che contiene dati relativi alle domande di mutuo e le relative approvazioni o rifiuti.

Caricamento del Dataset

Per iniziare, carichiamo il dataset utilizzando il pacchetto Ecdat e esaminiamo le prime righe dei dati.

library(Ecdat)
library(dplyr)
library(fixest)
data(Hmda)
head(Hmda)
    dir   hir       lvr ccs mcs pbcr dmi self single uria condominium black
1 0.221 0.221 0.8000000   5   2   no  no   no     no  3.9           0    no
2 0.265 0.265 0.9218750   2   2   no  no   no    yes  3.2           0    no
3 0.372 0.248 0.9203980   1   2   no  no   no     no  3.2           0    no
4 0.320 0.250 0.8604651   1   2   no  no   no     no  4.3           0    no
5 0.360 0.350 0.6000000   1   1   no  no   no     no  3.2           0    no
6 0.240 0.170 0.5105263   1   1   no  no   no     no  3.9           0    no
  deny
1   no
2   no
3   no
4   no
5   no
6   no

Il dataset Hmda contiene 2381 osservazioni e 13 variabili. Le variabili sono descritte nella ?@tbl-descr.

Variabile Descrizione
dir Rapporto tra i pagamenti del debito e il reddito totale. Indica quanto del reddito totale viene destinato al pagamento dei debiti.
hir Rapporto tra le spese abitative e il reddito. Misura la percentuale del reddito spesa per le abitazioni.
lvr Rapporto tra l’importo del prestito e il valore stimato della proprietà. Indica quanta parte del valore della proprietà è finanziata tramite prestito.
ccs Punteggio di credito al consumo, da 1 a 6, dove un valore basso rappresenta un buon punteggio.
mcs Punteggio di credito ipotecario, da 1 a 4, dove un valore basso indica un buon punteggio di credito.
pbcr Presenza di cattivi precedenti creditizi pubblici. Variabile binaria (si/no) che indica se esistono precedenti negativi.
dmi Richiesta di assicurazione sul mutuo negata. Variabile binaria (si/no) che indica se è stata negata l’assicurazione sul mutuo.
self Se l’individuo è un lavoratore autonomo. Variabile binaria (si/no).
single Se l’applicante è single. Variabile binaria (si/no) che indica lo stato civile.
uria Tasso di disoccupazione del 1989 nel Massachusetts, nel settore di impiego dell’applicante. Fornisce contesto economico.
condominium Se l’unità abitativa è un condominio (=1). Variabile binaria (1/0) che descrive il tipo di proprietà abitativa.
black Se l’applicante è di etnia afroamericana. Variabile binaria (si/no), usata in analisi di discriminazione razziale.
deny Se la domanda di mutuo è stata negata. Variabile binaria (si/no) che indica l’esito della richiesta di mutuo.

Statistiche Descrittive

Il dataset contiene un’osservazione con alcuni dati mancanti (NA). Questa osservazione può essere eliminata mediante na.omit. Questa funzione restituisce un data.frame con le osservazioni complete, cioè tutte le osservazioni per cui tutte le varabile sono non NA.

Hmda <- na.omit(Hmda)

Il pacchetto gtsummary contiene delle funzioni molto utili per calcolare le statistiche descrittive delle variabili presenti in un data.frame.

library(gtsummary)
library(dplyr)
Hmda <- Hmda |> select(deny, everything())
Hmda |>
  tbl_summary(
    by = black,
    statistic = list(
      all_continuous() ~ "{mean} ({sd})",
      all_categorical() ~ "{n} ({p}%)"
    ),
    digits = all_continuous() ~ 2,
    label = deny ~ "Mutuo Concesso (deny)",
    include = names(Hmda)
  ) |> 
  add_overall() |>
   modify_spanning_header(c("stat_1", "stat_2") ~ "**Black**") 
Characteristic Overall, N = 2,3801 Black
no, N = 2,0411 yes, N = 3391
Mutuo Concesso (deny) 285 (12%) 189 (9.3%) 96 (28%)
dir 0.33 (0.11) 0.33 (0.11) 0.35 (0.09)
hir 0.26 (0.10) 0.25 (0.10) 0.27 (0.08)
lvr 0.74 (0.18) 0.73 (0.18) 0.81 (0.16)
ccs


    1 1,353 (57%) 1,226 (60%) 127 (37%)
    2 441 (19%) 390 (19%) 51 (15%)
    3 126 (5.3%) 99 (4.9%) 27 (8.0%)
    4 77 (3.2%) 53 (2.6%) 24 (7.1%)
    5 182 (7.6%) 140 (6.9%) 42 (12%)
    6 201 (8.4%) 133 (6.5%) 68 (20%)
mcs


    1 747 (31%) 697 (34%) 50 (15%)
    2 1,571 (66%) 1,288 (63%) 283 (83%)
    3 41 (1.7%) 38 (1.9%) 3 (0.9%)
    4 21 (0.9%) 18 (0.9%) 3 (0.9%)
pbcr 175 (7.4%) 115 (5.6%) 60 (18%)
dmi 48 (2.0%) 31 (1.5%) 17 (5.0%)
self 277 (12%) 252 (12%) 25 (7.4%)
single 936 (39%) 761 (37%) 175 (52%)
uria 3.77 (2.03) 3.83 (2.10) 3.45 (1.50)
condominium 686 (29%) 519 (25%) 167 (49%)
1 n (%); Mean (SD)

Categorizzazione del rapporto loan-to-value

Classifichiamo il rapporto loan-to-value (lvr) in categorie basse, medie e alte per analisi future.

Hmda <- Hmda |> 
  mutate(lvra = case_when(
    lvr < 0.8 ~ "low",
    lvr > 0.95 ~ "high",
    TRUE ~ "medium"
  ))

Creiamo la variable dummy denied che prende il valore 1 quando deny=="yes" and il valore 0 quando deny=="no".

Hmda <- Hmda |>
  mutate(denied = case_when(
    deny == "yes" ~ 1,
    deny == "no" ~ 0
  ))

Modello di Probabilità Lineare

Utilizziamo un modello di regressione lineare per stimare la probabilità di rifiuto del mutuo.

library(fixest)
lpm_HMDA <-
  feols(denied ~ black + dir + hir + lvra + ccs + mcs + pbcr + dmi 
        + self + uria + condominium,
    data = Hmda
  )
lpm_HMDA
OLS estimation, Dep. Var.: denied
Observations: 2,380 
Standard-errors: IID 
             Estimate Std. Error   t value   Pr(>|t|)    
(Intercept) -0.010389   0.044382 -0.234072 8.1495e-01    
blackyes     0.084833   0.017443  4.863364 1.2298e-06 ***
dir          0.444625   0.086863  5.118693 3.3242e-07 ***
hir         -0.046887   0.096121 -0.487795 6.2574e-01    
lvralow     -0.188589   0.033249 -5.672020 1.5832e-08 ***
lvramedium  -0.157255   0.033323 -4.719096 2.5070e-06 ***
ccs          0.030792   0.003684  8.357460  < 2.2e-16 ***
mcs          0.019743   0.011090  1.780232 7.5166e-02 .  
pbcryes      0.196684   0.023159  8.492874  < 2.2e-16 ***
dmiyes       0.701116   0.041172 17.028780  < 2.2e-16 ***
selfyes      0.055638   0.018169  3.062313 2.2210e-03 ** 
uria         0.004864   0.002872  1.693364 9.0518e-02 .  
condominium  0.003865   0.012980  0.297765 7.6591e-01    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 0.277932   Adj. R2: 0.263457

Il coefficient sulla variable blackyes (la dummy automaticamente creata da R che prende il valore 1 se black=="yes") è 0.085. L’interpretazione di questo coefficiente è che una persona di coloro a parità di altre caratteristiche ha una probabilità di avere il mutuo concesso più bassa di 0.085.

Per avere un’idea di quanto sia grande questa differenza, possiamo calcolare la variazione relative della probabilità: \[ \frac{\Pr(black=1|X) - \Pr(black=0|X)}{\Pr(black=0)} = \frac{0.085}{0.093} \approx 0.91 (91\%) \] In altre parole, se rapportata alla probabilità (non condizionata) che hanno le persone non di colore di ottenere il mutuo (9.3%), le persone di colore hanno una probabilita’ piu bassa di ottenere il mutuo di circa il 90%.

Modello Logit e Probit

logit_HMDA <-
  feglm(
    denied ~ black + dir + hir + lvra + ccs + mcs + pbcr +
      dmi + self + uria + condominium,
    data = Hmda,
    family = binomial("logit")
  )
probit_HMDA <-
  feglm(
    denied ~ black + dir + hir + lvra + ccs + mcs + pbcr +
      dmi + self + uria + condominium,
    data = Hmda,
    family = binomial("probit")
  )

Confrontiamo i tre diversi modelli:

Mentre il coefficiente del modello lineare per la probabilità si presta immediatamente ad una interpretazione, i coefficienti del modello logit e probit ci danno esclusiavamente delle informazioni riguardo al segno della relazione fra la probabilità e le rispettive variabili. Per ottenere un’interpretazione bisogna procedere calcolando le predizioni.

Predizioni

Il modo più semplice per ottenere una stima della differenza nella probabilita’ che il mutuo venga accettto per le persone di colore e quelle non di colore e’ procedere a calcolare le predizioni a dei valori prespecificati delle \(X\):

Per il modello probit: \[ \begin{aligned} \underset{\text{probabilità diniego mutuo per black}}{\underbrace{\Phi\left(\hat{\beta}_{0}+\hat{\beta}_{1}+\hat{\beta}_{2}\bar{dir}+\hat{\beta}_{3}\bar{hir}+\hat{\beta}_{6}\bar{ccs}+\hat{\beta}_{7}\bar{mcs}+\hat{\beta}_{11}\bar{uria}\right)}}\\-\underset{\text{probabilità diniego mutuo per non-black}}{\underbrace{\Phi\left(\hat{\beta}_{0}+\hat{\beta}_{2}\bar{dir}+\hat{\beta}_{3}\bar{hir}+\hat{\beta}_{6}\bar{ccs}+\hat{\beta}_{7}\bar{mcs}+\hat{\beta}_{11}\bar{uria}\right)}} \end{aligned} \] e per il modello logit \[ \begin{aligned} \underset{\text{probabilità diniego mutuo per black}}{\underbrace{F\left(\hat{\beta}_{0}+\hat{\beta}_{1}+\hat{\beta}_{2}\bar{dir}+\hat{\beta}_{3}\bar{hir}+\hat{\beta}_{6}\bar{ccs}+\hat{\beta}_{7}\bar{mcs}+\hat{\beta}_{11}\bar{uria}\right)}}\\-\underset{\text{probabilità diniego mutuo per non-black}}{\underbrace{F\left(\hat{\beta}_{0}+\hat{\beta}_{2}\bar{dir}+\hat{\beta}_{3}\bar{hir}+\hat{\beta}_{6}\bar{ccs}+\hat{\beta}_{7}\bar{mcs}+\hat{\beta}_{11}\bar{uria}\right)}}, \end{aligned} \] dove \(F(\cdot)\) è la funzione di ripartizaione della distribuzione logistica.

Per ottenere le predizioni è necessario creare un data.frame contenente i valori per le \(X\):

new <- data.frame(
  "dir" = mean(Hmda$dir),
  "hir" = mean(Hmda$hir),
  "lvra" = "low",
  "ccs" = mean(Hmda$ccs),
  "mcs" = mean(Hmda$mcs),
  "pbcr" = "no",
  "dmi" = "no",
  "self" = "no",
  "black" = c("no", "yes"),
  "uria" = mean(Hmda$uria),
  "condominium" = 0
)

Possiamo ottenere le predizioni per i due modelli usando la funzione predict:

logit_pred <- predict(logit_HMDA, newdata = new)
probit_pred <- predict(probit_HMDA, newdata = new)

logit_pred e probit_pred sono due vettori che hanno come prime elemento la stima della probabilità per black and come secondo la stima della probabilità per non-black (condizionatamente ai valori specificati in new per le altre variabili). La differenza di questi due valori è la stima della differenza della probabilita’.

delta_logit = diff(logit_pred)
delta_logit
[1] 0.04204562
delta_probit = diff(probit_pred)
delta_probit
[1] 0.05186245

Lo stesso risultato puo’ essere ottenuto usando marginaleffects

library(marginaleffects)

avg_slopes(logit_HMDA, newdata = "mean", variables = "black")

  Term Contrast Estimate Std. Error   z Pr(>|z|)   S  2.5 % 97.5 %
 black yes - no    0.042     0.0145 2.9  0.00375 8.1 0.0136 0.0705

Columns: rowid, term, contrast, estimate, std.error, statistic, p.value, s.value, conf.low, conf.high, predicted_lo, predicted_hi, predicted 
Type:  response 
avg_slopes(probit_HMDA, newdata = "mean", variables = "black")

  Term Contrast Estimate Std. Error    z Pr(>|z|)   S  2.5 % 97.5 %
 black yes - no   0.0519      0.017 3.06  0.00222 8.8 0.0186 0.0851

Columns: rowid, term, contrast, estimate, std.error, statistic, p.value, s.value, conf.low, conf.high, predicted_lo, predicted_hi, predicted 
Type:  response 

Alternativamente, possiamo calcolare la media delle probabilità

Hmda_tmp <- Hmda
Hmda_tmp$black <- "yes"
proba_black <- predict(logit_HMDA, newdata = Hmda_tmp)
Hmda_tmp$black <- "no"
proba_nonblack <- predict(logit_HMDA, newdata = Hmda_tmp)

mean(proba_black - proba_nonblack)
[1] 0.06281968

Questa stima e’ equivalente a quella ottenuta con marginaleffects

avg_slopes(logit_HMDA, variables = "black")

  Term Contrast Estimate Std. Error    z Pr(>|z|)    S  2.5 % 97.5 %
 black yes - no   0.0628     0.0184 3.41   <0.001 10.6 0.0267 0.0989

Columns: term, contrast, estimate, std.error, statistic, p.value, s.value, conf.low, conf.high 
Type:  response 

I vantaggi di utilizzare marginaleffects rispetto a procedere ai calcoli manuali sono che 1) otteniamo anche gli errori standard per l’effetto e 2) marinaleffects calcola gli effetti per tutte le variabili del modello:

avg_slopes(logit_HMDA)

        Term      Contrast Estimate Std. Error       z Pr(>|z|)    S     2.5 %
 black       yes - no       0.06282    0.01841  3.4131  < 0.001 10.6  0.026745
 ccs         dY/dX          0.02195    0.00299  7.3335  < 0.001 42.0  0.016084
 condominium 1 - 0          0.00251    0.01262  0.1989  0.84235  0.2 -0.022227
 dir         dY/dX          0.35585    0.07822  4.5495  < 0.001 17.5  0.202548
 dmi         yes - no       0.73198    0.06885 10.6314  < 0.001 85.3  0.597038
 hir         dY/dX         -0.00628    0.09347 -0.0672  0.94640  0.1 -0.189488
 lvra        low - high    -0.15213    0.04388 -3.4667  < 0.001 10.9 -0.238139
 lvra        medium - high -0.11724    0.04381 -2.6763  0.00744  7.1 -0.203099
 mcs         dY/dX          0.01947    0.01057  1.8415  0.06555  3.9 -0.001252
 pbcr        yes - no       0.12664    0.02810  4.5064  < 0.001 17.2  0.071563
 self        yes - no       0.05348    0.02085  2.5651  0.01031  6.6  0.012618
 uria        dY/dX          0.00474    0.00257  1.8457  0.06493  3.9 -0.000293
   97.5 %
  0.09889
  0.02782
  0.02725
  0.50915
  0.86693
  0.17692
 -0.06612
 -0.03138
  0.04019
  0.18172
  0.09435
  0.00977

Columns: term, contrast, estimate, std.error, statistic, p.value, s.value, conf.low, conf.high 
Type:  response 

Queste stime sono stime medie. Possiamo anche visualizzare le stime usilizzando le \(X\) sdi ciascun individuo nel nostro campione e poi visualizzare le differenze.

a <- slopes(logit_HMDA)
b <- slopes(logit_HMDA, newdata = "mean")
library(ggplot2)
ggplot(a, aes(x=estimate)) + 
  geom_histogram(bins = 60) + 
  geom_vline(data=b, aes(xintercept = estimate), color = "darkred") + 
  facet_wrap(contrast~term, scales= "free") + 
  theme_minimal()