0으로 팽창 된 감마 회귀를위한 SAS NLMIXED 코드를 R로 변환


11

R에서 연속 응답 변수에 대해 0으로 부풀린 회귀를 실행하려고합니다. gamlss 구현을 알고 있지만 Dale McLerran이 개념적으로 조금 더 직관적 인이 알고리즘을 시도하고 싶습니다. 불행히도 코드는 SAS에 있으며 nlme와 같은 코드를 다시 작성하는 방법을 모르겠습니다.

코드는 다음과 같습니다.

proc nlmixed data=mydata;
  parms b0_f=0 b1_f=0 
        b0_h=0 b1_h=0 
        log_theta=0;


  eta_f = b0_f + b1_f*x1 ;
  p_yEQ0 = 1 / (1 + exp(-eta_f));


  eta_h = b0_h + b1_h*x1;
  mu    = exp(eta_h);
  theta = exp(log_theta);
  r = mu/theta;


  if y=0 then
     ll = log(p_yEQ0);
  else
     ll = log(1 - p_yEQ0)
          - lgamma(theta) + (theta-1)*log(y) - theta*log(r) - y/r;


  model y ~ general(ll);
  predict (1 - p_yEQ0)*mu out=expect_zig;
  predict r out=shape;
  estimate "scale" theta;
run;

보낸 사람 : http://listserv.uga.edu/cgi-bin/wa?A2=ind0805A&L=sas-l&P=R20779

더하다:

참고 : 여기에는 혼합 효과가 없으며 고정되어 있습니다.

이 피팅의 장점은 (계수는 로지스틱 회귀를 P (y = 0)에 개별적으로 피팅하는 것과 동일하지만 E (y | y> 0에 로그 링크를 갖는 감마 오류 회귀와 동일하더라도)에도 불구하고 0을 포함하는 결합 함수 E (y)를 추정하십시오. line을 사용하여 SAS에서 CI를 사용하여이 값을 예측할 수 있습니다 predict (1 - p_yEQ0)*mu.

또한 E (y)에 대한 예측 변수의 중요성을 테스트하기 위해 사용자 정의 대비 문을 작성할 수 있습니다. 예를 들어, 내가 사용한 다른 SAS 코드 버전은 다음과 같습니다.

proc nlmixed data=TestZIG;
      parms b0_f=0 b1_f=0 b2_f=0 b3_f=0
            b0_h=0 b1_h=0 b2_h=0 b3_h=0
            log_theta=0;


        if gifts = 1 then x1=1; else x1 =0;
        if gifts = 2 then x2=1; else x2 =0;
        if gifts = 3 then x3=1; else x3 =0;


      eta_f = b0_f + b1_f*x1 + b2_f*x2 + b3_f*x3;
      p_yEQ0 = 1 / (1 + exp(-eta_f));

      eta_h = b0_h + b1_h*x1 + b2_h*x2 + b3_h*x3;
      mu    = exp(eta_h);
      theta = exp(log_theta);
      r = mu/theta;

      if amount=0 then
         ll = log(p_yEQ0);
      else
         ll = log(1 - p_yEQ0)
              - lgamma(theta) + (theta-1)*log(amount) -                      theta*log(r) - amount/r;

      model amount ~ general(ll);
      predict (1 - p_yEQ0)*mu out=expect_zig;
      estimate "scale" theta;
    run; 

그런 다음 "gift1"대 "gift2"(b1 대 b2)를 추정하기 위해 다음과 같은 추정 문을 작성할 수 있습니다.

estimate "gift1 versus gift 2" 
 (1-(1 / (1 + exp(-b0_f -b1_f))))*(exp(b0_h + b1_h)) - (1-(1 / (1 + exp(-b0_f -b2_f))))*(exp(b0_h + b2_h)) ; 

R이 할 수 있습니까?


2
user779747은 Rhelp에 그의 크로스 포스팅에서이 글이 여기에 처음으로 게시되었다는 점에 주목했습니다. 나는 SO에 그러한 통지를 게시하라는 구체적인 요청을 보지 못했지만 우리의 일부 헬프 데스크 담당자는 R 메일 링리스트에 명시된 기대치 때문에 그것을 기대합니다.
DWin

답변:


9

이 코드에서 약간의 시간을 보냈다면 기본적으로 마치

1) 우측으로 로지스틱 회귀 하는가 b0_f + b1_f*x1y > 0목표 변수,

2) y> 0 인 관측치의 경우 오른쪽 b0_h + b1_h*x1, 감마 우도 link=log,

3) 또한 감마 분포의 모양 모수를 추정합니다.

한 번의 함수 호출 만하면되기 때문에 공동으로 가능성을 최대화합니다. 그러나 가능성은 어쨌든 분리되므로 결과적으로 개선 된 모수 추정값을 얻지 못합니다.

다음은 glm프로그래밍 노력을 절약하기 위해 함수를 사용하는 일부 R 코드입니다 . 알고리즘 자체를 모호하게하기 때문에 원하는 것이 아닐 수도 있습니다. 코드는 확실히 깨끗하지도 않습니다.

McLerran <- function(y, x)
{
  z <- y > 0
  y.gt.0 <- y[y>0]
  x.gt.0 <- x[y>0]

  m1 <- glm(z~x, family=binomial)
  m2 <- glm(y.gt.0~x.gt.0, family=Gamma(link=log))

  list("p.ygt0"=m1,"ygt0"=m2)
}

# Sample data
x <- runif(100)
y <- rgamma(100, 3, 1)      # Not a function of x (coef. of x = 0)
b <- rbinom(100, 1, 0.5*x)  # p(y==0) is a function of x
y[b==1] <- 0

foo <- McLerran(y,x)
summary(foo$ygt0)

Call:
glm(formula = y.gt.0 ~ x.gt.0, family = Gamma(link = log))

Deviance Residuals: 
     Min        1Q    Median        3Q       Max  
-2.08888  -0.44446  -0.06589   0.28111   1.31066  

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   1.2033     0.1377   8.737 1.44e-12 ***
x.gt.0       -0.2440     0.2352  -1.037    0.303    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

(Dispersion parameter for Gamma family taken to be 0.3448334)

    Null deviance: 26.675  on 66  degrees of freedom
Residual deviance: 26.280  on 65  degrees of freedom
AIC: 256.42

Number of Fisher Scoring iterations: 6

감마 분포의 모양 모수는 1 / 감마 패밀리의 분산 모수와 같습니다. 프로그래밍 방식으로 액세스하려는 계수 및 기타 항목은 반환 값 목록의 개별 요소에서 액세스 할 수 있습니다.

> coefficients(foo$p.ygt0)
(Intercept)           x 
   2.140239   -2.393388 

루틴의 출력을 사용하여 예측을 수행 할 수 있습니다. 다음은 예상 값과 기타 정보를 생성하는 방법을 보여주는 R 코드입니다.

# Predict expected value
predict.McLerren <- function(model, x.new)
{
  x <- as.data.frame(x.new)
  colnames(x) <- "x"
  x$x.gt.0 <- x$x

  pred.p.ygt0 <- predict(model$p.ygt0, newdata=x, type="response", se.fit=TRUE)
  pred.ygt0 <- predict(model$ygt0, newdata=x, type="response", se.fit=TRUE)  

  p0 <- 1 - pred.p.ygt0$fit
  ev <- (1-p0) * pred.ygt0$fit

  se.p0 <- pred.p.ygt0$se.fit
  se.ev <- pred.ygt0$se.fit

  se.fit <- sqrt(((1-p0)*se.ev)^2 + (ev*se.p0)^2 + (se.p0*se.ev)^2)

  list("fit"=ev, "p0"=p0, "se.fit" = se.fit,
       "pred.p.ygt0"=pred.p.ygt0, "pred.ygt0"=pred.ygt0)
}

그리고 샘플 실행 :

> x.new <- seq(0.05,0.95,length=5)
> 
> foo.pred <- predict.McLerren(foo, x.new)
> foo.pred$fit
       1        2        3        4        5 
2.408946 2.333231 2.201889 2.009979 1.763201 
> foo.pred$se.fit
        1         2         3         4         5 
0.3409576 0.2378386 0.1753987 0.2022401 0.2785045 
> foo.pred$p0
        1         2         3         4         5 
0.1205351 0.1733806 0.2429933 0.3294175 0.4291541 

이제 계수 추출과 대조를 위해 :

coef.McLerren <- function(model)
{
  temp1 <- coefficients(model$p.ygt0)
  temp2 <- coefficients(model$ygt0)
  names(temp1) <- NULL
  names(temp2) <- NULL
  retval <- c(temp1, temp2)
  names(retval) <- c("b0.f","b1.f","b0.h","b1.h")
  retval
}

contrast.McLerren <- function(b0_f, b1_f, b2_f, b0_h, b1_h, b2_h)
{
  (1-(1 / (1 + exp(-b0_f -b1_f))))*(exp(b0_h + b1_h)) - (1-(1 / (1 + exp(-b0_f -b2_f))))*(exp(b0_h + b2_h))
}


> coef.McLerren(foo)
      b0.f       b1.f       b0.h       b1.h 
 2.0819321 -1.8911883  1.0009568  0.1334845 

2
"부품"(예 : PR (y> 0)에 대한 로짓 회귀 분석 및 E (y | y> 0)에 대한 감마 회귀 분석)과 관련하여 정확하지만 합쳐진 추정치 (및 표준 오류, CI) 주요 관심사, 즉 E (y)이 수량의 예측은 SAS 코드에서 (1-p_yEQ0) * mu에 의해 이루어지며이 공식을 통해이 결합 된 값의 계수에 대비를 수행 할 수 있습니다.
B_Miner

@B_Miner-예측 문제를 부분적으로 해결하는 코드 + 예제를 추가했습니다.
jbowman

그래도 별도의 추정치가 아닙니까? SAS에서 NLMIXED는 CI뿐만 아니라 E (y)의 포인트 추정치를 추정 할 수있는 기능을 제공 할 것입니다 (델타 방법을 사용). 또한 선형 가설을 테스트하기 위해 위에 표시된대로 매개 변수의 사용자 정의 대비를 작성할 수 있습니다. R 대안이 있어야합니까?
B_Miner

예, 아니오 이 예제를 사용하기 위해 반환 된 foo.pred$fit값은 E (y)의 추정치를 제공하지만 구성 요소 foo.pred$pred.ygt0$pred는 E (y | y> 0)을 제공합니다. y, BTW에 대한 표준 오류 계산에 se.fit으로 반환했습니다. 계수는 계수 ( foo.pred$pred.ygt0) 및 계수 ( foo.pred$pred.p.ygt0)로 구성 요소에서 얻을 수 있습니다 . 추출 루틴과 대조 루틴을 잠시 후에 작성하겠습니다.
jbowman

se.fit <-sqrt (((1-p0) * se.ev) ^ 2 + (ev * se.p0) ^ 2 + (se.p0 * se.ev) ^ 2)
B_Miner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.