6.1 Sobrevivência

Análise de sobrevivência serve para ajustar modelos com informações censuradas. A grande diferença desse tipo de modelo está na contribuição que uma observação tem na verossimilhança do modelo.

Quando temos informação pontual, a contribuição da observação \(i\) na verossimilhança é dada por

\[ f(t_i|\theta) \]

Quando temos informação censurada, só sabemos que \(x_i > t_i\), logo a contribuição é dada por

\[ P(X_i > t_i|\theta) = 1-F(t_i|\theta) = S(t_i|\theta) \]

Assim, a verossimilhança é dada por

\[ L(x|\theta) = \prod_{i=1}^n f(t_i|\theta)^{\delta_i} S(t_i|\theta)^{(1-\delta_i)} \]

em que \(\delta_i\) é um indicador de observação pontual (não-censurada).

O modelo mais conhecido de análise de sobrevivência é o Kaplan-Meier, um modelo que estima a curva de sobrevivência através da seguinte conta

\[ \hat{S}(t) = \prod_{i:t_i\leq t}\left(1-\frac{d_i}{n_i}\right) \]

onde \(d_i\) é o número de eventos ocorridos até o momento e \(n_i\) é o número de processos vivos no tempo do indivíduo \(i\). Essa conta leva a censura em conta de forma adequada e existem diversas razões teóricas para sua utilização.

6.1.1 Base de dados

A base de dados final desse projeto, após a realização de todos os filtros e sumarizações, além da análise da cifra oculta, está armazenada no objeto d_fcc (dados Fórum Central Cível).

library(tidyverse)
d_fcc <- readRDS("data/d_fcc.rds") %>% 
  mutate(censura = as.numeric(pmax(julgado, baixa, recurso, sentenca)),
         censura = if_else(censura > 0, 1, 0)) %>%
  mutate(t_deci_total = n_deci_e_desp * t_deci) %>% 
  filter(tipo != "RJ", tempo_total > 0, tempo_total < 1700)

glimpse(d_fcc)
#> Observations: 329,578
#> Variables: 28
#> $ n_processo    <chr> "0000014-24.2013.8.26.0003", "0000017-82.2013.8....
#> $ comarca       <chr> "Foro Central Cível", "Foro Central Cível", "For...
#> $ foro          <chr> "Foro Central Cível", "Foro Central Cível", "For...
#> $ vara          <chr> "26ª Vara Cível", "19ª Vara Cível", "2ª Vara Cív...
#> $ classe        <chr> "Alienação Judicial de Bens", "Procedimento Comu...
#> $ assunto       <chr> "Alienação Judicial", "Indenização por Dano Mora...
#> $ data_dist     <date> 2013-01-07, 2013-01-30, 2013-01-07, 2013-01-07,...
#> $ n_deci        <int> 3, 3, 0, 1, 5, 5, 4, 5, 2, 6, 6, 6, 2, 2, 0, 1, ...
#> $ n_desp        <int> 2, 0, 4, 5, 7, 0, 3, 3, 4, 2, 1, 2, 0, 4, 1, 2, ...
#> $ n_mov         <int> 36, 24, 26, 36, 54, 48, 59, 73, 55, 82, 25, 43, ...
#> $ tempo_total   <dbl> 319, 439, 823, 1303, 1323, 1244, 634, 1311, 1304...
#> $ julgado       <int> 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, ...
#> $ baixa         <int> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, ...
#> $ recurso       <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, ...
#> $ sentenca      <int> 2, 1, 1, 2, 2, 1, 1, 0, 1, 2, 0, 2, 0, 1, 3, 2, ...
#> $ prim_mov      <date> 2013-01-07, 2013-01-30, 2013-01-07, 2013-01-07,...
#> $ ult_mov       <date> 2013-11-22, 2014-04-14, 2015-04-10, 2016-08-02,...
#> $ data_julgado  <date> NA, NA, 2015-04-10, NA, NA, 2013-12-12, NA, NA,...
#> $ data_baixa    <date> 2013-11-21, 2014-04-14, 2015-04-10, NA, NA, NA,...
#> $ data_recurso  <date> NA, NA, NA, NA, 2016-05-10, NA, NA, NA, NA, NA,...
#> $ data_sentenca <date> 2013-09-26, 2014-01-17, 2013-10-14, 2013-06-21,...
#> $ n_deci_e_desp <int> 5, 3, 4, 6, 11, 5, 7, 7, 6, 8, 7, 8, 2, 6, 1, 3,...
#> $ t_deci        <dbl> 10.200000, 23.333333, 80.250000, 8.000000, 25.54...
#> $ n_deci_n_nula <dbl> 4, 3, 4, 6, 11, 5, 7, 7, 3, 4, 7, 6, 1, 5, 1, 2,...
#> $ p             <dbl> 0.00000000, 0.00000000, 0.00000000, 0.00000000, ...
#> $ tipo          <chr> "Comum", "Comum", "Comum", "Comum", "Comum", "Em...
#> $ censura       <dbl> 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, ...
#> $ t_deci_total  <dbl> 51, 70, 321, 48, 281, 187, 105, 166, 16, 6, 332,...

6.1.2 Ajustando de modelos no R

O pacote utilizado para ajuste de modelos

  • Surv() serve para criar a variável resposta do modelo considerando as duas variáveis que a compõem: tempo e indicador de não-censura
  • survfit() ajusta o kaplan-meier (ou outros modelos) para uma fórmula com Surv() do lado esquerdo do ~ e outras covariáveis do lado direito.
library(survival)

Modelando o tempo total do processo. A função broom::tidy() mostra os principais achados do modelo numa base de dados arrumada, para ser posteriormente utilizada.

modelo_tempo_total <- d_fcc %>%
   with(survfit(Surv(tempo_total, censura) ~ tipo)) 

modelo_tempo_total %>% 
   broom::tidy()

Modelando o tempo de decisão

modelo_tempo_decisao <- d_fcc %>%
   with(survfit(Surv(t_deci_total, censura) ~ tipo)) 

modelo_tempo_decisao %>% 
   broom::tidy()

O pacote broom existe para diversos modelos e ajuda bastante a trabalhar com os resultados de ajustes. Dê uma olhada em https://github.com/tidyverse/broom para detalhes.

6.1.3 Curvas de sobrevivência

Atualmente, o melhor pacote para fazer curvas de sobrevivência é o survminer. Basta rodar a função ggsurvplot:

survminer::ggsurvplot(modelo_tempo_total, risk.table = TRUE, data = d_fcc)

survminer::ggsurvplot(modelo_tempo_decisao, risk.table = TRUE, data = d_fcc)

Dá para observar que processos empresariais são mais lentos, mas não dá pra ver quase nada nesses gráficos. Por isso comparamos as curvas utilizando uma estatística das ruas.

6.1.4 Comparação das curvas

plota_grafico_dificuldade <- function(broom_model) {
  # empresarial
  d_e <- broom_model %>% 
    filter(strata == "tipo=Empresarial")
  
  # comum
  d_c <- broom_model %>% 
    filter(strata == "tipo=Comum")
  
  # fuzzyjoin das duas curvas
  fuzzyjoin::difference_inner_join(d_e, d_c, 'estimate', max_dist = 0.01) %>%
  mutate(razao = time.x/time.y,
         dificuldade = as.factor(cut(1-estimate.x, breaks = 10, labels = FALSE,
                                     include.lowest = TRUE))) %>%
  group_by(dificuldade) %>%
  summarise(razao = mean(razao)) %>%
  ggplot(aes(x = as.numeric(dificuldade), y = razao)) +
  geom_col(fill = 'royalblue') + 
  theme_minimal(17)
}

Tempo total:

modelo_tempo_total %>% 
  broom::tidy() %>% 
  plota_grafico_dificuldade() +
  geom_hline(yintercept = 1, linetype = 1) +
  scale_y_continuous(limits = c(0, 1.5), labels = scales::percent) +
  labs(x = "Dificuldade do caso", y = "Razão entre os tempos medianos") +
  ggtitle("Razão dos tempo total versus dificuldade")

Tempo da decisão:

modelo_tempo_decisao %>% 
  broom::tidy() %>% 
  plota_grafico_dificuldade() +
  geom_hline(yintercept = 1, linetype = 1) +
  geom_hline(yintercept = 2, linetype = 2) +
  labs(x = "Dificuldade do caso", y = "Razão entre os tempos medianos") +
  ggtitle("Razão dos tempo de decisão versus dificuldade") +
  scale_y_continuous(labels = scales::percent)

6.1.5 Resultados

Como resultados dessa análise, concluímos que

  • Processos empresariais de fato são mais complexos que processos cíveis.
  • A diferença é menor em processos de alta complexidade.
  • A diferença também é maior quando consideramos somente o tempo de decisões e não o tempo total.