Motivação de desligamento: o que o motivo declarado esconde
Caso fictício. A Cestária Supermercados, suas lojas, pessoas e entrevistas não existem. Os dados foram gerados do zero por um script em R, com padrões de tamanho conhecido. O método é real.
Baixar o relatório (PDF) · Baixar as prioridades por gerência (CSV)
A pergunta
A Cestária é uma rede de supermercados do interior de Minas Gerais, com 8 lojas, um centro de distribuição e um escritório central, e cerca de 1.790 pessoas no quadro. Em 2024 e 2025, 1.453 pessoas saíram da empresa.
A taxa de desligamento ficou parada: em média, 3,31% do quadro saiu a cada mês em 2024 e 3,45% em 2025, uma diferença compatível com o acaso (p = 0,45). A composição, porém, mudou. As saídas voluntárias subiram de 1,98% para 2,35% ao mês, e as dispensas caíram quase na mesma medida.
Com o total estável, a rotatividade não parecia ser assunto. A diretoria fez outras duas perguntas: por que as pessoas pedem para sair, e onde agir primeiro? Para responder, a entrevista de desligamento, que a empresa já fazia e ninguém lia junto com o resto, foi cruzada com o quadro mês a mês e com os desligamentos.
O que os dados mostram
- O motivo declarado esconde o motivo real. “Salário e benefícios” é o motivo mais citado por quem pede para sair (25,6%). Entre quem deu nota 1 ou 2 ao gestor, porém, “liderança e gestor” passa à frente, com 44,5% contra 20,9%.
- As saídas nos primeiros 90 dias cresceram em duas gerências. No CD Expedição, a parte dos admitidos que saiu por vontade própria até 90 dias foi de 20% em 2024 para 39% em 2025; na L3 Operações, de 20% para 41%. Nas demais gerências, o número ficou perto de 17%.
- A L5 Vendas passou a perder mais gente depois da troca de gestor, em julho de 2025, e “liderança e gestor” virou o motivo de 71% das saídas respondidas dali em diante.
- A escala 6x1 no turno da noite concentra “jornada e escala”, motivo de 40% das saídas nesse grupo, contra 8% no resto.
- A idade não explica as saídas. Os mais jovens saem mais, mas só porque são mais novos de casa; com o tempo de casa no modelo, a diferença some.
- A entrevista tem viés de resposta, mais forte nas saídas involuntárias e na L7, mas corrigir esse viés não muda a ordem dos motivos.
O que o motivo declarado esconde
Quem pede para sair (pedido de demissão ou acordo) responde, na entrevista, um motivo principal e, se quiser, um secundário, numa lista fechada de oito. Foram 712 respostas com motivo nos dois anos.
No geral, “salário e benefícios” lidera, com 25,6% das respostas (IC 95% de 22,5% a 28,9%), e “liderança e gestor” aparece com 16,0%. O retrato muda entre as 182 pessoas que deram nota 1 ou 2 ao gestor: “liderança e gestor” passa a 44,5% (de 37,5% a 51,8%), e salário cai para 20,9%.
O salário também esconde a liderança quando aparece junto com a nota baixa. Das 38 pessoas que deram nota 1 ou 2 ao gestor e declararam salário como motivo principal, 22 (58%) puseram “liderança e gestor” como motivo secundário. Somando principal e secundário, 73% de quem deu nota baixa ao gestor fala da liderança, contra 15% entre os demais.
Isso não prova que o gestor causou a saída. Mostra que o motivo declarado, lido sozinho, aponta para salário, enquanto a nota ao gestor e o motivo secundário apontam para a liderança. Salário é a resposta mais fácil de dar numa conversa de saída; por isso a entrevista precisa ser lida com a nota e com o segundo motivo, e não só pelo primeiro.
Quem respondeu a entrevista
A entrevista não é obrigatória. Responderam 77% de quem pediu para sair e só 38% de quem foi dispensado. Entre as unidades, a L7 fica bem abaixo das outras, com 37% de resposta.
Como o motivo só é perguntado a quem pede para sair, a diferença entre voluntárias e involuntárias não distorce o retrato dos motivos; a diferença entre unidades, sim. Para ver se ela muda a conclusão, cada resposta foi ponderada pela inversa da taxa de resposta da sua unidade, de modo que a L7 pese o que pesaria se todos tivessem respondido. Nenhum motivo mudou mais de 0,3 ponto percentual, e a ordem ficou a mesma.
| Motivo | Sem ponderação | Ponderado |
|---|---|---|
| Salário e benefícios | 25,6% | 25,6% |
| Liderança e gestor | 16,0% | 15,9% |
| Jornada e escala | 14,9% | 14,9% |
| Proposta de outra empresa | 14,0% | 14,0% |
| Crescimento e carreira | 9,6% | 9,4% |
| Deslocamento | 9,1% | 8,9% |
| Motivos pessoais e família | 5,8% | 6,0% |
| Ambiente e equipe | 5,1% | 5,2% |
Salário e benefícios
Sem ponderação: 25,6%
Ponderado: 25,6%
Liderança e gestor
Sem ponderação: 16,0%
Ponderado: 15,9%
Jornada e escala
Sem ponderação: 14,9%
Ponderado: 14,9%
Proposta de outra empresa
Sem ponderação: 14,0%
Ponderado: 14,0%
Crescimento e carreira
Sem ponderação: 9,6%
Ponderado: 9,4%
Deslocamento
Sem ponderação: 9,1%
Ponderado: 8,9%
Motivos pessoais e família
Sem ponderação: 5,8%
Ponderado: 6,0%
Ambiente e equipe
Sem ponderação: 5,1%
Ponderado: 5,2%
A ponderação supõe que, dentro de cada unidade, quem respondeu é parecido com quem não respondeu. Se quem não respondeu na L7 saiu por motivos diferentes dos de quem respondeu, nenhum peso corrige isso; é a primeira das limitações do caso.
Onde agir primeiro
Saídas nos primeiros 90 dias
Entre os 1.222 admitidos de janeiro de 2024 a 02/10/2025, que já completaram 90 dias de casa, a parte que pediu para sair até o 90º dia subiu em duas gerências e ficou estável no resto. No CD Expedição, foi de 20% entre os admitidos de 2024 para 39% entre os de 2025 (IC 95% de 31% a 48%); na L3 Operações, de 20% para 41% (de 26% a 57%). Nas demais gerências, de 15% para 17%.
Num modelo de Cox causa-específico só com os admitidos de 2025, o risco de saída voluntária foi 2,2 vezes o das demais gerências no CD Expedição (IC 95% de 1,6 a 3,0) e 2,1 vezes na L3 Operações (de 1,3 a 3,5).
Sair nos primeiros 90 dias costuma ter mais a ver com a chegada do que com o mercado: integração, escala informada na contratação, primeira liderança. As duas gerências não trocaram de gestor, e a entrevista de quem sai tão cedo é curta; o próximo passo é ouvir os admitidos dessas duas áreas antes de completarem 90 dias.
A troca de gestor na L5 Vendas
A L5 Vendas trocou de gestor em julho de 2025. Para separar o efeito da troca do que aconteceu na empresa toda no mesmo período, a L5 foi comparada com as outras sete gerências de Vendas, que não trocaram de gestor.
Antes da troca, a L5 perdia 2,1% do quadro por mês em saídas voluntárias, e as outras gerências de Vendas, 2,0%. Depois, a L5 foi a 5,8%, e as outras, a 2,2%. Descontada a mudança das outras gerências, a taxa da L5 ficou 2,5 vezes maior depois da troca (IC 95% de 1,4 a 4,4, modelo de Poisson).
O motivo acompanha: antes da troca, “liderança e gestor” apareceu em menos de 10 das 25 respostas da L5; depois, em 17 das 24 (71%, de 51% a 85%). É uma associação no tempo, e não a prova de que o novo gestor é a causa: são só seis meses, e outra coisa pode ter mudado na loja ao mesmo tempo. Mas é o sinal mais forte do caso, e o mais barato de verificar, numa conversa com a equipe e com o gestor.
Escala 6x1 no turno da noite
Na escala 6x1 do turno da noite, que é a da reposição das lojas e de parte do CD, “jornada e escala” é o motivo de 40% das saídas voluntárias respondidas (de 33% a 48%), contra 8% nas outras combinações de turno e escala. A taxa de saída voluntária também é a maior: 2,80% do grupo por mês.
A noite em outras escalas (12x36 no CD, 5x2 em algumas lojas) não tem o mesmo problema. O que pesa é a combinação da noite com a folga única na semana, e isso aponta para uma decisão de escala, e não de salário.
Prioridades por gerência
As três frentes acima viram uma lista. Em 2025, cada gerência recebeu uma prioridade:
- Alta: a taxa de saída voluntária ou a parte dos admitidos que saiu até 90 dias fica acima da empresa mesmo no limite inferior do intervalo de confiança.
- Média: as duas ficam acima da empresa na estimativa, ou “liderança e gestor” ou “jornada e escala” ficam acima da empresa no limite inferior do intervalo.
- Acompanhar: o resto.
Dentro de cada nível, a ordem é a das saídas voluntárias acima do esperado pela taxa da empresa. A lista completa, com os intervalos, está no CSV do topo da página; nenhum número de grupo com menos de 10 pessoas aparece nela.
A L2 Operações tem um destaque de “jornada e escala” no cruzamento de motivo com gerência, mas continua em “Acompanhar”: em 2025, a taxa voluntária (2,82% ao mês) fica acima da empresa (2,35%) só na estimativa, as saídas até 90 dias (6%) ficam abaixo da empresa (24%), e a parte de “jornada e escala” entre as respostas de 2025 não passa da empresa no limite inferior do intervalo.
| Ordem | Gerência | Prioridade | Sinais | Taxa voluntária ao mês | Saídas até 90 dias | Resposta | Liderança e gestor |
|---|---|---|---|---|---|---|---|
| 1 | CD Expedição | Alta | Taxa voluntária; Saídas até 90 dias | 3,21% | 39% | 63% | 16% |
| 2 | L5 Vendas | Alta | Taxa voluntária; Liderança e gestor | 3,85% | 25% | 76% | 55% |
| 3 | L3 Operações | Alta | Saídas até 90 dias | 2,84% | 41% | 57% | 8% |
| 4 | L1 Operações | Média | Taxa voluntária (na estimativa); Saídas até 90 dias (na estimativa) | 3,60% | 30% | 77% | 6% |
| 5 | L2 Operações | Acompanhar | Jornada e escala (cruzamento com a gerência) | 2,82% | 6% | 64% | 23% |
| 6 | L3 Vendas | Acompanhar | 2,50% | 19% | 68% | 21% | |
| 7 | L8 Vendas | Acompanhar | 2,42% | 20% | 74% | 26% | |
| 8 | L6 Operações | Acompanhar | 2,28% | 24% | 78% | 31% | |
| 9 | L5 Operações | Acompanhar | 2,18% | 21% | 54% | <10 | |
| 10 | L4 Vendas | Acompanhar | 2,20% | 29% | 71% | 21% | |
| 11 | L8 Operações | Acompanhar | 1,99% | 12% | 60% | <10 | |
| 12 | L1 Vendas | Acompanhar | 2,11% | 17% | 65% | 27% | |
| 13 | L6 Vendas | Acompanhar | 2,11% | 19% | 53% | 7% | |
| 14 | L7 Operações | Acompanhar | 1,97% | 21% | 22% | <10 | |
| 15 | L4 Operações | Acompanhar | 1,85% | 7% | 84% | 0% | |
| 16 | L2 Vendas | Acompanhar | 2,02% | 13% | 69% | 11% | |
| 17 | L7 Vendas | Acompanhar | 1,58% | 6% | 32% | <10 | |
| 18 | CD Recebimento | Acompanhar | 2,01% | 18% | 62% | 8% | |
| 19 | ESC Administrativo | Acompanhar | 0,94% | 4% | 72% | 15% |
1. CD Expedição
Prioridade: Alta
Sinais: Taxa voluntária; Saídas até 90 dias
Taxa voluntária ao mês: 3,21%
Saídas até 90 dias: 39%
Resposta: 63%
Liderança e gestor: 16%
2. L5 Vendas
Prioridade: Alta
Sinais: Taxa voluntária; Liderança e gestor
Taxa voluntária ao mês: 3,85%
Saídas até 90 dias: 25%
Resposta: 76%
Liderança e gestor: 55%
3. L3 Operações
Prioridade: Alta
Sinais: Saídas até 90 dias
Taxa voluntária ao mês: 2,84%
Saídas até 90 dias: 41%
Resposta: 57%
Liderança e gestor: 8%
4. L1 Operações
Prioridade: Média
Sinais: Taxa voluntária (na estimativa); Saídas até 90 dias (na estimativa)
Taxa voluntária ao mês: 3,60%
Saídas até 90 dias: 30%
Resposta: 77%
Liderança e gestor: 6%
5. L2 Operações
Prioridade: Acompanhar
Sinais: Jornada e escala (cruzamento com a gerência)
Taxa voluntária ao mês: 2,82%
Saídas até 90 dias: 6%
Resposta: 64%
Liderança e gestor: 23%
6. L3 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,50%
Saídas até 90 dias: 19%
Resposta: 68%
Liderança e gestor: 21%
7. L8 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,42%
Saídas até 90 dias: 20%
Resposta: 74%
Liderança e gestor: 26%
8. L6 Operações
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,28%
Saídas até 90 dias: 24%
Resposta: 78%
Liderança e gestor: 31%
9. L5 Operações
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,18%
Saídas até 90 dias: 21%
Resposta: 54%
Liderança e gestor: <10
10. L4 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,20%
Saídas até 90 dias: 29%
Resposta: 71%
Liderança e gestor: 21%
11. L8 Operações
Prioridade: Acompanhar
Taxa voluntária ao mês: 1,99%
Saídas até 90 dias: 12%
Resposta: 60%
Liderança e gestor: <10
12. L1 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,11%
Saídas até 90 dias: 17%
Resposta: 65%
Liderança e gestor: 27%
13. L6 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,11%
Saídas até 90 dias: 19%
Resposta: 53%
Liderança e gestor: 7%
14. L7 Operações
Prioridade: Acompanhar
Taxa voluntária ao mês: 1,97%
Saídas até 90 dias: 21%
Resposta: 22%
Liderança e gestor: <10
15. L4 Operações
Prioridade: Acompanhar
Taxa voluntária ao mês: 1,85%
Saídas até 90 dias: 7%
Resposta: 84%
Liderança e gestor: 0%
16. L2 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,02%
Saídas até 90 dias: 13%
Resposta: 69%
Liderança e gestor: 11%
17. L7 Vendas
Prioridade: Acompanhar
Taxa voluntária ao mês: 1,58%
Saídas até 90 dias: 6%
Resposta: 32%
Liderança e gestor: <10
18. CD Recebimento
Prioridade: Acompanhar
Taxa voluntária ao mês: 2,01%
Saídas até 90 dias: 18%
Resposta: 62%
Liderança e gestor: 8%
19. ESC Administrativo
Prioridade: Acompanhar
Taxa voluntária ao mês: 0,94%
Saídas até 90 dias: 4%
Resposta: 72%
Liderança e gestor: 15%
O que não explica: a idade
Olhando só a idade, os mais jovens saem mais: a chance de uma pessoa de 18 a 24 anos pedir para sair num mês é 1,60 vezes a de quem tem de 35 a 44 (IC 95% de 1,33 a 1,94). Mas os mais jovens são, em média, os mais novos de casa, e o tempo de casa é o que pesa: com ele no modelo, a razão cai para 1,01 (de 0,83 a 1,24), e a faixa etária como um todo deixa de fazer diferença (p = 0,40).
É um achado nulo que importa: uma política “para reter os jovens” atacaria o alvo errado. O ponto de atenção são os primeiros meses de casa, de qualquer idade.
Limitações
- Dados fictícios. Os padrões foram plantados por um gerador, e a análise os encontrou sem ler o gabarito. Com dados reais, os números seriam outros; o método é o mesmo.
- Viés de resposta. A ponderação corrige a diferença de resposta entre unidades, mas supõe que, dentro de cada unidade, quem respondeu é parecido com quem não respondeu. Isso não pode ser verificado com estes dados.
- Associação não é causa. A comparação da L5 com as outras gerências de Vendas supõe que, sem a troca, a L5 teria seguido a mesma tendência delas. Com seis meses depois da troca, o intervalo ainda é largo.
- Motivo declarado. A lista é fechada, e cada pessoa escolhe um motivo principal; é o que ela diz, e não necessariamente o que pesou.
- Janela de 90 dias. Os admitidos depois de 02/10/2025 ficam fora dessa conta, porque ainda não completaram a janela.
- Muitas comparações. No cruzamento de motivo com gerência, só contam como destaque os resíduos ajustados de valor absoluto 3 ou mais.
Método
As etapas abaixo estão no código, com o trecho de cada uma recolhido; as tabelas técnicas ficam no fim da seção.
- Classificar as saídas. Voluntária é o pedido de demissão; involuntária, a dispensa sem justa causa e o término de experiência. O acordo é uma categoria própria e entra como voluntária na divisão em duas (930 voluntárias e 523 involuntárias nos dois anos).
- Taxa de desligamento. Desligamentos do mês ÷ headcount médio do mês, em que o headcount médio é a média entre o quadro do primeiro e do último dia. A fórmula clássica de turnover usa no numerador a média entre admissões e desligamentos. No ano, as duas dão quase o mesmo: a taxa de desligamento foi de 39,8% em 2024 e 41,4% em 2025, e o turnover clássico, de 38,8% e 41,3%. Os intervalos das taxas são exatos de Poisson, por pessoa-mês.
- Saídas até 90 dias. Entre os admitidos de janeiro de 2024 a 02/10/2025 (1.222 pessoas), quem pediu para sair até o 90º dia de casa. Quem foi dispensado antes dos 90 dias conta como “não saiu voluntariamente”.
- Motivos. Pareto do motivo principal entre quem pediu para sair e respondeu, no geral e com nota 1 ou 2 ao gestor; proporções com intervalo de Wilson.
- Taxa de resposta e ponderação. Taxa de resposta por tipo de saída e por unidade, e o Pareto ponderado pela inversa da taxa de resposta da unidade.
- Motivo × gerência. Qui-quadrado de independência (115,1 com 90 graus de liberdade), com os três motivos menos citados juntos em “outros motivos” e o p calculado por simulação (p = 0,035), porque 56% das células têm frequência esperada menor que 5. Destaque só para resíduos ajustados com valor absoluto 3 ou mais: L5 Vendas em “liderança e gestor” (4,9) e L2 Operações em “jornada e escala” (3,0).
- Incidência acumulada e Cox causa-específico. Tempo do dia da admissão até a saída, para os admitidos em 2024 e 2025, com a saída involuntária como risco competitivo (estimador de Aalen-Johansen,
survfitdo pacote survival com o status como fator). No lugar do teste de Gray, que exige um pacote que não está instalado, um modelo de Cox causa-específico: a gerência como um todo está associada ao risco de saída voluntária (teste da razão de verossimilhança, 62,5 com 18 graus de liberdade, p < 0,001). - Troca de gestor. Saídas voluntárias por gerência de Vendas e mês, com a exposição em pessoa-mês, num modelo de Poisson com a gerência, o período (antes ou depois de julho de 2025) e a interação da L5 com o período depois da troca (diferença em diferenças). O modelo binomial negativo entraria se a dispersão passasse de 1,2; ela foi de 0,96.
- Regressão logística. Saída voluntária até 90 dias, com o grupo de gerência, o ano de admissão e a interação dos dois, a noite na escala 6x1 e a faixa etária.
- Confundimento pela idade. Regressão logística por pessoa-mês da saída voluntária no mês, com a faixa etária sozinha e depois com a faixa de tempo de casa.
- Prioridades. Os critérios da seção anterior, aplicados a 2025, com as contagens de grupos com menos de 10 pessoas trocadas por “<10”.
Ver o código R: taxa de desligamento
# Taxa de desligamento do mês: desligamentos ÷ headcount médio, em que o
# headcount médio é a média entre o quadro do primeiro e do último dia.
# A fórmula clássica de turnover usa a média entre admissões e desligamentos
# no numerador; as duas aparecem no método.
mensal <- pessoa_mes |>
group_by(ano_mes) |>
summarise(hc_medio = sum(peso), admissoes = sum(admitido_no_mes), .groups = "drop") |>
left_join(saidas |> count(ano_mes, name = "desligamentos"), "ano_mes") |>
left_join(saidas |> filter(voluntaria) |> count(ano_mes, name = "voluntarios"), "ano_mes") |>
mutate(across(c(desligamentos, voluntarios), \(x) coalesce(x, 0L)),
taxa = 100 * desligamentos / hc_medio, taxa_vol = 100 * voluntarios / hc_medio,
turnover_classico = 100 * (admissoes + desligamentos) / 2 / hc_medio)
anual <- mensal |>
group_by(ano = as.integer(substr(ano_mes, 1, 4))) |>
summarise(exposicao = sum(hc_medio), hc_medio = exposicao / n(), desligamentos = sum(desligamentos),
voluntarios = sum(voluntarios), involuntarios = desligamentos - voluntarios,
admissoes = sum(admissoes), .groups = "drop") |>
# Taxa mensal média (por pessoa-mês) e taxa do ano (desligamentos do ano ÷
# headcount médio do ano).
mutate(taxa_ano = 100 * desligamentos / hc_medio, taxa_vol_ano = 100 * voluntarios / hc_medio,
taxa = 100 * desligamentos / exposicao,
taxa_inf = taxa_ic(desligamentos, exposicao, "inf"), taxa_sup = taxa_ic(desligamentos, exposicao, "sup"),
taxa_vol = 100 * voluntarios / exposicao,
taxa_vol_inf = taxa_ic(voluntarios, exposicao, "inf"), taxa_vol_sup = taxa_ic(voluntarios, exposicao, "sup"),
taxa_inv = 100 * involuntarios / exposicao,
turnover_classico = 100 * (admissoes + desligamentos) / 2 / exposicao,
turnover_classico_ano = 100 * (admissoes + desligamentos) / 2 / hc_medio)
teste_anos <- poisson.test(anual$desligamentos, anual$exposicao)
tipos <- saidas |> count(tipo) |> mutate(pct = 100 * n / sum(n))Ver o código R: saídas até 90 dias
# Saídas voluntárias até 90 dias, entre os admitidos no período. Ficam fora os
# admitidos depois de 02/10/2025, que ainda não completaram a janela. Quem foi
# dispensado antes dos 90 dias conta como "não saiu voluntariamente".
coorte <- colaborador |>
filter(data_admissao >= as.Date("2024-01-01")) |>
left_join(pessoa_mes |> distinct(id_colaborador, gerencia, unidade) |> distinct(id_colaborador, .keep_all = TRUE),
"id_colaborador") |>
left_join(deslig |> select(id_colaborador, data_desligamento, tipo), "id_colaborador") |>
mutate(ano_admissao = year(data_admissao),
dias = as.integer(coalesce(data_desligamento, FIM) - data_admissao),
vol_90 = !is.na(tipo) & tipo %in% VOLUNTARIOS & dias <= 90,
noite_6x1 = turno == "Noite" & escala == "6x1",
grupo = if_else(gerencia %in% c("L3 Operações", "CD Expedição"), gerencia, "Demais gerências"))
coorte_90 <- coorte |> filter(data_admissao <= JANELA_90)
noventa_ano <- coorte_90 |>
group_by(ano_admissao) |>
summarise(admitidos = n(), saidas = sum(vol_90), .groups = "drop") |>
mutate(pct = 100 * saidas / admitidos, inf = wilson(saidas, admitidos, "inf"), sup = wilson(saidas, admitidos, "sup"))
noventa_gerencia <- coorte_90 |>
group_by(gerencia, ano_admissao) |>
summarise(admitidos = n(), saidas = sum(vol_90), .groups = "drop") |>
mutate(pct = 100 * saidas / admitidos, inf = wilson(saidas, admitidos, "inf"), sup = wilson(saidas, admitidos, "sup"),
gerencia = factor(gerencia, ordem_gerencias))
# Diferença 2025 menos 2024 em cada gerência: as duas que mais sobem.
subida_90 <- noventa_gerencia |>
select(gerencia, ano_admissao, pct, admitidos) |>
pivot_wider(names_from = ano_admissao, values_from = c(pct, admitidos)) |>
mutate(diferenca = pct_2025 - pct_2024) |>
arrange(desc(diferenca))
noventa_grupo <- coorte_90 |>
group_by(grupo, ano_admissao) |>
summarise(admitidos = n(), saidas = sum(vol_90), .groups = "drop") |>
mutate(pct = 100 * saidas / admitidos, inf = wilson(saidas, admitidos, "inf"), sup = wilson(saidas, admitidos, "sup"))Ver o código R: motivos
# Motivo declarado: só quem pediu para sair (pedido ou acordo) e respondeu.
# Pareto geral e entre quem deu nota 1 ou 2 ao gestor.
respondentes <- saidas |> filter(voluntaria, respondeu == "Sim", !is.na(motivo_principal))
pareto <- function(d) {
d |>
count(motivo = motivo_principal) |>
complete(motivo = MOTIVOS, fill = list(n = 0)) |>
mutate(total = sum(n), pct = 100 * n / total, inf = wilson(n, total, "inf"), sup = wilson(n, total, "sup")) |>
arrange(desc(n))
}
pareto_geral <- pareto(respondentes)
nota_baixa <- respondentes |> filter(nota_gestor <= 2)
pareto_nota_baixa <- pareto(nota_baixa)
# Quem declarou salário e deu nota baixa ao gestor: quantos põem a liderança
# como motivo secundário.
salario_nota_baixa <- nota_baixa |>
filter(motivo_principal == "Salário e benefícios") |>
summarise(n = n(), lideranca_secundario = sum(motivo_secundario %in% "Liderança e gestor")) |>
mutate(pct = 100 * lideranca_secundario / n, inf = wilson(lideranca_secundario, n, "inf"),
sup = wilson(lideranca_secundario, n, "sup"))
# Liderança citada como motivo principal ou secundário.
lideranca_qualquer <- respondentes |>
mutate(nota_baixa = nota_gestor <= 2,
lideranca = motivo_principal == "Liderança e gestor" | motivo_secundario %in% "Liderança e gestor") |>
group_by(nota_baixa) |>
summarise(n = n(), x = sum(lideranca), .groups = "drop") |>
mutate(pct = 100 * x / n, inf = wilson(x, n, "inf"), sup = wilson(x, n, "sup"))Ver o código R: taxa de resposta e ponderação
# Taxa de resposta da entrevista e ponderação pela inversa da taxa de resposta.
resposta_tipo <- saidas |>
group_by(voluntaria) |>
summarise(saidas = n(), responderam = sum(respondeu == "Sim"), .groups = "drop") |>
mutate(pct = 100 * responderam / saidas, inf = wilson(responderam, saidas, "inf"),
sup = wilson(responderam, saidas, "sup"))
resposta_unidade <- saidas |>
group_by(unidade) |>
summarise(saidas = n(), responderam = sum(respondeu == "Sim"), .groups = "drop") |>
mutate(pct = 100 * responderam / saidas, inf = wilson(responderam, saidas, "inf"),
sup = wilson(responderam, saidas, "sup"),
unidade = factor(unidade, unique(estrutura$unidade)))
# Peso de cada resposta voluntária: saídas voluntárias da unidade ÷ respostas
# voluntárias da unidade. Supõe que, dentro de cada unidade, quem respondeu é
# parecido com quem não respondeu.
pesos <- saidas |>
filter(voluntaria) |>
group_by(unidade) |>
summarise(peso = n() / sum(respondeu == "Sim" & !is.na(motivo_principal)), .groups = "drop")
pareto_ponderado <- respondentes |>
left_join(pesos, "unidade") |>
group_by(motivo = motivo_principal) |>
summarise(peso = sum(peso), .groups = "drop") |>
mutate(pct = 100 * peso / sum(peso)) |>
right_join(pareto_geral |> select(motivo, pct_sem_peso = pct), "motivo") |>
mutate(pct = coalesce(pct, 0), diferenca = pct - pct_sem_peso) |>
arrange(desc(pct))Ver o código R: motivo × gerência
# Motivo × gerência: qui-quadrado com p por simulação (mesmo agrupando, há
# células com frequência esperada pequena) e resíduos ajustados. Os três
# motivos menos citados viram "Outros motivos". Só |resíduo| >= 3 é destaque,
# por causa das muitas comparações.
MOTIVOS_QUI <- c(MOTIVOS[1:4], "Crescimento e carreira", "Outros motivos")
motivo_qui <- if_else(respondentes$motivo_principal %in% MOTIVOS_QUI, respondentes$motivo_principal, "Outros motivos")
tabela_mg <- table(factor(respondentes$gerencia, ordem_gerencias), factor(motivo_qui, MOTIVOS_QUI))
qui <- suppressWarnings(chisq.test(tabela_mg, simulate.p.value = TRUE, B = 20000))
qui_assint <- suppressWarnings(chisq.test(tabela_mg))
residuos <- as_tibble(as.table(qui$stdres), .name_repair = ~ c("gerencia", "motivo", "residuo")) |>
left_join(as_tibble(tabela_mg, .name_repair = ~ c("gerencia", "motivo", "n")), c("gerencia", "motivo")) |>
mutate(destaque = abs(residuo) >= 3)Ver o código R: incidência acumulada e Cox
# Incidência acumulada da saída voluntária com a involuntária como risco
# competitivo (Aalen-Johansen), entre os admitidos no período, até 180 dias.
coorte_ce <- coorte |>
mutate(evento = factor(case_when(is.na(tipo) ~ "censura", tipo %in% VOLUNTARIOS ~ "voluntária",
TRUE ~ "involuntária"), c("censura", "voluntária", "involuntária")),
dias = pmax(dias, 0.5))
aj <- survfit(Surv(dias, evento) ~ grupo + ano_admissao, data = coorte_ce)
incidencia <- {
s <- summary(aj, times = 0:180, extend = TRUE)
col <- which(s$states == "voluntária")
tibble(estrato = as.character(s$strata), dias = s$time, inc = 100 * s$pstate[, col],
inf = 100 * s$lower[, col], sup = 100 * s$upper[, col]) |>
mutate(grupo = str_match(estrato, "grupo=([^,]+)")[, 2],
ano_admissao = as.integer(str_match(estrato, "ano_admissao=(\\d+)")[, 2]))
}
incidencia_90 <- incidencia |> filter(dias == 90)
# Cox causa-específico (a saída involuntária vira censura): teste global da
# gerência, no lugar do log-rank, e razão de riscos dos dois grupos em 2025.
cox_global <- coxph(Surv(dias, evento == "voluntária") ~ gerencia, data = coorte_ce)
teste_gerencia <- anova(cox_global)
cox_2025 <- coxph(Surv(dias, evento == "voluntária") ~ relevel(factor(grupo), "Demais gerências"),
data = filter(coorte_ce, ano_admissao == 2025))
hr_2025 <- broom::tidy(cox_2025, exponentiate = TRUE, conf.int = TRUE) |>
mutate(grupo = sub(".*\\)", "", term)) |>
select(grupo, hr = estimate, inf = conf.low, sup = conf.high, p = p.value)Ver o código R: troca de gestor
# L5 Vendas troca de gestor em julho de 2025. Comparação de antes e depois com
# as outras sete gerências de Vendas como controle: saídas voluntárias por
# pessoa-mês, com modelo binomial negativo (diferença em diferenças).
vendas <- pessoa_mes |>
filter(area == "Vendas") |>
group_by(gerencia, ano_mes) |>
summarise(hc = sum(peso), .groups = "drop") |>
left_join(saidas |> filter(voluntaria, area == "Vendas") |> count(gerencia, ano_mes, name = "vol"),
c("gerencia", "ano_mes")) |>
mutate(vol = coalesce(vol, 0L), depois = as.Date(paste0(ano_mes, "-01")) >= TROCA,
troca = gerencia == gerencia_troca, troca_depois = troca & depois)
# Poisson primeiro; se a dispersão passar de 1,2, binomial negativo.
formula_troca <- vol ~ gerencia + depois + troca_depois + offset(log(hc))
modelo_troca <- glm(formula_troca, family = poisson, data = vendas)
dispersao <- sum(residuals(modelo_troca, type = "pearson")^2) / df.residual(modelo_troca)
if (dispersao > 1.2) modelo_troca <- MASS::glm.nb(formula_troca, data = vendas)
rr_troca <- {
b <- coef(summary(modelo_troca))["troca_depoisTRUE", ]
tibble(rr = exp(b[["Estimate"]]), inf = exp(b[["Estimate"]] - 1.96 * b[["Std. Error"]]),
sup = exp(b[["Estimate"]] + 1.96 * b[["Std. Error"]]), p = b[[4]], dispersao = dispersao,
modelo = if (dispersao > 1.2) "binomial negativo" else "Poisson")
}
troca_taxas <- vendas |>
group_by(grupo = if_else(troca, gerencia_troca, "Outras gerências de Vendas"), depois) |>
summarise(vol = sum(vol), exposicao = sum(hc), .groups = "drop") |>
mutate(taxa = 100 * vol / exposicao, inf = taxa_ic(vol, exposicao, "inf"), sup = taxa_ic(vol, exposicao, "sup"))
troca_mensal <- vendas |>
group_by(grupo = if_else(troca, gerencia_troca, "Outras gerências de Vendas"), ano_mes) |>
summarise(vol = sum(vol), hc = sum(hc), .groups = "drop") |>
arrange(grupo, ano_mes) |>
group_by(grupo) |>
# Média móvel de três meses: a taxa de uma gerência só oscila muito mês a mês.
mutate(taxa_mm3 = 100 * zoo_soma(vol) / zoo_soma(hc)) |>
ungroup()
troca_lideranca <- respondentes |>
filter(gerencia == gerencia_troca) |>
group_by(depois = data_desligamento >= TROCA) |>
summarise(n = n(), x = sum(motivo_principal == "Liderança e gestor"), .groups = "drop") |>
mutate(pct = 100 * x / n, inf = wilson(x, n, "inf"), sup = wilson(x, n, "sup"))Ver o código R: escala e turno
# Escala 6x1 no turno da noite: participação de "jornada e escala" entre os
# motivos e taxa de saída voluntária, contra as outras combinações.
grupo_jornada <- function(turno, escala) {
case_when(turno == "Noite" & escala == "6x1" ~ "Noite, 6x1", turno == "Noite" ~ "Noite, outras escalas",
escala == "6x1" ~ "Dia, 6x1", TRUE ~ "Dia, outras escalas")
}
ordem_jornada <- c("Noite, 6x1", "Noite, outras escalas", "Dia, 6x1", "Dia, outras escalas")
jornada <- respondentes |>
group_by(grupo = factor(grupo_jornada(turno, escala), ordem_jornada)) |>
summarise(n = n(), x = sum(motivo_principal == "Jornada e escala"), .groups = "drop") |>
mutate(pct = 100 * x / n, inf = wilson(x, n, "inf"), sup = wilson(x, n, "sup")) |>
left_join(pessoa_mes |>
group_by(grupo = factor(grupo_jornada(turno, escala), ordem_jornada)) |>
summarise(exposicao = sum(peso), pessoas = n_distinct(id_colaborador), .groups = "drop") |>
left_join(saidas |> filter(voluntaria) |>
count(grupo = factor(grupo_jornada(turno, escala), ordem_jornada), name = "vol"), "grupo") |>
mutate(taxa_vol = 100 * vol / exposicao, taxa_inf = taxa_ic(vol, exposicao, "inf"),
taxa_sup = taxa_ic(vol, exposicao, "sup")),
"grupo")Ver o código R: regressões
# Regressão logística da saída voluntária até 90 dias, entre os admitidos até
# 02/10/2025.
modelo_90 <- glm(vol_90 ~ relevel(factor(grupo), "Demais gerências") * factor(ano_admissao) + noite_6x1 +
relevel(factor(faixa_etaria), "35 a 44"),
family = binomial, data = coorte_90)
or_90 <- broom::tidy(modelo_90, exponentiate = TRUE, conf.int = TRUE, conf.method = "Wald") |>
filter(term != "(Intercept)") |>
select(termo = term, or = estimate, inf = conf.low, sup = conf.high, p = p.value)
# Confundimento: a faixa etária parece importar, mas deixa de ter efeito
# quando o tempo de casa entra no modelo. Unidade: pessoa-mês.
pm <- pessoa_mes |>
filter(ativo_inicio == 1) |>
left_join(saidas |> filter(voluntaria) |> transmute(id_colaborador, ano_mes, saiu = 1L),
c("id_colaborador", "ano_mes")) |>
mutate(saiu = coalesce(saiu, 0L), faixa_etaria = relevel(factor(faixa_etaria), "35 a 44"),
tempo_casa = cut(tempo_casa_meses, c(-Inf, 2, 11, 35, Inf),
c("Até 3 meses", "3 a 11 meses", "1 a 3 anos", "Mais de 3 anos")))
idade_bruto <- glm(saiu ~ faixa_etaria, family = binomial, data = pm)
idade_ajustado <- glm(saiu ~ faixa_etaria + tempo_casa, family = binomial, data = pm)
or_idade <- bind_rows(
broom::tidy(idade_bruto, exponentiate = TRUE, conf.int = TRUE, conf.method = "Wald") |> mutate(modelo = "Bruto"),
broom::tidy(idade_ajustado, exponentiate = TRUE, conf.int = TRUE, conf.method = "Wald") |> mutate(modelo = "Ajustado")) |>
filter(str_detect(term, "faixa_etaria")) |>
transmute(modelo, faixa = sub("faixa_etaria", "", term), or = estimate, inf = conf.low, sup = conf.high, p = p.value)
teste_idade_ajustado <- anova(update(idade_ajustado, . ~ tempo_casa), idade_ajustado, test = "LRT")
idade_tempo <- pm |>
count(faixa_etaria, tempo_casa) |>
group_by(faixa_etaria) |>
mutate(pct = 100 * n / sum(n)) |>
ungroup()Ver o código R: prioridades
# Prioridades por gerência, em 2025. Alta: a taxa voluntária ou as saídas até
# 90 dias ficam acima da empresa mesmo no limite inferior do intervalo.
# Média: as duas acima da empresa na estimativa, ou um motivo (liderança e
# gestor, jornada e escala) acima da empresa no limite inferior do intervalo.
# Acompanhar: o resto.
ano_ref <- 2025
empresa_vol <- with(filter(anual, ano == ano_ref), taxa_vol)
empresa_90 <- with(filter(noventa_ano, ano_admissao == ano_ref), pct)
empresa_motivo <- function(m) 100 * mean(respondentes$motivo_principal[respondentes$ano == ano_ref] == m)
prior <- pessoa_mes |>
filter(ano == ano_ref) |>
group_by(gerencia, unidade) |>
summarise(exposicao = sum(peso), .groups = "drop") |>
mutate(hc_medio = exposicao / 12) |>
left_join(saidas |> filter(ano == ano_ref) |>
group_by(gerencia) |>
summarise(vol = sum(voluntaria), saidas = n(), responderam = sum(respondeu == "Sim"),
nota_gestor = mean(nota_gestor, na.rm = TRUE), .groups = "drop"), "gerencia") |>
left_join(respondentes |> filter(ano == ano_ref) |>
group_by(gerencia) |>
summarise(resp_vol = n(), lideranca = sum(motivo_principal == "Liderança e gestor"),
jornada = sum(motivo_principal == "Jornada e escala"), .groups = "drop"), "gerencia") |>
left_join(noventa_gerencia |> filter(ano_admissao == ano_ref) |> mutate(gerencia = as.character(gerencia)) |>
select(gerencia, admitidos, saidas_90 = saidas), "gerencia") |>
mutate(across(c(vol, saidas, responderam, resp_vol, lideranca, jornada, admitidos, saidas_90), \(x) coalesce(x, 0L)),
taxa_vol = 100 * vol / exposicao, taxa_inf = taxa_ic(vol, exposicao, "inf"),
taxa_sup = taxa_ic(vol, exposicao, "sup"),
pct_90 = 100 * saidas_90 / admitidos, pct_90_inf = wilson(saidas_90, admitidos, "inf"),
pct_90_sup = wilson(saidas_90, admitidos, "sup"),
resposta = 100 * responderam / saidas,
pct_lideranca = 100 * lideranca / resp_vol, lid_inf = wilson(lideranca, resp_vol, "inf"),
pct_jornada = 100 * jornada / resp_vol, jor_inf = wilson(jornada, resp_vol, "inf"),
excesso = vol - exposicao * empresa_vol / 100,
sinal_lideranca = resp_vol >= MINIMO & lid_inf > empresa_motivo("Liderança e gestor"),
sinal_jornada = resp_vol >= MINIMO & jor_inf > empresa_motivo("Jornada e escala"),
alta = taxa_inf > empresa_vol | pct_90_inf > empresa_90,
media = !alta & ((taxa_vol > empresa_vol & pct_90 > empresa_90) | sinal_lideranca | sinal_jornada),
prioridade = case_when(alta ~ "Alta", media ~ "Média", TRUE ~ "Acompanhar"),
estimativa = !alta & taxa_vol > empresa_vol & pct_90 > empresa_90) |>
# Destaques do cruzamento motivo × gerência (2024 e 2025) também viram sinal,
# mesmo quando não mudam a prioridade.
left_join(residuos |> filter(destaque, residuo > 0) |>
group_by(gerencia) |>
summarise(motivos_residuo = paste(motivo, collapse = "; "), .groups = "drop"), "gerencia") |>
mutate(sinais = pmap_chr(list(taxa_inf > empresa_vol, pct_90_inf > empresa_90, estimativa, sinal_lideranca,
sinal_jornada, motivos_residuo),
\(a, b, e, l, j, r) {
s <- c(if (a) "Taxa voluntária", if (b) "Saídas até 90 dias",
if (e) c("Taxa voluntária (na estimativa)", "Saídas até 90 dias (na estimativa)"),
if (l) "Liderança e gestor", if (j) "Jornada e escala")
if (!is.na(r)) {
novos <- setdiff(strsplit(r, "; ")[[1]], s)
if (length(novos)) s <- c(s, paste(novos, "(cruzamento com a gerência)"))
}
paste(s, collapse = "; ")
})) |>
arrange(factor(prioridade, c("Alta", "Média", "Acompanhar")), desc(excesso)) |>
mutate(ordem = row_number())
# CSV para baixar: só agregados; contagens e percentuais de grupos com menos
# de 10 pessoas viram "<10".
# Mesmo formato do CSV da Auditoria: vírgula separa colunas e ponto separa decimais.
fmt <- function(x, d = 1) formatC(x, format = "f", digits = d)
mascara <- function(valor, n, d = 1) if_else(n < MINIMO, "<10", fmt(valor, d))
prioridades_csv <- prior |>
transmute(ordem, gerencia, unidade, prioridade, sinais = na_if(sinais, ""),
headcount_medio = fmt(hc_medio, 0),
saidas_voluntarias = if_else(vol < MINIMO, "<10", as.character(vol)),
taxa_voluntaria_mensal_pct = fmt(taxa_vol, 2),
taxa_ic95_inf = fmt(taxa_inf, 2), taxa_ic95_sup = fmt(taxa_sup, 2),
admitidos = if_else(admitidos < MINIMO, "<10", as.character(admitidos)),
saidas_ate_90_dias_pct = mascara(pct_90, admitidos), saidas_90_ic95_inf = mascara(pct_90_inf, admitidos),
saidas_90_ic95_sup = mascara(pct_90_sup, admitidos),
taxa_resposta_pct = mascara(resposta, saidas),
lideranca_gestor_pct = mascara(pct_lideranca, resp_vol),
jornada_escala_pct = mascara(pct_jornada, resp_vol),
nota_media_gestor = mascara(nota_gestor, responderam))
dir.create("resultados", showWarnings = FALSE)
write_csv(prioridades_csv, "resultados/prioridades_gerencias.csv", na = "")Regressão logística: saída voluntária até 90 dias (1.222 admitidos; referências: demais gerências, admitidos em 2024, dia ou outras escalas, 35 a 44 anos).
| Termo | Razão de chances | IC 95% | p |
|---|---|---|---|
| CD Expedição | 1,38 | 0,81 a 2,29 | 0,219 |
| L3 Operações | 1,35 | 0,61 a 2,79 | 0,433 |
| Admitido em 2025 | 1,20 | 0,84 a 1,73 | 0,318 |
| Noite, escala 6x1 | 1,47 | 1,02 a 2,09 | 0,037 |
| 18 a 24 anos | 1,46 | 0,91 a 2,42 | 0,125 |
| 25 a 34 anos | 1,24 | 0,76 a 2,08 | 0,399 |
| 45 anos ou mais | 1,06 | 0,54 a 2,04 | 0,874 |
| CD Expedição × 2025 | 2,30 | 1,15 a 4,66 | 0,019 |
| L3 Operações × 2025 | 2,10 | 0,76 a 6,02 | 0,158 |
Faixa etária, sem e com o tempo de casa (42.987 pessoas-mês; referência: 35 a 44 anos).
| Modelo | Faixa etária | Razão de chances | IC 95% | p |
|---|---|---|---|---|
| Só a faixa etária | 18 a 24 anos | 1,60 | 1,33 a 1,94 | < 0,001 |
| Só a faixa etária | 25 a 34 anos | 1,13 | 0,93 a 1,37 | 0,220 |
| Só a faixa etária | 45 ou mais anos | 0,85 | 0,67 a 1,07 | 0,168 |
| Com o tempo de casa | 18 a 24 anos | 1,01 | 0,83 a 1,24 | 0,902 |
| Com o tempo de casa | 25 a 34 anos | 0,92 | 0,76 a 1,12 | 0,412 |
| Com o tempo de casa | 45 ou mais anos | 0,86 | 0,67 a 1,09 | 0,208 |
Taxa de resposta por tipo de saída.
| Grupo | Saídas | Responderam | Taxa de resposta (IC 95%) |
|---|---|---|---|
| Involuntárias (dispensa ou término de experiência) | 523 | 199 | 38,0% (34,0% a 42,3%) |
| Voluntárias (pedido ou acordo) | 930 | 712 | 76,6% (73,7% a 79,2%) |
O que o caso demonstra
- Ler a entrevista junto com o resto. O motivo declarado, sozinho, apontava para salário; cruzado com a nota ao gestor e com o motivo secundário, apontou para a liderança.
- Olhar a composição, e não só o total. Uma taxa estável escondia mais saídas voluntárias e saídas cada vez mais cedo em duas gerências.
- Comparar com um controle. A troca de gestor da L5 foi medida contra as outras gerências de Vendas, e não só contra o próprio passado.
- Dizer o que os dados não sustentam. O viés de resposta foi medido e corrigido, a idade foi descartada como explicação, e nenhuma associação foi tratada como causa.
- Uma base pronta para o painel. As seis tabelas formam um modelo dimensional, que a próxima etapa do caso usa num painel de turnover em Power BI.
Sua empresa faz entrevista de desligamento, mas ninguém lê junto com o resto?
Me conte como funciona hoje e eu digo o que dá para cruzar.












