The R Project SVN R

Rev

Rev 88768 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
56186 murdoch 1
 
88779 pd 2
R Under development (unstable) (2025-09-03 r88777) -- "Unsuffered Consequences"
88768 pd 3
Copyright (C) 2025 The R Foundation for Statistical Computing
4
Platform: x86_64-apple-darwin21.6.0
56186 murdoch 5
 
6
R is free software and comes with ABSOLUTELY NO WARRANTY.
7
You are welcome to redistribute it under certain conditions.
8
Type 'license()' or 'licence()' for distribution details.
9
 
10
R is a collaborative project with many contributors.
11
Type 'contributors()' for more information and
12
'citation()' on how to cite R or R packages in publications.
13
 
14
Type 'demo()' for some demos, 'help()' for on-line help, or
15
'help.start()' for an HTML browser interface to help.
16
Type 'q()' to quit R.
17
 
18
> pkgname <- "stats4"
19
> source(file.path(R.home("share"), "R", "examples-header.R"))
20
> options(warn = 1)
21
> library('stats4')
22
> 
61787 ripley 23
> base::assign(".oldSearch", base::search(), pos = 'CheckExEnv')
73819 hornik 24
> base::assign(".old_wd", base::getwd(), pos = 'CheckExEnv')
56186 murdoch 25
> cleanEx()
26
> nameEx("mle")
27
> ### * mle
28
> 
29
> flush(stderr()); flush(stdout())
30
> 
31
> ### Name: mle
32
> ### Title: Maximum Likelihood Estimation
33
> ### Aliases: mle
34
> ### Keywords: models
35
> 
36
> ### ** Examples
37
> 
38
> ## Avoid printing to unwarranted accuracy
39
> od <- options(digits = 5)
77805 pd 40
> 
41
> ## Simulated EC50 experiment with count data
88768 pd 42
> ec50 <- data.frame(
43
+ x = 0:10,
44
+ y = c(26, 17, 13, 12, 20, 5, 9, 8, 5, 4, 8))
56186 murdoch 45
> 
46
> ## Easy one-dimensional MLE:
88768 pd 47
> nLL <- function(lambda) with(ec50,-sum(stats::dpois(y, lambda, log = TRUE)))
48
> fit0 <- mle(nLL, start = list(lambda = 5), nobs = NROW(ec50))
77805 pd 49
> 
50
> ## sanity check --- notice that "nobs" must be input
51
> ## (not guaranteed to be meaningful for any likelihood)
88768 pd 52
> stopifnot(nobs(fit0) == length(ec50$y))
77805 pd 53
> 
54
> 
56186 murdoch 55
> # For 1D, this is preferable:
88768 pd 56
> fit1 <- mle(nLL, start = list(lambda = 5), nobs = NROW(ec50),
56186 murdoch 57
+             method = "Brent", lower = 1, upper = 20)
58
> 
59
> ## This needs a constrained parameter space: most methods will accept NA
88779 pd 60
> mll1 <- function(ymax = 15, xhalf = 6) {
88768 pd 61
+     if(ymax > 0 && xhalf > 0) 
62
+       with(ec50, -sum(stats::dpois(y, lambda = ymax/(1+x/xhalf), log = TRUE)))
56281 ripley 63
+     else NA
64
+ }
88779 pd 65
> (fit <- mle(mll1, nobs = NROW(ec50)))
56186 murdoch 66
 
67
Call:
88779 pd 68
mle(minuslogl = mll1, nobs = NROW(ec50))
56186 murdoch 69
 
70
Coefficients:
71
   ymax   xhalf 
72
24.9931  3.0571 
88779 pd 73
> mle(mll1, fixed = list(xhalf = 6))
56186 murdoch 74
 
75
Call:
88779 pd 76
mle(minuslogl = mll1, fixed = list(xhalf = 6))
56186 murdoch 77
 
78
Coefficients:
79
  ymax  xhalf 
80
19.288  6.000 
77805 pd 81
> 
77937 pd 82
> ## Alternative using bounds on optimization
88779 pd 83
> mll2 <- function(ymax = 15, xhalf = 6)
88768 pd 84
+     with(ec50, -sum(stats::dpois(y, lambda = ymax/(1+x/xhalf), log = TRUE)))
88779 pd 85
> mle(mll2, lower = rep(0, 2))
56186 murdoch 86
 
87
Call:
88779 pd 88
mle(minuslogl = mll2, lower = rep(0, 2))
56186 murdoch 89
 
90
Coefficients:
91
   ymax   xhalf 
92
24.9994  3.0558 
93
> 
94
> AIC(fit)
95
[1] 61.208
96
> BIC(fit)
97
[1] 62.004
98
> 
99
> summary(fit)
100
Maximum likelihood estimation
101
 
102
Call:
88779 pd 103
mle(minuslogl = mll1, nobs = NROW(ec50))
56186 murdoch 104
 
105
Coefficients:
106
      Estimate Std. Error
107
ymax   24.9931     4.2244
108
xhalf   3.0571     1.0348
109
 
110
-2 log L: 57.208 
111
> logLik(fit)
112
'log Lik.' -28.604 (df=2)
113
> vcov(fit)
114
         ymax   xhalf
115
ymax  17.8459 -3.7206
116
xhalf -3.7206  1.0708
117
> plot(profile(fit), absVal = FALSE)
118
> confint(fit)
119
Profiling...
120
        2.5 %  97.5 %
121
ymax  17.8845 34.6194
122
xhalf  1.6616  6.4792
123
> 
56281 ripley 124
> ## Use bounded optimization
125
> ## The lower bounds are really > 0,
126
> ## but we use >=0 to stress-test profiling
88779 pd 127
> (fit2 <- mle(mll2, lower = c(0, 0)))
56186 murdoch 128
 
129
Call:
88779 pd 130
mle(minuslogl = mll2, lower = c(0, 0))
56186 murdoch 131
 
132
Coefficients:
133
   ymax   xhalf 
134
24.9994  3.0558 
61164 ripley 135
> plot(profile(fit2), absVal = FALSE)
56186 murdoch 136
> 
77937 pd 137
> ## A better parametrization:
88779 pd 138
> mll3 <- function(lymax = log(15), lxhalf = log(6))
88768 pd 139
+     with(ec50, -sum(stats::dpois(y, lambda = exp(lymax)/(1+x/exp(lxhalf)), log = TRUE)))
88779 pd 140
> (fit3 <- mle(mll3))
56186 murdoch 141
 
142
Call:
88779 pd 143
mle(minuslogl = mll3)
56186 murdoch 144
 
145
Coefficients:
146
 lymax lxhalf 
147
3.2189 1.1170 
148
> plot(profile(fit3), absVal = FALSE)
149
> exp(confint(fit3))
150
Profiling...
151
         2.5 %  97.5 %
152
lymax  17.8815 34.6186
153
lxhalf  1.6615  6.4794
154
> 
77937 pd 155
> # Regression tests for bounded cases (this was broken in R 3.x)
88779 pd 156
> fit4 <- mle(mll1, lower = c(0, 4)) # has max on boundary
77675 ripley 157
> confint(fit4)
158
Profiling...
159
       2.5 %  97.5 %
160
ymax  17.446 26.5081
161
xhalf     NA  6.9109
162
> 
163
> ## direct check that fixed= and constraints work together
88779 pd 164
> mle(mll1, lower = c(0, 4), fixed=list(ymax=23)) # has max on boundary
77675 ripley 165
 
166
Call:
88779 pd 167
mle(minuslogl = mll1, fixed = list(ymax = 23), lower = c(0, 4))
77675 ripley 168
 
169
Coefficients:
170
 ymax xhalf 
171
   23     4 
172
> 
77805 pd 173
> ## Linear regression using MLE
88768 pd 174
> lr <- data.frame(
175
+ x = 1:10, 
176
+ y = c(0.48, 2.24, 2.22, 5.15, 4.64, 5.53, 7, 8.8, 7.67, 9.23))
77805 pd 177
> 
88768 pd 178
> 
77805 pd 179
> LM_mll <- function(formula, data = environment(formula))
180
+ {
77813 pd 181
+      y <- model.response(model.frame(formula, data))
77805 pd 182
+      X <- model.matrix(formula, data)
183
+      b0 <- numeric(NCOL(X))
184
+      names(b0) <- colnames(X)
185
+      function(b=b0, sigma=1)
186
+          -sum(dnorm(y, X %*% b, sigma, log=TRUE))
187
+ }
188
> 
88779 pd 189
> mll_lm <- LM_mll(y ~ x, lr)
77805 pd 190
> 
88768 pd 191
> summary(lm(y~x, data=lr)) # for comparison -- notice variance bias in MLE
77805 pd 192
 
193
Call:
88768 pd 194
lm(formula = y ~ x, data = lr)
77805 pd 195
 
196
Residuals:
197
   Min     1Q Median     3Q    Max 
198
-0.937 -0.500 -0.211  0.278  1.273 
199
 
200
Coefficients:
201
            Estimate Std. Error t value Pr(>|t|)    
202
(Intercept)   0.0927     0.5376    0.17     0.87    
203
x             0.9461     0.0866   10.92  4.4e-06 ***
204
---
205
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
206
 
207
Residual standard error: 0.787 on 8 degrees of freedom
208
Multiple R-squared:  0.937,	Adjusted R-squared:  0.929 
209
F-statistic:  119 on 1 and 8 DF,  p-value: 4.39e-06
210
 
88779 pd 211
> summary(mle(mll_lm, lower=c(-Inf,-Inf, 0.01)))
77805 pd 212
Maximum likelihood estimation
213
 
214
Call:
88779 pd 215
mle(minuslogl = mll_lm, lower = c(-Inf, -Inf, 0.01))
77805 pd 216
 
217
Coefficients:
218
              Estimate Std. Error
219
b.(Intercept) 0.092667   0.480869
220
b.x           0.946061   0.077499
221
sigma         0.703919   0.157400
222
 
223
-2 log L: 21.357 
88779 pd 224
> summary(mle(mll_lm, lower=list(sigma = 0.01))) # alternative specification
77805 pd 225
Maximum likelihood estimation
226
 
227
Call:
88779 pd 228
mle(minuslogl = mll_lm, lower = list(sigma = 0.01))
77805 pd 229
 
230
Coefficients:
231
              Estimate Std. Error
232
b.(Intercept) 0.092667   0.480869
233
b.x           0.946061   0.077499
234
sigma         0.703919   0.157400
235
 
236
-2 log L: 21.357 
237
> 
88779 pd 238
> confint(mle(mll_lm, lower=list(sigma = 0.01)))
77805 pd 239
Profiling...
240
                 2.5 % 97.5 %
241
b.(Intercept) -0.94831 1.1336
242
b.x            0.77829 1.1138
243
sigma          0.48017 1.1755
88779 pd 244
> plot(profile(mle(mll_lm, lower=list(sigma = 0.01))))
77805 pd 245
> 
77937 pd 246
> Binom_mll <- function(x, n)
247
+ {
248
+     force(x); force(n) ## beware lazy evaluation
249
+     function(p=.5) -dbinom(x, n, p, log=TRUE)
250
+ }
77805 pd 251
> 
77937 pd 252
> ## Likelihood functions for different x.
253
> ## This code goes wrong, if force(x) is not used in Binom_mll:
254
> 
255
> curve(Binom_mll(0, 10)(p), xname="p", ylim=c(0, 10))
256
> mll_list <- list(10)
257
> for (x in 1:10)
258
+     mll_list[[x]] <- Binom_mll(x, 10)
259
> for (mll in mll_list)
260
+     curve(mll(p), xname="p", add=TRUE)
261
> 
262
> mll <- Binom_mll(4,10)
263
> mle(mll, lower = 1e-16, upper = 1-1e-16) # limits must be inside (0,1)
264
 
265
Call:
266
mle(minuslogl = mll, lower = 1e-16, upper = 1 - 1e-16)
267
 
268
Coefficients:
269
  p 
270
0.4 
271
> 
272
> ## Boundary case: This works, but fails if limits are set closer to 0 and 1  
273
> mll <- Binom_mll(0, 10)
274
> mle(mll, lower=.005, upper=.995)
275
 
276
Call:
277
mle(minuslogl = mll, lower = 0.005, upper = 0.995)
278
 
279
Coefficients:
280
    p 
281
0.005 
282
> 
283
> ## Not run: 
284
> ##D ## We can use limits closer to the boundaries if we use the
285
> ##D ## drop-in replacement optimr() from the optimx package.
286
> ##D 
287
> ##D mle(mll, lower = 1e-16, upper = 1-1e-16, optim=optimx::optimr)
288
> ## End(Not run)
289
> 
290
> 
56186 murdoch 291
> options(od)
292
> 
293
> 
294
> 
295
> cleanEx()
296
> nameEx("update-methods")
297
> ### * update-methods
298
> 
299
> flush(stderr()); flush(stdout())
300
> 
301
> ### Name: update-methods
302
> ### Title: Methods for Function 'update' in Package 'stats4'
303
> ### Aliases: update-methods update,ANY-method update,mle-method
304
> ### Keywords: methods
305
> 
306
> ### ** Examples
307
> 
308
> x <- 0:10
309
> y <- c(26, 17, 13, 12, 20, 5, 9, 8, 5, 4, 8)
61164 ripley 310
> ll <- function(ymax = 15, xhalf = 6)
311
+     -sum(stats::dpois(y, lambda = ymax/(1+x/xhalf), log = TRUE))
56186 murdoch 312
> fit <- mle(ll)
59447 ripley 313
Warning in stats::dpois(y, lambda = ymax/(1 + x/xhalf), log = TRUE) :
314
  NaNs produced
56186 murdoch 315
> ## note the recorded call contains ..1, a problem with S4 dispatch
61164 ripley 316
> update(fit, fixed = list(xhalf = 3))
56186 murdoch 317
 
318
Call:
319
mle(minuslogl = ll, fixed = ..1)
320
 
321
Coefficients:
322
    ymax    xhalf 
323
25.19609  3.00000 
324
> 
325
> 
326
> 
327
> ### * <FOOTER>
328
> ###
73819 hornik 329
> cleanEx()
62439 ripley 330
> options(digits = 7L)
61787 ripley 331
> base::cat("Time elapsed: ", proc.time() - base::get("ptime", pos = 'CheckExEnv'),"\n")
88779 pd 332
Time elapsed:  0.574 0.015 0.593 0 0 
56186 murdoch 333
> grDevices::dev.off()
334
null device 
335
          1 
336
> ###
337
> ### Local variables: ***
338
> ### mode: outline-minor ***
339
> ### outline-regexp: "\\(> \\)?### [*]+" ***
340
> ### End: ***
341
> quit('no')