> # test.unusual.vars.R: test unusual variable names, and unusual formulas
> #
> # This file was initially created for plotmo 3.6.0 (Sep 2020)
> # ALso tests the naken() func introduced in plotmo 3.6.0 and earth 5.2.0 (Sep 2020)
> 
> source("test.prolog.R")
> library(earth)
Loading required package: Formula
Loading required package: plotmo
Loading required package: plotrix
> data(ozone1)
> data(etitanic)
> options(warn=1) # print warnings as they occur
> 
> check.naken <- function(s, expected, trace=0)
+ {
+     nude <- plotmo:::naken.formula.string(s, trace=trace)
+     printf("%-60.60s %-s\n", s, nude)
+     stopifnot(nude == expected)
+ }
> printf("=== check naken.formula.string\n")
=== check naken.formula.string
> 
> # edge cases
> check.naken("", "")
                                                             
> check.naken(" ", "")
                                                             
> check.naken("y~", "y ~ ")
y~                                                           y ~ 
> check.naken("y~ ", "y ~ ")
y~                                                           y ~ 
> check.naken("y ~ ", "y ~ ")
y ~                                                          y ~ 
> check.naken("y ~  ", "y ~ ")
y ~                                                          y ~ 
> check.naken(" y ~  ", "y ~ ")
 y ~                                                         y ~ 
> check.naken("[", "[", trace=2)
naked formula is the same
[                                                            [
> check.naken("`", "`", trace=2)
naked formula is the same
`                                                            `
> # standard formulas
> check.naken("x", "x")
x                                                            x
> check.naken("x1", "x1")
x1                                                           x1
> check.naken("y ~ x1 : x2 + x3", "y ~ x1 + x2 + x3", trace=2)
naked formula is y ~ x1 + x2 + x3
y ~ x1 : x2 + x3                                             y ~ x1 + x2 + x3
> check.naken("y ~ x1 + x2 - x3", "y ~ x1 + x2 + x3", trace=2) # TODO "-" is treated as a "+"
naked formula is y ~ x1 + x2 + x3
y ~ x1 + x2 - x3                                             y ~ x1 + x2 + x3
> check.naken("y ~ .-x3", "y ~ . + x3")
y ~ .-x3                                                     y ~ . + x3
> check.naken("cbind(damage, 6-damage)~temp", "cbind(damage, 6-damage) ~ temp", trace=2)
naked formula is the same
cbind(damage, 6-damage)~temp                                 cbind(damage, 6-damage) ~ temp
> check.naken("depIndex~q_4 + q_2102+q_2104  +q_3105+  q_3106", "depIndex ~ q_4 + q_2102 + q_2104 + q_3105 + q_3106")
depIndex~q_4 + q_2102+q_2104  +q_3105+  q_3106               depIndex ~ q_4 + q_2102 + q_2104 + q_3105 + q_3106
> check.naken("doy ~ (vh+wind+humidity)^2", "doy ~ vh + wind + humidity")
doy ~ (vh+wind+humidity)^2                                   doy ~ vh + wind + humidity
> check.naken("doy ~ s(wind) + s(humidity,wind) + s(vh)", "doy ~ wind + humidity + vh")
doy ~ s(wind) + s(humidity,wind) + s(vh)                     doy ~ wind + humidity + vh
> check.naken("log(doy) ~ I(vh*wind) + I(humidity*temp)+log(doy)", "log(doy) ~ vh + wind + humidity + temp + doy")
log(doy) ~ I(vh*wind) + I(humidity*temp)+log(doy)            log(doy) ~ vh + wind + humidity + temp + doy
> check.naken("log(doy)~vh+wind+humidity+I(wind*humidity)+temp+log(ibh)", "log(doy) ~ vh + wind + humidity + temp + ibh", trace=2)
naked formula is log(doy) ~ vh + wind + humidity + temp + ibh
log(doy)~vh+wind+humidity+I(wind*humidity)+temp+log(ibh)     log(doy) ~ vh + wind + humidity + temp + ibh
> check.naken("O3 ~ s(humidity)+s(temp)+s(ibt)+s(temp,ibt)", "O3 ~ humidity + temp + ibt")
O3 ~ s(humidity)+s(temp)+s(ibt)+s(temp,ibt)                  O3 ~ humidity + temp + ibt
> check.naken("Ozone^(1/3) ~ lo(Solar.R) + lo(Wind, Temp)", "Ozone^(1/3) ~ Solar.R + Wind + Temp")
Ozone^(1/3) ~ lo(Solar.R) + lo(Wind, Temp)                   Ozone^(1/3) ~ Solar.R + Wind + Temp
> check.naken("Volume~(Girth*Height2)-Height", "Volume ~ Girth + Height2 + Height")
Volume~(Girth*Height2)-Height                                Volume ~ Girth + Height2 + Height
> check.naken("y ~ s(x) + s(x,z1)", "y ~ x + z1")
y ~ s(x) + s(x,z1)                                           y ~ x + z1
> check.naken("y~s(x0,x1,k=12)+s(x2)+s(x3,k=20,fx=20)", "y ~ x0 + x1 + x2 + x3")
y~s(x0,x1,k=12)+s(x2)+s(x3,k=20,fx=20)                       y ~ x0 + x1 + x2 + x3
> check.naken("y~x[,1]+x[,2]", "y ~ x[,1] + x[,2]")
y~x[,1]+x[,2]                                                y ~ x[,1] + x[,2]
> check.naken("y~x[,1]+x[,my.list$j]", "y ~ x[,1] + x[,my.list$j]")
y~x[,1]+x[,my.list$j]                                        y ~ x[,1] + x[,my.list$j]
> check.naken("y~x[,i]+x[,2]", "y ~ x[,i] + x[,2]")
y~x[,i]+x[,2]                                                y ~ x[,i] + x[,2]
> check.naken("Salary~Hitters[,1]", "Salary ~ Hitters[,1]", trace=2)
naked formula is the same
Salary~Hitters[,1]                                           Salary ~ Hitters[,1]
> check.naken("Salary~Hitters[,-1]", "Salary ~ Hitters[,-1]", trace=2)
naked formula is the same
Salary~Hitters[,-1]                                          Salary ~ Hitters[,-1]
> check.naken("Salary~Hitters[,c(1,2)]", "Salary ~ Hitters[,c(1,2)]", trace=2)
naked formula is the same
Salary~Hitters[,c(1,2)]                                      Salary ~ Hitters[,c(1,2)]
> check.naken("Salary~Hitters[,1:2]", "Salary ~ Hitters[,1:2]")
Salary~Hitters[,1:2]                                         Salary ~ Hitters[,1:2]
> check.naken("Salary~Hitters[,c(1,2)]", "Salary ~ Hitters[,c(1,2)]", trace=2)
naked formula is the same
Salary~Hitters[,c(1,2)]                                      Salary ~ Hitters[,c(1,2)]
> # nested brackets
> check.naken("y ~ x1[[2]] + x1[[3]]", "y ~ x1[[2]] + x1[[3]]")
y ~ x1[[2]] + x1[[3]]                                        y ~ x1[[2]] + x1[[3]]
> check.naken("y[ , 1 ] ~ x1[[2]]", "y[ , 1 ] ~ x1[[2]]")
y[ , 1 ] ~ x1[[2]]                                           y[ , 1 ] ~ x1[[2]]
> check.naken("y ~ x0[,nonesuch1 + x1[nsuch2^2  +   3  ]]", "y ~ x0[,nonesuch1 + x1[nsuch2^2  +   3  ]]")
y ~ x0[,nonesuch1 + x1[nsuch2^2  +   3  ]]                   y ~ x0[,nonesuch1 + x1[nsuch2^2  +   3  ]]
> check.naken("y ~ x0[1,x2[3]] + x4[[5]] + x6[ x7[, 8], x9[ ,x10[11] ], drop=x12[13]]", "y ~ x0[1,x2[3]] + x4[[5]] + x6[ x7[, 8], x9[ ,x10[11] ], drop=x12[13]]")
y ~ x0[1,x2[3]] + x4[[5]] + x6[ x7[, 8], x9[ ,x10[11] ], dro y ~ x0[1,x2[3]] + x4[[5]] + x6[ x7[, 8], x9[ ,x10[11] ], drop=x12[13]]
> # backquotes
> check.naken("y ~ `a b c10` + `def`", "y ~ `a b c10` + `def`")
y ~ `a b c10` + `def`                                        y ~ `a b c10` + `def`
> check.naken("`y` ~ `a b c10` + `def` + s(sqrt(`x 1`))", "`y` ~ `a b c10` + `def` + `x 1`")
`y` ~ `a b c10` + `def` + s(sqrt(`x 1`))                     `y` ~ `a b c10` + `def` + `x 1`
> # without a response
> check.naken("x1 + x[,1] + `x3`", "x1 + x[,1] + `x3`")
x1 + x[,1] + `x3`                                            x1 + x[,1] + `x3`
> check.naken("Salary~Hitters[,c(1,2)]+sqrt(x)", "Salary ~ Hitters[,c(1,2)] + x")
Salary~Hitters[,c(1,2)]+sqrt(x)                              Salary ~ Hitters[,c(1,2)] + x
> check.naken("Salary~Hitters[,c(1,2)]+sqrt(x)+x99", "Salary ~ Hitters[,c(1,2)] + x + x99")
Salary~Hitters[,c(1,2)]+sqrt(x)+x99                          Salary ~ Hitters[,c(1,2)] + x + x99
> check.naken("Salary~x1+x2+`x6`+x3", "Salary ~ x1 + x2 + `x6` + x3")
Salary~x1+x2+`x6`+x3                                         Salary ~ x1 + x2 + `x6` + x3
> check.naken("x[,c(1,2)] + x[,3]", "x[,c(1,2)] + x[,3]")
x[,c(1,2)] + x[,3]                                           x[,c(1,2)] + x[,3]
> check.naken("x[,1] + x[,2] + x[,3] + x[,29] + x[,-14]", "x[,1] + x[,2] + x[,3] + x[,29] + x[,-14]")
x[,1] + x[,2] + x[,3] + x[,29] + x[,-14]                     x[,1] + x[,2] + x[,3] + x[,29] + x[,-14]
> check.naken("x[,c(1,2)] + x[,3] + x[,5:6] + x[,-1]", "x[,c(1,2)] + x[,3] + x[,5:6] + x[,-1]")
x[,c(1,2)] + x[,3] + x[,5:6] + x[,-1]                        x[,c(1,2)] + x[,3] + x[,5:6] + x[,-1]
> check.naken("log(y) ~ x9 + ns(x2,4) + s(x3,x4,df=4) + x5:sqrt(x6)", "log(y) ~ x9 + x2 + x3 + x4 + x5 + x6")
log(y) ~ x9 + ns(x2,4) + s(x3,x4,df=4) + x5:sqrt(x6)         log(y) ~ x9 + x2 + x3 + x4 + x5 + x6
> check.naken("log(y) ~ x9 + sqrt(x6) + ns(x2,4) + s(x3,x4,df=4) + x5", "log(y) ~ x9 + x6 + x2 + x3 + x4 + x5")
log(y) ~ x9 + sqrt(x6) + ns(x2,4) + s(x3,x4,df=4) + x5       log(y) ~ x9 + x6 + x2 + x3 + x4 + x5
> check.naken("x[,1] + sqrt(x2) + 2.34e6 + 1", "x[,1] + x2 + 1")
x[,1] + sqrt(x2) + 2.34e6 + 1                                x[,1] + x2 + 1
> 
> printf("\n=== test problem in lm() formula with -nonesuch ===\n")

=== test problem in lm() formula with -nonesuch ===
> 
> # Using "-nonesuch" in a "." formula (where nonesuch is a non-existent variable name)
> # causes the following error in stats::terms.formula (called via model.frame.default)
> # Error in terms.formula(formula, data = data) :  (converted from warning)
> #   'varlist' has changed (from nvar=3) to new 4 after EncodeVars() -- should no longer happen!
> options(warn=2) # treat warnings as errors
> expect.err(try(lm(formula = Volume ~ . - nonesuch, data=trees)),
+            "'varlist' has changed (from nvar=3) to new 4 after EncodeVars() -- should no longer happen!")
Error in terms.formula(formula, data = data) : 
  (converted from warning) 'varlist' has changed (from nvar=3) to new 4 after EncodeVars() -- should no longer happen!
Got expected error from try(lm(formula = Volume ~ . - nonesuch, data = trees))
> options(warn=1) # print warnings as they occur
> 
> printf("\n=== test variables names with spaces in them ===\n")

=== test variables names with spaces in them ===
> spaced.trees <- trees
> stopifnot(colnames(spaced.trees) == c("Girth", "Height", "Volume")) # sanity check
> colnames(spaced.trees) <- c("Girth extra", "Height 999", "Volume") # put spaces in the names
> 
> lm.spaced.trees <- lm(Volume~., data=spaced.trees)
> options(warn=2)
> expect.err(try(plotmo(lm.spaced.trees)),
+            "Cannot determine which variables to plot in degree2 plots")
Error : (converted from warning) Cannot determine which variables to plot in degree2 plots (use all2=TRUE?)
         Confused by variable name "`Girth extra`"
Got expected error from try(plotmo(lm.spaced.trees))
> options(warn=1)
> plotmo(lm.spaced.trees)            # warning, but still plots (no degree2 plots)
Warning: Cannot determine which variables to plot in degree2 plots (use all2=TRUE?)
         Confused by variable name "`Girth extra`"
 plotmo grid:    Girth extra Height 999
                        12.9         76
> plotmo(lm.spaced.trees, all2=TRUE) # no warning
 plotmo grid:    Girth extra Height 999
                        12.9         76
> 
> earth.spaced.trees <- earth(Volume~. , data=spaced.trees, degree=2)
> plotmo(earth.spaced.trees)
 plotmo grid:    Girth extra Height 999
                        12.9         76
> cat("\nevimp(earth.spaced.trees)\n")

evimp(earth.spaced.trees)
> print(evimp(earth.spaced.trees))
              nsubsets   gcv    rss
`Girth extra`        3 100.0  100.0
`Height 999`         1  10.9   11.9
> 
> printf("\n=== test non standard variable names and use of earth's bx matrix ===\n")

=== test non standard variable names and use of earth's bx matrix ===
> emod <- earth(survived~., data=etitanic, degree=2)
> plotmo(emod)
 plotmo grid:    pclass  sex age sibsp parch
                    3rd male  28     0     0
> cat("\nevimp(emod)\n")

evimp(emod)
> print(evimp(emod))
          nsubsets   gcv    rss
sexmale          7 100.0  100.0
pclass3rd        6  56.4   58.4
pclass2nd        5  46.3   48.4
age              4  38.0   40.2
sibsp            3  26.6   29.2
> bx <- emod$bx
> bx.df <- as.data.frame(bx[,-1])  # -1 to drop intercept
> bx.df$survived <- etitanic$survived
> # following gsub make it a bit easier to see what's going on
> # because the next call to earth also creates hinge functions
> # (so we end up with nested hinge functions)
> colnames(bx.df) <- gsub("h(", "H(", colnames(bx.df), fixed=TRUE)
> lm.bx    <- lm(survived ~ ., data=bx.df)
> set.seed(2020)
> earth.bx <- earth(survived ~ ., data=bx.df, degree=2)
> printf("\nsummary(earth.bx):\n")

summary(earth.bx):
> print(summary(earth.bx))
Call: earth(formula=survived~., data=bx.df, degree=2)

                                             coefficients
(Intercept)                                    2.05782826
sexmale                                       -0.60749103
pclass3rd                                     -1.27902837
pclass2nd * sexmale                           -0.23995151
pclass3rd * sexmale                            0.25312923
h(4-sexmale * H(16-age))                      -0.20886491
h(2-pclass3rd * H(4-sibsp))                   -0.14508261
pclass3rd * h(5-sexmale * H(16-age))           0.09290713
h(pclass3rd * H(4-sibsp)-2) * h(1-H(age-32))   0.07452385

Selected 9 of 17 terms, and 7 of 7 predictors
Termination condition: Reached nk 21
Importance: sexmale, pclass3rd, `sexmale*H(16-age)`, `pclass2nd*sexmale`, ...
Number of terms at each degree of interaction: 1 6 2
GCV 0.1385367    RSS 139.1493    GRSq 0.4276272    RSq 0.4493265
> printf("\nevimp(earth.bx):\n")

evimp(earth.bx):
> print(evimp(earth.bx))
                       nsubsets   gcv    rss
sexmale                       8 100.0  100.0
pclass3rd                     7  57.5   59.7
`sexmale*H(16-age)`           5  39.5   42.0
`pclass2nd*sexmale`           5  39.5   42.0
`pclass3rd*sexmale`           4  35.7   38.0
`pclass3rd*H(4-sibsp)`        4  30.5   33.3
`H(age-32)`                   3  24.9   27.6
> plot(earth.bx, info=TRUE)
> plotmo(lm.bx) # Warning: Cannot determine which variables to plot in degree2 plots
Warning: Cannot determine which variables to plot in degree2 plots (use all2=TRUE?)
         Confused by variable name "`sexmale*H(16-age)`"
 plotmo grid:    sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale
                       1         0                 0                 0
 pclass3rd*H(4-sibsp) pclass3rd*sexmale H(age-32)
                    0                 0         0
> plotmo(lm.bx, all2=TRUE, SHOWCALL=TRUE)
 plotmo grid:    sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale
                       1         0                 0                 0
 pclass3rd*H(4-sibsp) pclass3rd*sexmale H(age-32)
                    0                 0         0
> plotmo(earth.bx, pmethod="partdep", trace=2)
plotmo trace 2: plotmo(object=earth.bx, pmethod="partdep", trace=2)
--get.model.env for object with class earth
object call is earth(formula=survived~., data=bx.df, degree=2)
using the environment saved in $terms of the earth model: R_GlobalEnv
--plotmo_prolog for earth object 'earth.bx'
--plotmo_x for earth object

get.object.x:
object$x is NULL (and it has no colnames)

object call is earth(formula=survived~., data=bx.df, degree=2)

get.x.from.model.frame:
formula(object) is survived ~ sexmale + pclass3rd + `sexmale*H(16-age)` + `p...
naked formula is the same
formula is valid, now looking for data for the model.frame
object$model is NULL (and it has no colnames)
object$data is NULL (and it has no colnames)
argument 2 of the call is 'data'
eval(call$data, R_GlobalEnv)
call$data is usable and has column names sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale pclass3rd*H(4-sibsp) pclass3rd*sexmale H(ag...
na.action(object) is "na.fail"
stats::model.frame(survived ~ sexmale + pclass3rd + `sex..., data=call$data, na.action="na.fail")
x=model.frame[,-1] is usable and has column names sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale pclass3rd*H(4-sibsp) pclass3rd*sexmale H(ag...
setting check.naked=FALSE because backtick in formula
plotmo_x returned[1046,7]:
     sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale pclass3rd*H(4-sibsp)
1          0         0            0.0000                 0                    0
2          1         0           15.0833                 0                    0
3          0         0            0.0000                 0                    0
...        1         0            0.0000                 0                    0
1046       1         1            0.0000                 0                    4
     pclass3rd*sexmale H(age-32)
1                    0         0
2                    0         0
3                    0         0
...                  0         0
1046                 1         0

----Metadata: plotmo_predict with nresponse=NULL and newdata=NULL
calling predict.earth with NULL newdata
stats::predict(earth.object, NULL, type="response")
predict returned[1046,1]:
      survived
1    0.9322034
2    1.1601720
3    0.9322034
...  0.3247124
1046 0.2025618
predict after processing with nresponse=NULL is [1046,1]:
      survived
1    0.9322034
2    1.1601720
3    0.9322034
...  0.3247124
1046 0.2025618

----Metadata: plotmo_fitted with nresponse=NULL
stats::fitted(object=earth.object)
fitted(object) returned[1046,1]:
      survived
1    0.9322034
2    1.1601720
3    0.9322034
...  0.3247124
1046 0.2025618
fitted(object) after processing with nresponse=NULL is [1046,1]:
      survived
1    0.9322034
2    1.1601720
3    0.9322034
...  0.3247124
1046 0.2025618

----Metadata: plotmo_y with nresponse=NULL
--plotmo_y with nresponse=NULL for earth object

get.object.y:
object$y is NULL (and it has no colnames)

object call is earth(formula=survived~., data=bx.df, degree=2)

get.y.from.model.frame:
formula(object) is survived ~ sexmale + pclass3rd + `sexmale*H(16-age)` + `p...
formula is valid, now looking for data for the model.frame
object$model is NULL (and it has no colnames)
object$data is NULL (and it has no colnames)
argument 2 of the call is 'data'
eval(call$data, R_GlobalEnv)
call$data is usable and has column names sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale pclass3rd*H(4-sibsp) pclass3rd*sexmale H(ag...
na.action(object) is "na.fail"
stats::model.frame(survived ~ sexmale + pclass3rd + `sex..., data=call$data, na.action="na.fail")
y=model.frame[,1] is usable and has column name survived
plotmo_y returned[1046,1]:
     survived
1           1
2           1
3           0
...         0
1046        0
plotmo_y after processing with nresponse=NULL is [1046,1]:
     survived
1           1
2           1
3           0
...         0
1046        0
converted nresponse=NA to nresponse=1
nresponse=1 (was NA) ncol(fitted) 1 ncol(predict) 1 ncol(y) 1

----Metadata: plotmo_y with nresponse=1
--plotmo_y with nresponse=1 for earth object

get.object.y:
object$y is NULL (and it has no colnames)

object call is earth(formula=survived~., data=bx.df, degree=2)

get.y.from.model.frame:
formula(object) is survived ~ sexmale + pclass3rd + `sexmale*H(16-age)` + `p...
formula is valid, now looking for data for the model.frame
object$model is NULL (and it has no colnames)
object$data is NULL (and it has no colnames)
argument 2 of the call is 'data'
eval(call$data, R_GlobalEnv)
call$data is usable and has column names sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale pclass3rd*H(4-sibsp) pclass3rd*sexmale H(ag...
na.action(object) is "na.fail"
stats::model.frame(survived ~ sexmale + pclass3rd + `sex..., data=call$data, na.action="na.fail")
y=model.frame[,1] is usable and has column name survived
got model response from model.frame(survived ~ sexmale + pclass3rd + `sex...,
                                    data=call$data, na.action="na.fail")
plotmo_y returned[1046,1]:
     survived
1           1
2           1
3           0
...         0
1046        0
plotmo_y after processing with nresponse=1 is [1046,1]:
     survived
1           1
2           1
3           0
...         0
1046        0
got response name "survived" from yhat
got resp.levs from object$levels
response levels: 0 1

----Metadata: done

number of x values: sexmale 2 pclass3rd 2 sexmale*H(16-age) 24 pclass2nd*sexm...

----plotmo_singles for earth object
singles: 1 sexmale, 2 pclass3rd, 3 sexmale*H(16-age), 4 pclass2nd*sexmale, 5 pclass3rd*H(4-sibsp), 6 pclass3rd*sexmale 

----plotmo_pairs for earth object
pairs:
     [,1]                     [,2]                 
[1,] "2 pclass3rd"            "3 sexmale*H(16-age)"
[2,] "5 pclass3rd*H(4-sibsp)" "7 H(age-32)"        

graphics::par(mfrow=c(3,3), mgp=c(1.5,0.4,0), tcl=-0.3, font.main=2,
              mar=c(3,2,1.2,0.8), oma=c(0,0,3,0), cex.main=1.2, cex.lab=1,
              cex.axis=1, cex=0.66)

----Figuring out ylim
--get.ylim.by.dummy.plots
--plot.degree1(draw.plot=FALSE)
degree1 plot1 (pmethod "partdep") variable sexmale
calculating partdep for sexmale
newdata[2092,7]:
       sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale
1            0         0            0.0000                 0
2            0         0           15.0833                 0
3            0         0            0.0000                 0
...          0         0            0.0000                 0
1046.1       1         1            0.0000                 0
       pclass3rd*H(4-sibsp) pclass3rd*sexmale H(age-32)
1                         0                 0         0
2                         0                 0         0
3                         0                 0         0
...                       0                 0         0
1046.1                    4                 1         0
stats::predict(earth.object, data.frame[2092,7], type="response")
predict returned[2092,1]:
      survived
1    0.9322034
2    1.7676630
3    0.9322034
...  0.9322034
2092 0.2025618
predict after processing with nresponse=1 is [2092,1]:
      survived
1    0.9322034
2    1.7676630
3    0.9322034
...  0.9322034
2092 0.2025618

Reducing trace level for subsequent degree1 plots
degree1 plot2 (pmethod "partdep") variable pclass3rd
calculating partdep for pclass3rd 
degree1 plot3 (pmethod "partdep") variable sexmale*H(16-age)
calculating partdep for sexmale*H(16-age) 
degree1 plot4 (pmethod "partdep") variable pclass2nd*sexmale
calculating partdep for pclass2nd*sexmale 
degree1 plot5 (pmethod "partdep") variable pclass3rd*H(4-sibsp)
calculating partdep for pclass3rd*H(4-sibsp) 
degree1 plot6 (pmethod "partdep") variable pclass3rd*sexmale
calculating partdep for pclass3rd*sexmale 
--plot.degree2(draw.plot=FALSE)
degree2 plot1 (pmethod "partdep") variables pclass3rd:sexmale*H(16-age)
calculating partdep for pclass3rd:sexmale*H(16-age) 
1234newdata[20920,7]:
        sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale
1             0         0            0.0000                 0
2             1         0            0.0000                 0
3             0         0            0.0000                 0
...           1         0            0.0000                 0
1046.19       1         0           15.6667                 0
        pclass3rd*H(4-sibsp) pclass3rd*sexmale H(age-32)
1                          0                 0         0
2                          0                 0         0
3                          0                 0         0
...                        0                 0         0
1046.19                    4                 1         0
stats::predict(earth.object, data.frame[20920,7], type="response")
predict returned[20920,1]:
       survived
1     0.9322034
2     0.3247124
3     0.9322034
...   0.3247124
20920 1.8525142
predict after processing with nresponse=1 is [20920,1]:
       survived
1     0.9322034
2     0.3247124
3     0.9322034
...   0.3247124
20920 1.8525142
56790
Reducing trace level for subsequent degree2 plots
degree2 plot2 (pmethod "partdep") variables pclass3rd*H(4-sibsp):H(age-32)
calculating partdep for pclass3rd*H(4-sibsp):H(age-32) 
1newdata[20920,7]:
        sexmale pclass3rd sexmale*H(16-age) pclass2nd*sexmale
1             0         0            0.0000                 0
2             1         0           15.0833                 0
3             0         0            0.0000                 0
...           1         0            0.0000                 0
1046.19       1         1            0.0000                 0
        pclass3rd*H(4-sibsp) pclass3rd*sexmale H(age-32)
1                          0                 0         0
2                          0                 0         0
3                          0                 0         0
...                        0                 0         0
1046.19                    0                 1        48
stats::predict(earth.object, data.frame[20920,7], type="response")
predict returned[20920,1]:
        survived
1      0.9322034
2      1.1601720
3      0.9322034
...    0.3247124
20920 -0.2366511
predict after processing with nresponse=1 is [20920,1]:
        survived
1      0.9322034
2      1.1601720
3      0.9322034
...    0.3247124
20920 -0.2366511
234567890
--done get.ylim.by.dummy.plots

ylim c(-0.04329, 1.607)    clip TRUE

--plot.degree1(draw.plot=TRUE)
graphics::plot.default(x=c(0,0.5,0.5,1), y=c(0.7904,0.7904...), type="n",
                       main="1 sexmale", xlab="", ylab="", xaxt="s", yaxt="s",
                       xlim=c(-0.1,1.1), ylim=c(-0.0433,1.607))
--plot.degree2(draw.plot=TRUE)
persp(pclass3rd:sexmale*H(16-age)) theta 55
persp(pclass3rd*H(4-sibsp):H(age-32)) theta 235
> 
> printf("\n=== put spaces into the column names of bx (for both response and predictors) ===\n")

=== put spaces into the column names of bx (for both response and predictors) ===
> spaced.bx <- bx.df
> colnames(spaced.bx) <- gsub("-", " - ", colnames(spaced.bx), fixed=TRUE)
> colnames(spaced.bx)[colnames(spaced.bx) == "survived"] <- "Survived = YES"
> printf("\nhead(spaced.bx):\n")

head(spaced.bx):
> print(head(spaced.bx))
  sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
1       0         0              0.0000                 0
2       1         0             15.0833                 0
3       0         0              0.0000                 0
4       1         0              0.0000                 0
5       0         0              0.0000                 0
6       1         0              0.0000                 0
  pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32) Survived = YES
1                      0                 0           0              1
2                      0                 0           0              1
3                      0                 0           0              0
4                      0                 0           0              0
5                      0                 0           0              0
6                      0                 0          16              1
> 
> lm.spaced.bx    <- lm(`Survived = YES` ~ ., data=spaced.bx)
> 
> set.seed(2020)
> earth.spaced.bx <- earth(`Survived = YES` ~ ., data=spaced.bx, degree=2, trace=.5,
+                          nfold=4, ncross=3, varmod.method="lm", pmethod="cv")
Preliminary model with pmethod="backward": GRSq 0.428 RSq 0.449 nterms 9
CV fold  1.1  CVRSq  0.402   n.oof  779 26%   n.infold.nz  320 41%   n.oof.nz  107 40%
CV fold  1.2  CVRSq  0.424   n.oof  785 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  1.3  CVRSq  0.418   n.oof  786 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  1.4  CVRSq  0.433   n.oof  788 25%   n.infold.nz  321 41%   n.oof.nz  106 41%
CV fold  2.1  CVRSq  0.470   n.oof  784 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  2.2  CVRSq  0.417   n.oof  775 26%   n.infold.nz  320 41%   n.oof.nz  107 39%
CV fold  2.3  CVRSq  0.412   n.oof  787 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  2.4  CVRSq  0.421   n.oof  792 24%   n.infold.nz  321 41%   n.oof.nz  106 42%
CV fold  3.1  CVRSq  0.385   n.oof  777 26%   n.infold.nz  320 41%   n.oof.nz  107 40%
CV fold  3.2  CVRSq  0.429   n.oof  792 24%   n.infold.nz  320 40%   n.oof.nz  107 42%
CV fold  3.3  CVRSq  0.461   n.oof  780 25%   n.infold.nz  320 41%   n.oof.nz  107 40%
CV fold  3.4  CVRSq  0.377   n.oof  789 25%   n.infold.nz  321 41%   n.oof.nz  106 41%
CV all        CVRSq  0.421                    n.infold.nz  427 41%
Final model with pmethod="cv": GRSq 0.425 RSq 0.452 nterms selected by cv 11

varmod method="lm" rmethod="hc12" lambda=1 exponent=1 conv=1 clamp=0.1 minspan=-3:
     iter weight.ratio coefchange% (Intercept) `Survived = YES`
        1          2.2        0.00        0.31           -0.074
        2          3.7       36.00        0.33           -0.122
        3          5.3       14.02        0.34           -0.151
        4          6.5        6.60        0.35           -0.168
        5          7.3        3.21        0.35           -0.176
        6          7.8        1.57        0.36           -0.181
        7          8.0        0.76        0.36           -0.183

> printf("\nsummary(earth.spaced.bx):\n")

summary(earth.spaced.bx):
> print(summary(earth.spaced.bx))
Call: earth(formula=`Survived=YES`~., data=spaced.bx, pmethod="cv", trace=0.5,
            degree=2, nfold=4, ncross=3, varmod.method="lm")

                                                 coefficients
(Intercept)                                        2.01771627
sexmale                                           -0.56066394
pclass3rd                                         -1.25089642
pclass2nd * sexmale                               -0.26729133
pclass3rd * sexmale                                0.20879448
h(4-sexmale * H(16 - age))                        -0.20186359
h(2-pclass3rd * H(4 - sibsp))                     -0.13902926
sexmale * h(H(age - 32)-6)                        -0.00607253
pclass3rd * h(5-sexmale * H(16 - age))             0.08709723
h(pclass3rd * H(4 - sibsp)-2) * h(H(age - 32)-1)   0.00242931
h(pclass3rd * H(4 - sibsp)-2) * h(1-H(age - 32))   0.08048994

Selected 11 of 17 terms, and 7 of 7 predictors (pmethod="cv")
Termination condition: Reached nk 21
Importance: sexmale, pclass3rd, `sexmale*H(16 - age)`, `pclass2nd*sexmale`, ...
Number of terms at each degree of interaction: 1 6 4
GRSq 0.4251614  RSq 0.4523366  mean.oof.RSq 0.4245627 (sd 0.0258)

pmethod="backward" would have selected:
    9 terms 7 preds,  GRSq 0.4276272  RSq 0.4493265  mean.oof.RSq 0.4224044

varmod: method "lm"    min.sd 0.0354    iter.rsq 0.070

stddev of predictions:
               coefficients iter.stderr iter.stderr%
(Intercept)       0.4476988   0.0176523            4
Survived = YES   -0.2293581   0.0258681           11

                              mean    smallest    largest      ratio
95% prediction interval   1.387928   0.6949522   1.966296   2.829398

                                         68%    80%    90%    95% 
response values in prediction interval   69     75<    84<    93< 
> printf("\nevimp(earth.spaced.bx):\n")

evimp(earth.spaced.bx):
> print(evimp(earth.spaced.bx))
                         nsubsets   gcv    rss
sexmale                        10 100.0  100.0
pclass3rd                       9  57.2   60.0
`sexmale*H(16 - age)`           7  38.8   42.6
`pclass2nd*sexmale`             7  38.8   42.6
`pclass3rd*sexmale`             6  35.0   38.7
`pclass3rd*H(4 - sibsp)`        6  29.7   34.2
`H(age - 32)`                   5  23.8   28.7
> 
> set.seed(2020)
> earth.glm.spaced.bx <- earth(`Survived = YES` ~ ., data=spaced.bx, degree=2, trace=.5,
+                          glm=list(family="binomial"),
+                          nfold=4, ncross=3, varmod.method="lm", pmethod="cv")
Preliminary model with pmethod="backward": GRSq 0.428 RSq 0.449 nterms 9
CV fold  1.1  CVRSq  0.402   n.oof  779 26%   n.infold.nz  320 41%   n.oof.nz  107 40%
CV fold  1.2  CVRSq  0.424   n.oof  785 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  1.3  CVRSq  0.418   n.oof  786 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  1.4  CVRSq  0.433   n.oof  788 25%   n.infold.nz  321 41%   n.oof.nz  106 41%
CV fold  2.1  CVRSq  0.470   n.oof  784 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  2.2  CVRSq  0.417   n.oof  775 26%   n.infold.nz  320 41%   n.oof.nz  107 39%
CV fold  2.3  CVRSq  0.412   n.oof  787 25%   n.infold.nz  320 41%   n.oof.nz  107 41%
CV fold  2.4  CVRSq  0.421   n.oof  792 24%   n.infold.nz  321 41%   n.oof.nz  106 42%
CV fold  3.1  CVRSq  0.385   n.oof  777 26%   n.infold.nz  320 41%   n.oof.nz  107 40%
CV fold  3.2  CVRSq  0.429   n.oof  792 24%   n.infold.nz  320 40%   n.oof.nz  107 42%
CV fold  3.3  CVRSq  0.461   n.oof  780 25%   n.infold.nz  320 41%   n.oof.nz  107 40%
CV fold  3.4  CVRSq  0.377   n.oof  789 25%   n.infold.nz  321 41%   n.oof.nz  106 41%
CV all        CVRSq  0.421                    n.infold.nz  427 41%
Final model with pmethod="cv": GRSq 0.425 RSq 0.452 nterms selected by cv 11

varmod method="lm" rmethod="hc12" lambda=1 exponent=1 conv=1 clamp=0.1 minspan=-3:
     iter weight.ratio coefchange% (Intercept) `Survived = YES`
        1          2.2        0.00        0.31           -0.074
        2          3.7       36.00        0.33           -0.122
        3          5.3       14.02        0.34           -0.151
        4          6.5        6.60        0.35           -0.168
        5          7.3        3.21        0.35           -0.176
        6          7.8        1.57        0.36           -0.181
        7          8.0        0.76        0.36           -0.183

> printf("\nsummary(earth.glm.spaced.bx):\n")

summary(earth.glm.spaced.bx):
> print(summary(earth.glm.spaced.bx))
Call: earth(formula=`Survived=YES`~., data=spaced.bx, pmethod="cv", trace=0.5,
            glm=list(family="binomial"), degree=2, nfold=4, ncross=3,
            varmod.method="lm")

GLM coefficients
                                                 `Survived = YES`
(Intercept)                                             9.8189944
sexmale                                                -3.0197582
pclass3rd                                              -8.5391964
pclass2nd * sexmale                                    -1.9328478
pclass3rd * sexmale                                     1.2008915
h(4-sexmale * H(16 - age))                             -1.4278190
h(2-pclass3rd * H(4 - sibsp))                          -0.7433398
sexmale * h(H(age - 32)-6)                             -0.0441700
pclass3rd * h(5-sexmale * H(16 - age))                  0.7564144
h(pclass3rd * H(4 - sibsp)-2) * h(H(age - 32)-1)        0.0091406
h(pclass3rd * H(4 - sibsp)-2) * h(1-H(age - 32))        0.5068265

GLM (family binomial, link logit):
 nulldev   df       dev   df   devratio     AIC iters converged
 1414.62 1045   873.999 1035      0.382     896     6         1

Earth selected 11 of 17 terms, and 7 of 7 predictors (pmethod="cv")
Termination condition: Reached nk 21
Importance: sexmale, pclass3rd, `sexmale*H(16 - age)`, `pclass2nd*sexmale`, ...
Number of terms at each degree of interaction: 1 6 4
Earth GRSq 0.4251614  RSq 0.4523366  mean.oof.RSq 0.4245627 (sd 0.0258)

pmethod="backward" would have selected:
    9 terms 7 preds,  GRSq 0.4276272  RSq 0.4493265  mean.oof.RSq 0.4224044

varmod: method "lm"    min.sd 0.0354    iter.rsq 0.070

stddev of predictions:
               coefficients iter.stderr iter.stderr%
(Intercept)       0.4476988   0.0176523            4
Survived = YES   -0.2293581   0.0258681           11

                              mean    smallest    largest      ratio
95% prediction interval   1.387928   0.6949522   1.966296   2.829398

                                         68%    80%    90%    95% 
response values in prediction interval   69     75<    84<    93< 
> printf("\nevimp(earth.glm.spaced.bx):\n")

evimp(earth.glm.spaced.bx):
> print(evimp(earth.glm.spaced.bx))
                         nsubsets   gcv    rss
sexmale                        10 100.0  100.0
pclass3rd                       9  57.2   60.0
`sexmale*H(16 - age)`           7  38.8   42.6
`pclass2nd*sexmale`             7  38.8   42.6
`pclass3rd*sexmale`             6  35.0   38.7
`pclass3rd*H(4 - sibsp)`        6  29.7   34.2
`H(age - 32)`                   5  23.8   28.7
> 
> options(warn=2)
> expect.err(try(plotmo(lm.spaced.bx)),
+            "Cannot determine which variables to plot in degree2 plots")
Error : (converted from warning) Cannot determine which variables to plot in degree2 plots (use all2=TRUE?)
         Confused by variable name "`sexmale*H(16 - age)`"
Got expected error from try(plotmo(lm.spaced.bx))
> options(warn=1)
> 
> plotmo(lm.spaced.bx, do.par=2, SHOWCALL=TRUE)
Warning: Cannot determine which variables to plot in degree2 plots (use all2=TRUE?)
         Confused by variable name "`sexmale*H(16 - age)`"
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plotres(lm.spaced.bx, do.par=0, which=c(1, 3))
> par(org.par)
> 
> plotmo(earth.spaced.bx, degree1="sexmale", do.par=2, level=.8, SHOWCALL=TRUE)
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plot(earth.spaced.bx, do.par=0, which=c(1, 3), info=TRUE, level=.8, type="earth")
> par(org.par)
> 
> plot(earth.spaced.bx, versus="b:", info=TRUE, level=.8, type="earth", SHOWCALL=TRUE)
> 
> # following should be the same as previous page (since type="earth")
> plotmo(earth.glm.spaced.bx, degree1="sexmale", do.par=2, level=.8, type="earth", SHOWCALL=TRUE)
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plot(earth.glm.spaced.bx, do.par=0, which=1, info=TRUE, level=.8, type="earth")
> # $$ TODO Following shouldn't cause Warning: Internal inconsistency: p$fit - fitted != 0
> #         No warning if don't use glm=list(family="binomial") in call to earth
> options(warn=2)
> expect.err(try(plot(earth.glm.spaced.bx, do.par=0, which=3, info=TRUE, level=.8, type="earth")),
+            "Internal inconsistency: p$fit != fitted")
Error : (converted from warning) Internal inconsistency: p$fit != fitted
         Workaround: no 'glm' arg in call to earth, or no 'level' arg n call to plotres
Got expected error from try(plot(earth.glm.spaced.bx, do.par = 0, which = 3, info = TRUE,     level = 0.8, type = "earth"))
> options(warn=1)
> plot(earth.glm.spaced.bx, do.par=0, which=3, info=TRUE, level=.8, type="earth")
Warning: Internal inconsistency: p$fit != fitted
         Workaround: no 'glm' arg in call to earth, or no 'level' arg n call to plotres
> par(org.par)
> 
> expect.err(try(plotmo(earth.glm.spaced.bx, level=.8)),
+            "predict.earth: with earth-glm models, use type=\"earth\" when using the interval argument")
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
Error : predict.earth: with earth-glm models, use type="earth" when using the interval argument
Got expected error from try(plotmo(earth.glm.spaced.bx, level = 0.8))
> 
> plotmo(earth.glm.spaced.bx, degree1="sexmale", do.par=2, SHOWCALL=TRUE)
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plot(earth.glm.spaced.bx, do.par=0, which=c(1, 3), info=TRUE)
> par(org.par)
> 
> printf("\n=== test combinations of variables in formula ===\n")

=== test combinations of variables in formula ===
> 
> vdata <- data.frame(
+     resp = 1:13,
+     bool = c(F, F, F, F, F, T, T, T, T, T, T, T, T),
+     ord  = ordered(c("ORD1", "ORD1", "ORD1",
+                      "ORD1", "ORD1", "ORD1",
+                      "ORD3", "ORD3", "ORD3",
+                      "ORD2", "ORD2", "ORD2", "ORD2"),
+                    levels=c("ORD1", "ORD3", "ORD2")),
+     fac  = as.factor(c("FAC1", "FAC1", "FAC1",
+                        "FAC2", "FAC2", "FAC2",
+                        "FAC3", "FAC3", "FAC3",
+                        "FAC1", "FAC2", "FAC3", "FAC3")),
+     str  = c("STR1", "STR1", "STR1", # WILL BE TREATED LIKE A FACTOR
+              "STR2", "STR2", "STR2",
+              "STR3", "STR3", "STR3",
+              "STR3", "STR3", "STR3", "STR3"),
+     num  = c(1, 3, 2, 3, 4, 5, 6, 4, 5, 6.5, 3, 6, 5), # 7 unique values (but one is non integral)
+     sqrt_num  = sqrt(c(1, 3, 2, 3, 4, 5, 6, 4, 5, 6.5, 3, 6, 5)),
+     int  = c(1L, 1L, 3L, 3L, 4L, 4L, 3L, 5L, 3L, 6L, 7L, 8L, 10L), # 8 unique values
+     date = as.Date(
+            c("2018-08-01", "2018-08-02", "2018-08-03",
+              "2018-08-04", "2018-08-05", "2018-08-06",
+              "2018-08-07", "2018-08-08", "2018-08-08",
+              "2018-08-08", "2018-08-10", "2018-08-11", "2018-08-11")),
+     date_num = as.numeric(as.Date(
+            c("2018-08-01", "2018-08-02", "2018-08-03",
+              "2018-08-04", "2018-08-05", "2018-08-06",
+              "2018-08-07", "2018-08-08", "2018-08-08",
+              "2018-08-08", "2018-08-10", "2018-08-11", "2018-08-11"))))
> 
> vdata$off <- (1:nrow(vdata)) / nrow(vdata)
> 
> resp2 <- 13:1
> 
> vweights <- rep(1, length.out=nrow(vdata))
> vweights[1] <- 2
> 
> set.seed(2020)
> lognum.bool.ord.off <- earth(resp ~ log(num) + bool + ord + offset(off), degree=2, weights=vweights,
+            data=vdata, pmethod="none", varmod.method="lm",
+            nfold=2, ncross=3,
+            trace=1)
x[13,4] with colnames log(num) boolTRUE ord.L ord.Q
y[13,1] with colname resp, and values 0.9231, 1.846, 2.769, 3.692, ...
weights[13]: 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Forward pass term 1, 2, 4, 6, 8
GRSq -Inf at 7 terms, 5 terms used
After forward pass GRSq -in RSq 0.966
Prune none penalty 3 nprune null: selected 5 of 5 terms, and 3 of 4 preds
After pruning pass GRSq -0.732 RSq 0.952

CV fold  1.1  CVRSq -0.476   n.oof  6 54%   n.infold.nz  6 100%   n.oof.nz  7 100%
CV fold  1.2  CVRSq  0.823   n.oof  7 46%   n.infold.nz  7 100%   n.oof.nz  6 100%
CV fold  2.1  CVRSq -0.622   n.oof  6 54%   n.infold.nz  6 100%   n.oof.nz  7 100%
CV fold  2.2  CVRSq  0.816   n.oof  7 46%   n.infold.nz  7 100%   n.oof.nz  6 100%
CV fold  3.1  CVRSq  0.559   n.oof  6 54%   n.infold.nz  6 100%   n.oof.nz  7 100%
CV fold  3.2  CVRSq  0.698   n.oof  7 46%   n.infold.nz  7 100%   n.oof.nz  6 100%
CV all        CVRSq  0.300                  n.infold.nz 13 100%


varmod method="lm" rmethod="hc12" lambda=1 exponent=1 conv=1 clamp=0.1 minspan=-3:
     iter weight.ratio coefchange% (Intercept)  resp
        1          1.6        0.00        1.76 0.045
        2          2.2       39.64        1.55 0.076
        3          2.9       19.19        1.40 0.098
        4          3.5       12.21        1.29 0.115
        5          4.1        8.66        1.21 0.127
        6          4.6        6.50        1.15 0.137
        7          5.0        5.05        1.10 0.145
        8          5.5        4.02        1.06 0.152
        9          5.8        3.25        1.03 0.157
       10          6.1        2.66        1.00 0.162
       11          6.4        2.19        0.98 0.165
       12          6.7        1.82        0.97 0.168
       13          6.9        1.52        0.95 0.171
       14          7.1        1.28        0.94 0.173
       15          7.3        1.08        0.93 0.175
       16          7.4        0.91        0.92 0.176

> 
> printf("summary(lognum.bool.ord.off)\n")
summary(lognum.bool.ord.off)
> print(summary(lognum.bool.ord.off))
Call: earth(formula=resp~log(num)+bool+ord+offset(off), data=vdata,
            weights=vweights, pmethod="none", trace=1, degree=2, nfold=2,
            ncross=3, varmod.method="lm")

                                 coefficients
(Intercept)                          6.273213
boolTRUE                             1.111403
h(-7.85046e-17-ord.L)               -7.600147
h(ord.L- -7.85046e-17)               4.568998
log(num) * h(-7.85046e-17-ord.L)     3.100021

Selected 5 of 5 terms, and 3 of 4 predictors (pmethod="none")
Termination condition: GRSq -Inf at 5 terms
Importance: ord.L, log(num), boolTRUE, ord.Q-unused
Offset: off with values 0.07692308, 0.1538462, 0.2307692, 0.3076923, 0.3...
Weights: 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Number of terms at each degree of interaction: 1 3 1
GCV 28.70012  RSS 8.830806  GRSq -0.7319038  RSq 0.9518916  CVRSq 0.2995745

Note: the cross-validation sd's below are standard deviations across folds

Cross validation:   nterms 2.33 sd 0.52    nvars 1.00 sd 0.00

     CVRSq    sd     MaxErr   sd
       0.3 0.666         -6 3.53

varmod: method "lm"    min.sd 0.27    iter.rsq 0.204

stddev of predictions:
            coefficients iter.stderr iter.stderr%
(Intercept)     1.151190    0.759983           66
resp            0.220811    0.131375           59

                              mean   smallest    largest      ratio
95% prediction interval   10.57312   5.357389   14.56643   2.718942

                                          68%     80%     90%     95% 
response values in prediction interval   100     100     100     100  
> cat("\nevimp(lognum.bool.ord.off)\n")

evimp(lognum.bool.ord.off)
> print(evimp(lognum.bool.ord.off))
         nsubsets   gcv    rss
ord.L           4 -73.4  100.0
log(num)        2 -98.7   30.8
boolTRUE        1 -100.0    6.6
> 
> plotmo(lognum.bool.ord.off, do.par=2, level=.8, SHOWCALL=TRUE)
Note: the offset in the formula is not plotted
      (use all1=TRUE to plot the offset, or use trace=-1 to silence this message)

 plotmo grid:    num bool  ord       off
                   4 TRUE ORD1 0.5384615
> plot(lognum.bool.ord.off, which=1, do.par=0)
> par(org.par)
> 
> num.fac.sqrt.num.ord.bool <- earth(resp ~ num + int + fac + offset(off) + sqrt(num) + ord:bool - int,
+            data=vdata, pmethod="none", trace=1)
x[13,10] with colnames num facFAC2 facFAC3 sqrt(num) ordORD1:boolFALSE ordORD3:b...
y[13,1] with colname resp, and values 0.9231, 1.846, 2.769, 3.692, ...
Forward pass term 1, 2, 4, 6, 8, 10
GRSq -Inf at 9 terms, 6 terms used
After forward pass GRSq -in RSq 0.979
Prune none penalty 2 nprune null: selected 6 of 6 terms, and 4 of 10 preds
After pruning pass GRSq 0.045 RSq 0.973
> plotmo(num.fac.sqrt.num.ord.bool, SHOWCALL=TRUE)
Note: the offset in the formula is not plotted
      (use all1=TRUE to plot the offset, or use trace=-1 to silence this message)

 plotmo grid:    num int  fac       off  ord bool
                   4   4 FAC3 0.5384615 ORD1 TRUE
> cat("\nevimp(num.fac.sqrt.num.ord.bool)\n")

evimp(num.fac.sqrt.num.ord.bool)
> print(evimp(num.fac.sqrt.num.ord.bool))
                  nsubsets   gcv    rss
ordORD1:boolFALSE        4  25.3  100.0
ordORD2:boolTRUE         4 -87.6   52.9
num                      3 -100.0   30.0
facFAC3                  3 -100.0   30.0
> 
> printf("\n=== unusual formulas, compare to lm ===\n")

=== unusual formulas, compare to lm ===
> 
> lm1 <- lm(resp~ord+sqrt(as.numeric(fac)) + num+sqrt(num / 2)+I(2 * int)+date, data = vdata)
> 
> # same formula terms  as lm1 but in different order
> earth1 <- earth(resp~sqrt(as.numeric(fac)) + ord + date + num + sqrt(.5 * num)+I(int / .5),
+                 data = vdata, linpreds=TRUE, thresh=0, penalty=-1)
> cat("\nevimp(earth1)\n")

evimp(earth1)
> print(evimp(earth1))
                      nsubsets   gcv    rss
date                         7 100.0  100.0
sqrt(as.numeric(fac))        5  10.8   10.8
ord.L                        5   5.3    5.3
num                          4   3.6    3.6
I(int/0.5)                   4   3.6    3.6
ord.Q                        2   0.0    0.0
sqrt(0.5 * num)              1   0.0    0.0
> plotmo(lm1,    SHOWCALL=TRUE)
 plotmo grid:    ord  fac num int       date
                ORD1 FAC3   4   4 2018-08-07
> plotmo(earth1, SHOWCALL=TRUE)
 plotmo grid:    fac  ord       date num int
                FAC3 ORD1 2018-08-07   4   4
> stopifnot(max(abs(sort(lm1$coef) - sort(earth1$coef))) < 1e-10)
> stopifnot((summary(lm1)$r.squared - earth1$rsq) < 1e-10)
> stopifnot(max(abs(predict(lm1, newdata=vdata[5,,drop=FALSE]) - predict(earth1, newdata=vdata[5,,drop=FALSE]))) < 1e-10)
> 
> fac.sqrt    <- earth(resp~sqrt(num)+fac, data = vdata, linpreds=TRUE, thresh=0, penalty=-1)
> fac.sqrt_   <- earth(resp~sqrt_num+fac,  data = vdata, linpreds=TRUE, thresh=0, penalty=-1)
> cat("\nevimp(fac.sqrt)\n")

evimp(fac.sqrt)
> print(evimp(fac.sqrt))
          nsubsets   gcv    rss
sqrt(num)        3 100.0  100.0
facFAC3          2  37.4   37.4
facFAC2          1  18.4   18.4
> cat("\nevimp(fac.sqrt_)\n")

evimp(fac.sqrt_)
> print(evimp(fac.sqrt_))
         nsubsets   gcv    rss
sqrt_num        3 100.0  100.0
facFAC3         2  37.4   37.4
facFAC2         1  18.4   18.4
> # as.vector to remove names (which are slightly different: sqrt(num) vs sqrt_num
> stopifnot(identical(as.vector(fac.sqrt$coef), as.vector(fac.sqrt_$coef)))
> 
> newdata.extra <- vdata[3:5,] # extra variables unused in the model
> newdata.extra$extra <- sqrt(newdata.extra[,1])
> cat("\ncolnames(newdata.extra):", paste(colnames(newdata.extra)), "\n")

colnames(newdata.extra): resp bool ord fac str num sqrt_num int date date_num off extra 
> 
> newd  <- vdata[3:5,c("num", "fac")]             # only variables used in the formula model
> newd_ <- vdata[3:5,c("num", "sqrt_num", "fac")] # only variables used in the xy model
> 
> stopifnot(identical(predict(fac.sqrt, newdata=newdata.extra), predict(fac.sqrt_, newdata=newd_)))
> stopifnot(identical(predict(fac.sqrt, newdata=newd), predict(fac.sqrt_, newdata=newd_)))
> stopifnot(identical(predict(fac.sqrt, newdata=newd), predict(fac.sqrt_, newdata=newd_)))
> stopifnot(identical(predict(fac.sqrt, newdata=newd), predict(fac.sqrt_, newdata=newd_)))
> 
> stopifnot(max(abs(predict(fac.sqrt, newdata=newdata.extra) - predict(fac.sqrt_, newdata=newdata.extra))) < 1e-10)
> stopifnot(max(abs(predict(fac.sqrt, newdata=newdata.extra) - predict(fac.sqrt_, newdata=newdata.extra))) < 1e-10)
> 
> printf("\n=== two response model ===\n")

=== two response model ===
> 
> vdata.2resp <- vdata
> resp2 <- 13:1
> vdata.2resp$resp2 <- resp2
> 
> earth.2resp <- earth(resp+resp2~num+sqrt(num), data=vdata.2resp, weights=vweights, trace=1,
+                      linpreds=TRUE, thresh=0, penalty=-1)
Using class "Formula" because lhs of formula has terms separated by "+"
x[13,2] with colnames num sqrt(num)
y[13,2] with colnames resp resp2
weights[13]: 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Forward pass term 1, 2, 4, 6
No new term increases RSq (perhaps reached numerical limits) at 5 terms, 3 terms used
After forward pass GRSq 0.584 RSq 0.584
Prune backward penalty -1 nprune null: selected 3 of 3 terms, and 2 of 2 preds
After pruning pass GRSq 0.584 RSq 0.584
> printf("\nsummary(earth.2resp)\n")

summary(earth.2resp)
> print(summary(earth.2resp))
Call: earth(formula=resp+resp2~num+sqrt(num), data=vdata.2resp,
            weights=vweights, trace=1, linpreds=TRUE, thresh=0, penalty=-1)

                  resp      resp2
(Intercept) -6.0874826 20.0874826
num         -0.3162815  0.3162815
sqrt(num)    7.2649780 -7.2649780

Selected 3 of 3 terms, and 2 of 2 predictors
Termination condition: No new term increases RSq at 3 terms
Importance: sqrt(num), num
Weights: 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Number of terms at each degree of interaction: 1 2 (additive model)

            GCV       RSS      GRSq       RSq
resp   6.899683  89.69588 0.5836398 0.5836398
resp2  6.899683  89.69588 0.5836398 0.5836398
All   13.799366 179.39176 0.5836398 0.5836398
> cat("\nevimp(earth.2resp)\n")

evimp(earth.2resp)
> print(evimp(earth.2resp))
          nsubsets   gcv    rss
sqrt(num)        2 100.0  100.0
num              1   2.4    2.4
> par(mfrow = c(2, 2), mar = c(3, 3, 3, 1), mgp = c(1.5, 0.5, 0), oma=c(0,0,4,0))
> # for formula models, plotmo plots a sinle plot for the effect of num
> plotmo(earth.2resp, nresp=1, do.par=0, main="earth.2resp    nresp1")
> title <- paste(
+     "two-response model: resp+resp2~num+sqrt(num)\n",
+     "the top row is for earth.formula models: the combined effect of num and sqrt(num) is plotted together\n",
+     "the bottom row is for an earth.default model: num and sqrt(num) are plotted separately")
> title(title, outer=TRUE, cex=.6)
> plotmo(earth.2resp, nresp=2, do.par=0, main="earth.2resp    nresp2")
> 
> # put two response data mats into matrix form for earth.default and for lm
> xmat <- vdata[,c("num", "sqrt_num"), drop=FALSE]
> colnames(xmat) <- c("num", "sqrt(num)")
> xmat <- as.matrix(xmat)
> ymat <- vdata[, "resp", drop=FALSE]
> ymat$resp2 <- resp2
> ymat <- as.matrix(ymat)
> earthxy.2resp <- earth(xmat, ymat, weights=vweights, trace=1,
+                        linpreds=TRUE, thresh=0, penalty=-1)
x[13,2] with colnames num sqrt(num)
y[13,2] with colnames resp resp2
weights[13]: 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Forward pass term 1, 2, 4, 6
No new term increases RSq (perhaps reached numerical limits) at 5 terms, 3 terms used
After forward pass GRSq 0.584 RSq 0.584
Prune backward penalty -1 nprune null: selected 3 of 3 terms, and 2 of 2 preds
After pruning pass GRSq 0.584 RSq 0.584
> printf("\nsummary(earthxy.2resp)\n")

summary(earthxy.2resp)
> print(summary(earthxy.2resp))
Call: earth(x=xmat, y=ymat, weights=vweights, trace=1, linpreds=TRUE, thresh=0,
            penalty=-1)

                  resp      resp2
(Intercept) -6.0874826 20.0874826
num         -0.3162815  0.3162815
sqrt(num)    7.2649780 -7.2649780

Selected 3 of 3 terms, and 2 of 2 predictors
Termination condition: No new term increases RSq at 3 terms
Importance: sqrt(num), num
Weights: 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Number of terms at each degree of interaction: 1 2 (additive model)

            GCV       RSS      GRSq       RSq
resp   6.899683  89.69588 0.5836398 0.5836398
resp2  6.899683  89.69588 0.5836398 0.5836398
All   13.799366 179.39176 0.5836398 0.5836398
> cat("\nevimp(earthxy.2resp)\n")

evimp(earthxy.2resp)
> print(evimp(earthxy.2resp))
          nsubsets   gcv    rss
sqrt(num)        2 100.0  100.0
num              1   2.4    2.4
> # for xy models, plotmo plots a separate plots for the effect of num and sqrt(num)
> plotmo(earthxy.2resp, nresp=1, do.par=0)
 plotmo grid:    num sqrt(num)
                   4         2
> # plotmo(earthxy.2resp, nresp=2, do.par=0)
> stopifnot(identical(earth.2resp$coeff, earthxy.2resp$coeff))
> 
> lm.2resp <- lm(ymat~xmat, weights=vweights)
> printf("\nsummary(lm.2resp)\n")

summary(lm.2resp)
> print(summary(lm.2resp))
Response resp :

Call:
lm(formula = resp ~ xmat, weights = vweights)

Weighted Residuals:
    Min      1Q  Median      3Q     Max 
-3.5470 -2.1773 -0.3788  0.8227  5.4530 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)
(Intercept)    -6.0875    10.4903  -0.580    0.575
xmatnum        -0.3163     3.4983  -0.090    0.930
xmatsqrt(num)   7.2650    12.4500   0.584    0.572

Residual standard error: 2.995 on 10 degrees of freedom
Multiple R-squared:  0.5836,	Adjusted R-squared:  0.5004 
F-statistic: 7.009 on 2 and 10 DF,  p-value: 0.01251


Response resp2 :

Call:
lm(formula = resp2 ~ xmat, weights = vweights)

Weighted Residuals:
    Min      1Q  Median      3Q     Max 
-5.4530 -0.8227  0.3788  2.1773  3.5470 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)  
(Intercept)    20.0875    10.4903   1.915   0.0845 .
xmatnum         0.3163     3.4983   0.090   0.9297  
xmatsqrt(num)  -7.2650    12.4500  -0.584   0.5725  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.995 on 10 degrees of freedom
Multiple R-squared:  0.5836,	Adjusted R-squared:  0.5004 
F-statistic: 7.009 on 2 and 10 DF,  p-value: 0.01251


> options(warn=2) # treat warnings as errors
> expect.err(try(plotmo(lm.2resp, nresp=1)),
+            "the variable on the right side of the formula is a matrix or data.frame")
Error : (converted from warning) the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Got expected error from try(plotmo(lm.2resp, nresp = 1))
> options(warn=1) # print warnings as they occur
> 
> # check that lm and earth coeffs are the same
> # need order() below because coeffs appear in different row order in the coeff mat
> earth.2resp.order <- order(earth.2resp$coeff[,1])
> lm.order <- order(lm.2resp$coeff[,1])
> stopifnot(max(abs(earth.2resp$coeff[earth.2resp.order] - lm.2resp$coeff[lm.order])) < 1e-10)
> 
> printf("\n=== test glm() with spaced.bx ===\n")

=== test glm() with spaced.bx ===
> 
> # glm requires response to be a factor (or two columns)
> spaced.bx.fac <- spaced.bx
> spaced.bx.fac$`surv fac` <- factor(ifelse(spaced.bx$`Survived = YES`, "yes", "no"), levels = c("yes", "no"))
> spaced.bx.fac$`Survived = YES` <- NULL
> glm.spaced.bx <- glm(`surv fac` ~ ., data=spaced.bx.fac, family="binomial")
> printf("summary(glm.spaced.bx):\n")
summary(glm.spaced.bx):
> print(summary(glm.spaced.bx))

Call:
glm(formula = `surv fac` ~ ., family = "binomial", data = spaced.bx.fac)

Coefficients:
                         Estimate Std. Error z value Pr(>|z|)    
(Intercept)              -2.91353    0.28320 -10.288  < 2e-16 ***
sexmale                   3.18562    0.31478  10.120  < 2e-16 ***
pclass3rd                 5.03006    0.56669   8.876  < 2e-16 ***
`sexmale*H(16 - age)`    -0.24181    0.03646  -6.632 3.31e-11 ***
`pclass2nd*sexmale`       1.76809    0.32676   5.411 6.27e-08 ***
`pclass3rd*H(4 - sibsp)` -0.61865    0.13506  -4.581 4.64e-06 ***
`pclass3rd*sexmale`      -1.22270    0.39291  -3.112  0.00186 ** 
`H(age - 32)`             0.03757    0.01178   3.189  0.00143 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1414.62  on 1045  degrees of freedom
Residual deviance:  892.79  on 1038  degrees of freedom
AIC: 908.79

Number of Fisher Scoring iterations: 5

> plotmo(glm.spaced.bx, do.par=2)
Warning: Cannot determine which variables to plot in degree2 plots (use all2=TRUE?)
         Confused by variable name "`sexmale*H(16 - age)`"
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plotres(glm.spaced.bx, which=3, do.par=0, info=TRUE, main="plotres(glm.spaced.bx,which=3")
> # TODO why is Residuals-Vs-Fitted plot different for plotres and plot for glm models?
> plot(glm.spaced.bx, which=1, caption="plot(glm.spaced.bx, which=1)")
> par(org.par)
> plotmo(glm.spaced.bx, all2=TRUE, degree2=c("sexmale", "pclass"), SHOW.CALL=TRUE, do.par=2)
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plotmo(glm.spaced.bx, degree1=0, all2=TRUE, degree2=c("sexmale", "age"), do.par=0)
> par(org.par) # TODO I think plot(glm.spaced.bx) doesn't restore the graphics params?
> 
> printf("\n=== test formulas which have a rhs variable which a matrix ===\n")

=== test formulas which have a rhs variable which a matrix ===
> # This also tests that earth's naming of variables is the same as lm for such rhs variables
> #
> # TODO plotmo fails when rhs variable is a matrix --- would be nice to fix that
> 
> x_ <- etitanic[,"age",drop=FALSE]
> x_$pclass <- etitanic$pclass
> x_$pclass <- as.numeric(etitanic$pclass)
> x_ <- as.matrix(x_)
> y_ <- as.matrix(as.numeric(etitanic[,"survived"]))
> 
> earthxy.rhs.mat <- earth(x_, y_, degree=2, trace=1)
x[1046,2] with colnames age pclass
y[1046,1] with colname y_, and values 1, 1, 0, 0, 0, 1, 1, 0, 1, 0,...
Forward pass term 1, 2, 4, 6, 8, 10
RSq changed by less than 0.001 at 9 terms (DeltaRSq 0.00055)
After forward pass GRSq 0.120 RSq 0.162
Prune backward penalty 3 nprune null: selected 6 of 9 terms, and 2 of 2 preds
After pruning pass GRSq 0.137 RSq 0.158
> print(summary(earthxy.rhs.mat))
Call: earth(x=x_, y=y_, trace=1, degree=2)

                        coefficients
(Intercept)               0.47789359
h(18-age)                 0.03051719
h(age-18)                -0.00609975
h(2-pclass)               0.28092736
h(pclass-2)              -0.16376873
h(23-age) * h(pclass-2)  -0.01570789

Selected 6 of 9 terms, and 2 of 2 predictors
Termination condition: RSq changed by less than 0.001 at 9 terms
Importance: pclass, age
Number of terms at each degree of interaction: 1 4 1
GCV 0.2088003    RSS 212.8039    GRSq 0.1373292    RSq 0.1578438
> cat("\nevimp(earthxy.rhs.mat)\n")

evimp(earthxy.rhs.mat)
> print(evimp(earthxy.rhs.mat))
       nsubsets   gcv    rss
pclass        5 100.0  100.0
age           4  66.0   69.3
> cat("\nearthxy.rhs.mat$modvars\n")

earthxy.rhs.mat$modvars
> print(earthxy.rhs.mat$modvars)
       age pclass
age      1      0
pclass   0      1
> plotmo(earthxy.rhs.mat, SHOWCALL=TRUE) # ok
 plotmo grid:    age pclass
                  28      2
> 
> earth.rhs.mat <- earth(y_ ~ x_, degree=2, trace=1)
x[1046,2] with colnames x_age x_pclass
y[1046,1] with colname y_, and values 1, 1, 0, 0, 0, 1, 1, 0, 1, 0,...
Forward pass term 1, 2, 4, 6, 8, 10
RSq changed by less than 0.001 at 9 terms (DeltaRSq 0.00055)
After forward pass GRSq 0.120 RSq 0.162
Prune backward penalty 3 nprune null: selected 6 of 9 terms, and 2 of 2 preds
After pruning pass GRSq 0.137 RSq 0.158
> print(summary(earth.rhs.mat))
Call: earth(formula=y_~x_, trace=1, degree=2)

                            coefficients
(Intercept)                   0.47789359
h(18-x_age)                   0.03051719
h(x_age-18)                  -0.00609975
h(2-x_pclass)                 0.28092736
h(x_pclass-2)                -0.16376873
h(23-x_age) * h(x_pclass-2)  -0.01570789

Selected 6 of 9 terms, and 2 of 2 predictors
Termination condition: RSq changed by less than 0.001 at 9 terms
Importance: x_pclass, x_age
Number of terms at each degree of interaction: 1 4 1
GCV 0.2088003    RSS 212.8039    GRSq 0.1373292    RSq 0.1578438
> cat("\nevimp(earth.rhs.mat)\n")

evimp(earth.rhs.mat)
> print(evimp(earth.rhs.mat))
         nsubsets   gcv    rss
x_pclass        5 100.0  100.0
x_age           4  66.0   69.3
> cat("\nearth.rhs.mat$modvars\n")

earth.rhs.mat$modvars
> print(earth.rhs.mat$modvars)
   x_age x_pclass
x_     1        1
> stopifnot(max(abs(earthxy.rhs.mat$coeff - earth.rhs.mat$coeff)) < 1e-15)
> expect.err(try(plotmo(earth.rhs.mat)), # Warning: the variable on the right side of the formula is a matrix or data.frame
+            "model.frame.default could not interpret the data passed to get.earth.x from model.matrix.earth from predict.earth")
Warning: the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Warning: Cannot determine which variables to plot (use all1=TRUE?)
             single.names=c(x_,x_,x_,x_)
             colnames(x)=c(age,pclass)


stats::predict(earth.object, data.frame[50,2], type="response")

Error : model.frame.default could not interpret the data passed to get.earth.x from model.matrix.earth from predict.earth
        (actual.nrows=1046 expected.nrows=50 fitted.nrows=1046)
Got expected error from try(plotmo(earth.rhs.mat))
> expect.err(try(plotmo(earth.rhs.mat, all1=TRUE)), # still fails
+            "model.frame.default could not interpret the data passed to get.earth.x from model.matrix.earth from predict.earth")
Warning: the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables

stats::predict(earth.object, data.frame[50,2], type="response")

Error : model.frame.default could not interpret the data passed to get.earth.x from model.matrix.earth from predict.earth
        (actual.nrows=1046 expected.nrows=50 fitted.nrows=1046)
Got expected error from try(plotmo(earth.rhs.mat, all1 = TRUE))
> 
> lm.rhs.mat <- lm(y_ ~ x_)
> print(summary(lm.rhs.mat))

Call:
lm(formula = y_ ~ x_)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.9113 -0.3505 -0.1995  0.4395  1.0350 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  1.167193   0.062574  18.653  < 2e-16 ***
x_age       -0.007626   0.001070  -7.125 1.94e-12 ***
x_pclass    -0.240589   0.018334 -13.123  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.4553 on 1043 degrees of freedom
Multiple R-squared:  0.1444,	Adjusted R-squared:  0.1427 
F-statistic: 87.98 on 2 and 1043 DF,  p-value: < 2.2e-16

> expect.err(try(plotmo(lm.rhs.mat)), # Warning: the variable on the right side of the formula is a matrix or data.frame
+            "predict returned the wrong length (got 1046 but expected 50)")
Warning: the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Warning: 'newdata' had 50 rows but variables found have 1046 rows
Error : predict returned the wrong length (got 1046 but expected 50)
Got expected error from try(plotmo(lm.rhs.mat))
> expect.err(try(plotmo(lm.rhs.mat, all1=TRUE)), # still fails
+            "predict returned the wrong length (got 1046 but expected 50)")
Warning: the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Warning: 'newdata' had 50 rows but variables found have 1046 rows
Error : predict returned the wrong length (got 1046 but expected 50)
Got expected error from try(plotmo(lm.rhs.mat, all1 = TRUE))
> earth1.rhs.mat <- earth(y_ ~ x_, linpreds=TRUE, thresh=0, penalty=-1) # degree1
> cat("\nevimp(earth1.rhs.mat)\n")

evimp(earth1.rhs.mat)
> print(evimp(earth1.rhs.mat))
         nsubsets   gcv    rss
x_pclass        2 100.0  100.0
x_age           1  53.7   53.7
> options(warn=2)
> expect.err(try(plotmo(earth.rhs.mat)),
+            "the variable on the right side of the formula is a matrix or data.frame")
Error : (converted from warning) the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Got expected error from try(plotmo(earth.rhs.mat))
> expect.err(try(plotmo(earth.rhs.mat, all1=TRUE)), # still fails
+            "the variable on the right side of the formula is a matrix or data.frame")
Error : (converted from warning) the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Got expected error from try(plotmo(earth.rhs.mat, all1 = TRUE))
> options(warn=1)
> stopifnot(max(abs(sort(lm.rhs.mat$coeff) - sort(earth1.rhs.mat$coeff))) < 1e-12)
> stopifnot(sort(rownames(lm.rhs.mat$coeff)) == sort(rownames(earth1.rhs.mat$coeff)))
> 
> x_nonames <- x_
> colnames(x_nonames) <- NULL
> lm.rhs.nonames <- lm(y_ ~ x_nonames)
> print(summary(lm.rhs.nonames))

Call:
lm(formula = y_ ~ x_nonames)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.9113 -0.3505 -0.1995  0.4395  1.0350 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  1.167193   0.062574  18.653  < 2e-16 ***
x_nonames1  -0.007626   0.001070  -7.125 1.94e-12 ***
x_nonames2  -0.240589   0.018334 -13.123  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.4553 on 1043 degrees of freedom
Multiple R-squared:  0.1444,	Adjusted R-squared:  0.1427 
F-statistic: 87.98 on 2 and 1043 DF,  p-value: < 2.2e-16

> expect.err(try(plotmo(lm.rhs.nonames)), # Warning: the variable on the right side of the formula is a matrix or data.frame
+            "predict returned the wrong length (got 1046 but expected 50)")
Warning: the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Warning: 'newdata' had 50 rows but variables found have 1046 rows
Error : predict returned the wrong length (got 1046 but expected 50)
Got expected error from try(plotmo(lm.rhs.nonames))
> expect.err(try(plotmo(lm.rhs.nonames, all1=TRUE)), # still fails
+            "predict returned the wrong length (got 1046 but expected 50)")
Warning: the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Warning: 'newdata' had 50 rows but variables found have 1046 rows
Error : predict returned the wrong length (got 1046 but expected 50)
Got expected error from try(plotmo(lm.rhs.nonames, all1 = TRUE))
> earth1.rhs.nonames <- earth(y_ ~ x_nonames, linpreds=TRUE, thresh=0, penalty=-1) # degree1
> print(summary(earth1.rhs.nonames))
Call: earth(formula=y_~x_nonames, linpreds=TRUE, thresh=0, penalty=-1)

            coefficients
(Intercept)   1.16719336
x_nonames1   -0.00762624
x_nonames2   -0.24058942

Selected 3 of 3 terms, and 2 of 2 predictors
Termination condition: No new term increases RSq at 3 terms
Importance: x_nonames2, x_nonames1
Number of terms at each degree of interaction: 1 2 (additive model)
GCV 0.2067034    RSS 216.2118    GRSq 0.1443571    RSq 0.1443571
> cat("\nevimp(earth1.rhs.nonames)\n")

evimp(earth1.rhs.nonames)
> print(evimp(earth1.rhs.nonames))
           nsubsets   gcv    rss
x_nonames2        2 100.0  100.0
x_nonames1        1  53.7   53.7
> options(warn=2)
> expect.err(try(plotmo(earth1.rhs.nonames)), # Warning: the variable on the right side of the formula is a matrix or data.frame
+            "the variable on the right side of the formula is a matrix or data.frame")
Error : (converted from warning) the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Got expected error from try(plotmo(earth1.rhs.nonames))
> expect.err(try(plotmo(earth1.rhs.nonames, all1=TRUE)), # still fails
+            "the variable on the right side of the formula is a matrix or data.frame")
Error : (converted from warning) the variable on the right side of the formula is a matrix or data.frame
         plotmo often cannot process such variables
Got expected error from try(plotmo(earth1.rhs.nonames, all1 = TRUE))
> options(warn=1)
> stopifnot(max(abs(sort(lm.rhs.nonames$coeff) - sort(earth1.rhs.nonames$coeff))) < 1e-12)
> stopifnot(sort(rownames(lm.rhs.nonames$coeff)) == sort(rownames(earth1.rhs.nonames$coeff)))
> 
> printf("\n=== test handling consecutive '-' in formula ===\n")

=== test handling consecutive '-' in formula ===
> 
> options(warn=2)
> lm.consec.minus <- lm(Volume~.--Girth, data=trees) # note double --
> expect.err(try(plotmo(lm.consec.minus)),
+            "Consecutive '-' in formula may cause problems")
Error : (converted from warning) Consecutive '-' in formula may cause problems
         Formula: (Girth + Height) - -Girth
Got expected error from try(plotmo(lm.consec.minus))
> earth.consec.minus <- earth(Volume~.--Girth, data=trees) # note double --
> cat("\nsummary(earth.consec.minus)\n")

summary(earth.consec.minus)
> print(summary(earth.consec.minus))
Call: earth(formula=Volume~.--Girth, data=trees)

              coefficients
(Intercept)     29.0599535
h(14.2-Girth)   -3.4198062
h(Girth-14.2)    6.2295143
h(Height-75)     0.5813644

Selected 4 of 5 terms, and 2 of 2 predictors
Termination condition: RSq changed by less than 0.001 at 5 terms
Importance: Girth, Height
Number of terms at each degree of interaction: 1 3 (additive model)
GCV 11.25439    RSS 209.1139    GRSq 0.959692    RSq 0.9742029
> cat("\nevimp(earth.consec.minus)\n")

evimp(earth.consec.minus)
> print(evimp(earth.consec.minus))
       nsubsets   gcv    rss
Girth         3 100.0  100.0
Height        1  10.7   11.5
> expect.err(try(plotmo(earth.consec.minus)),
+            "Consecutive '-' in formula may cause problems")
Error : (converted from warning) Consecutive '-' in formula may cause problems
         Formula: (Girth + Height) - -Girth
Got expected error from try(plotmo(earth.consec.minus))
> options(warn=1)
> 
> printf("\n=== test rpart() with spaced.bx ===\n")

=== test rpart() with spaced.bx ===
> 
> library(rpart.plot)
Loading required package: rpart
> rpart.mod <- rpart(`Survived = YES` ~ ., data=spaced.bx)
> printf("\nprint(rpart.rules(rpart.mod))\n")

print(rpart.rules(rpart.mod))
> print(rpart.rules(rpart.mod))
 Survived = YES                                                                                                                       
          0.062 when sexmale is 1 & pclass3rd is 1 & sexmale*H(16 - age) >= 6.5                          & pclass3rd*H(4 - sibsp) <  2
          0.082 when sexmale is 1                  & sexmale*H(16 - age) <  6.5 & pclass2nd*sexmale is 1                              
          0.150 when sexmale is 1 & pclass3rd is 1 & sexmale*H(16 - age) <  6.5 & pclass2nd*sexmale is 0                              
          0.338 when sexmale is 1 & pclass3rd is 0 & sexmale*H(16 - age) <  6.5 & pclass2nd*sexmale is 0                              
          0.474 when sexmale is 0 & pclass3rd is 1                                                                                    
          0.769 when sexmale is 1 & pclass3rd is 1 & sexmale*H(16 - age) >= 6.5                          & pclass3rd*H(4 - sibsp) >= 2
          0.932 when sexmale is 0 & pclass3rd is 0                                                                                    
          1.000 when sexmale is 1 & pclass3rd is 0 & sexmale*H(16 - age) >= 6.5                                                       
> set.seed(2020)
> plotmo(rpart.mod, do.par=2, degree1=c("sexmale", "pclass3rd"), degree2=2, pt.col="red")
 plotmo grid:    sexmale pclass3rd sexmale*H(16 - age) pclass2nd*sexmale
                       1         0                   0                 0
 pclass3rd*H(4 - sibsp) pclass3rd*sexmale H(age - 32)
                      0                 0           0
> plotres(rpart.mod, do.par=0, which=c(1,3))
> par(org.par)
> 
> printf("\n=== tibble, class \"Date\", and ndiscrete ===\n")

=== tibble, class "Date", and ndiscrete ===
> 
> library(tibble)
> library(lubridate)

Attaching package: 'lubridate'

The following objects are masked from 'package:base':

    date, intersect, setdiff, union

> tib1 <- tibble(y    = c(1, 1, 2, 3), # even number of variables
+                bool = c(F, F, F, T),
+                date = c(ymd('2018-08-01'), ymd('2018-08-02'), ymd('2018-08-03'),
+                         ymd('2018-08-03')))
> cat("class tib1$date: ", class(tib1$date), "\n")
class tib1$date:  Date 
> mod.tib1 <- lm(y ~ ., data = tib1)
> plotmo(mod.tib1, col.response=2, all2=TRUE, ticktype="d", do.par=2, caption="mod.tib1: Dates ndiscrete=default 5")
 plotmo grid:    bool       date
                FALSE 2018-08-02
> plotmo(mod.tib1, col.response=2, degree1=0, all2=TRUE, ticktype="d", do.par=0, theta=-45)
> par(org.par)
> 
> plotmo(mod.tib1, col.response=2, all2=TRUE, ticktype="d", do.par=2, ndiscrete=2, caption="mod.tib1: Dates ndiscrete=2")
 plotmo grid:    bool       date
                FALSE 2018-08-02
> plotmo(mod.tib1, col.response=2, degree1=0, all2=TRUE, ticktype="d", do.par=0, theta=-45, ndiscrete=2)
> par(org.par)
> 
> plotmo(mod.tib1, col.response=2, all2=TRUE, ticktype="d", do.par=2, ndiscr=1, caption="mod.tib1: Dates ndiscrete=1")
 plotmo grid:    bool       date
                FALSE 2018-08-02
> plotmo(mod.tib1, col.response=2, degree1=0, all2=TRUE, ticktype="d", do.par=0, theta=-45, ndiscrete=2)
> par(org.par)
> 
> tib2 <- tibble(y    = c(1, 1, 2, 3, 4), # odd number of variables
+                bool = c(F, F, F, T, T),
+                date = c(ymd('2018-08-01'), ymd('2018-08-02'), ymd('2018-08-03'),
+                         ymd('2018-08-03'), ymd('2018-08-04')))
> mod.tib2 <- lm(y ~ ., data = tib2)
> plotmo(mod.tib2, col.response=2, all2=TRUE, ticktype="d", do.par=2, caption="mod.tib2: Dates ndiscrete=default 5")
 plotmo grid:    bool       date
                FALSE 2018-08-03
> plotmo(mod.tib2, col.response=2, degree1=0, all2=TRUE, ticktype="d", do.par=0, theta=-45)
> par(org.par)
> 
> plotmo(mod.tib2, col.response=2, all2=TRUE, ticktype="d", do.par=2, ndiscrete=2, caption="mod.tib2: Dates ndiscrete=2")
 plotmo grid:    bool       date
                FALSE 2018-08-03
> plotmo(mod.tib2, col.response=2, degree1=0, all2=TRUE, ticktype="d", do.par=0, theta=-45, ndiscrete=2)
> par(org.par)
> 
> plotmo(mod.tib2, col.response=2, all2=TRUE, ticktype="d", do.par=2, ndiscr=1, caption="mod.tib2: Dates ndiscrete=1")
 plotmo grid:    bool       date
                FALSE 2018-08-03
> plotmo(mod.tib2, col.response=2, degree1=0, all2=TRUE, ticktype="d", do.par=0, theta=-45, ndiscrete=2)
> par(org.par)
> 
> source("test.epilog.R")
