Traçando intervalos de confiança para as probabilidades previstas a partir de uma regressão logística

20

Ok, eu tenho uma regressão logística e usei a predict()função para desenvolver uma curva de probabilidade com base em minhas estimativas.

## LOGIT MODEL:
library(car)
mod1 = glm(factor(won) ~ as.numeric(bid), data=mydat, family=binomial(link="logit"))

## PROBABILITY CURVE:
all.x <- expand.grid(won=unique(won), bid=unique(bid))
y.hat.new <- predict(mod1, newdata=all.x, type="response")
plot(bid<-000:1000,predict(mod1,newdata=data.frame(bid<-c(000:1000)),type="response"), lwd=5, col="blue", type="l")

Isso é ótimo, mas estou curioso para traçar os intervalos de confiança para as probabilidades. Eu tentei, plot.ci()mas não tive sorte. Alguém pode me indicar algumas maneiras de fazer isso, de preferência com o carpacote ou a base R.

ATMathew
fonte
4
(+1) Em resposta aos votos para encerrar o tópico: Aparentemente, a base para esses votos é que a pergunta parece fazer uma pergunta puramente relacionada ao software ("como plotar tal e tal em R"), um pergunta que realmente deve aparecer no SO. Observe, no entanto, que ocultos na resposta atual são fórmulas estatísticas para criar os pontos de plotagem. Isso sugere que há interesse estatístico na questão, por isso reluto em votar na migração. Uma boa resposta aqui destacaria e explicaria esse ponto estatístico.
whuber

Respostas:

26

O código que você usou estima um modelo de regressão logística usando a glmfunção Você não incluiu dados, então eu vou inventar.

set.seed(1234)
mydat <- data.frame(
    won=as.factor(sample(c(0, 1), 250, replace=TRUE)), 
    bid=runif(250, min=0, max=1000)
)
mod1 <- glm(won~bid, data=mydat, family=binomial(link="logit"))

Um modelo de regressão logística modela a relação entre uma variável de resposta binária e, neste caso, um preditor contínuo. O resultado é uma probabilidade transformada em logit como uma relação linear com o preditor. No seu caso, o resultado é uma resposta binária correspondente a ganhar ou não ganhar no jogo e está sendo predito pelo valor da aposta. Os coeficientes de mod1são dados em probabilidades registradas (que são difíceis de interpretar), de acordo com:

logit(p)=registro(p(1-p))=β0 0+β1x1

Para converter probabilidades registradas em probabilidades, podemos traduzir o acima para

p=exp(β0 0+β1x1)(1+exp(β0 0+β1x1))

Você pode usar essas informações para configurar o gráfico. Primeiro, você precisa de um intervalo da variável preditora:

plotdat <- data.frame(bid=(0:1000))

Em seguida predict, usando , você pode obter previsões com base no seu modelo

preddat <- predict(mod1, newdata=plotdat, se.fit=TRUE)

Observe que os valores ajustados também podem ser obtidos via

mod1$fitted

Ao especificar se.fit=TRUE, você também obtém o erro padrão associado a cada valor ajustado. O resultado data.frameé uma matriz com os seguintes componentes: as previsões ajustadas ( fit), os erros padrão estimados ( se.fit) e um escalar que fornece a raiz quadrada da dispersão usada para calcular os erros padrão ( residual.scale). No caso de um logit binomial, o valor será de 1 (que você pode ver ao entrar preddat$residual.scaleno R). Se você quiser ver um exemplo do que você calculou até agora, digite head(data.frame(preddat)).

O próximo passo é configurar o gráfico. Eu gosto de configurar uma área de plotagem em branco com os parâmetros primeiro:

with(mydat, plot(bid, won, type="n", 
    ylim=c(0, 1), ylab="Probability of winning", xlab="Bid"))

Agora você pode ver onde é importante saber como calcular as probabilidades ajustadas. Você pode desenhar a linha correspondente às probabilidades ajustadas, seguindo a segunda fórmula acima. Usando o, preddat data.framevocê pode converter os valores ajustados em probabilidades e usá-los para plotar uma linha contra os valores da sua variável preditora.

with(preddat, lines(0:1000, exp(fit)/(1+exp(fit)), col="blue"))

Por fim, responda à sua pergunta, os intervalos de confiança podem ser adicionados ao gráfico calculando a probabilidade dos valores ajustados +/- 1.96vezes o erro padrão:

with(preddat, lines(0:1000, exp(fit+1.96*se.fit)/(1+exp(fit+1.96*se.fit)), lty=2))
with(preddat, lines(0:1000, exp(fit-1.96*se.fit)/(1+exp(fit-1.96*se.fit)), lty=2))

O gráfico resultante (dos dados gerados aleatoriamente) deve se parecer com isso:

insira a descrição da imagem aqui

Por conveniência, aqui está todo o código em um pedaço:

set.seed(1234)
mydat <- data.frame(
    won=as.factor(sample(c(0, 1), 250, replace=TRUE)), 
    bid=runif(250, min=0, max=1000)
)
mod1 <- glm(won~bid, data=mydat, family=binomial(link="logit"))
plotdat <- data.frame(bid=(0:1000))
preddat <- predict(mod1, newdata=plotdat, se.fit=TRUE)
with(mydat, plot(bid, won, type="n", 
    ylim=c(0, 1), ylab="Probability of winning", xlab="Bid"))
with(preddat, lines(0:1000, exp(fit)/(1+exp(fit)), col="blue"))
with(preddat, lines(0:1000, exp(fit+1.96*se.fit)/(1+exp(fit+1.96*se.fit)), lty=2))
with(preddat, lines(0:1000, exp(fit-1.96*se.fit)/(1+exp(fit-1.96*se.fit)), lty=2))

(Nota: esta é uma resposta muito editada, na tentativa de torná-la mais relevante para stats.stackexchange.)

smillig
fonte
onde a variável é se.fitdefinida?
Macro
In predict(..., se.fit=TRUE).
21712 smillig
(-1) Esses ICs são para cada um dos casos individuais? Nesse caso, para um resultado binário, o único IC sensível para uma probabilidade prevista é [0,1]. Mesmo que essa seja uma resposta tecnicamente proficiente.
Rolando2 23/03
Pelo comentário do @ whuber, acho que uma boa resposta deve incluir uma fórmula de como o SE é calculado. Alguém poderia talvez editar e melhorar a resposta?
Heisenberg
1
Sua resposta parece fornecer apenas o "intervalo médio de previsão". Como eu adicionaria o 'intervalo de previsão de pontos'?
Bob Hopez
0

Aqui está uma modificação da solução do @ smillig. Eu uso ferramentas tidyverse aqui e também uso a linkinvfunção que faz parte do objeto de modelo GLM mod1. Dessa forma, você não precisa inverter manualmente a função logística, e essa abordagem funcionará independentemente do GLM específico que você ajustar.

library(tidyverse)
library(magrittr)


set.seed(1234)

# create fake data on gambling. Does prob win depend on bid size? 
mydat <- data.frame(
  won=as.factor(sample(c(0, 1), 250, replace=TRUE)), 
  bid=runif(250, min=0, max=1000)
)

# logistic regression model: 
mod1 <- glm(won~bid, data=mydat, family=binomial(link="logit"))

# new predictor values to use for prediction: 
plotdat <- data.frame(bid=(0:1000))

# df with predictions, lower and upper limits of CIs: 
preddat <- predict(mod1,
               type = "link",
               newdata=plotdat,
               se.fit=TRUE) %>% 
  as.data.frame() %>% 
  mutate(bid = (0:1000), 

         # model object mod1 has a component called linkinv that 
         # is a function that inverts the link function of the GLM:
         lower = mod1$family$linkinv(fit - 1.96*se.fit), 
         point.estimate = mod1$family$linkinv(fit), 
         upper = mod1$family$linkinv(fit + 1.96*se.fit)) 


# plotting with ggplot: 
preddat %>% ggplot(aes(x = bid, 
                   y = point.estimate)) + 
  geom_line(colour = "blue") + 
  geom_ribbon(aes(ymin = lower,
                  ymax = upper), 
              alpha = 0.5) + 
  scale_y_continuous(limits = c(0,1))
Nayef
fonte
3
Embora a implementação seja frequentemente misturada com conteúdo substantivo em perguntas, devemos ser um site para fornecer informações sobre estatísticas, aprendizado de máquina etc., não sobre código. Também pode ser bom fornecer código, mas elabore sua resposta substantiva em texto para pessoas que não leem esse idioma o suficiente para reconhecer e extrair a resposta do código.
gung - Restabelece Monica