Author: Rousseeuw, P.J.
Date: 2026-04-29

# predsplot_examples

#### Rousseeuw, P.J.

#### 2026-04-29

    library(classmap)

# TopGear data

We start by loading the data, and selecting the relevant features. As pre-processing, we set values of accel==0 to missing because it is impossible. We also remove the incorrect weight of the Peugeot 107.

    data(TopGear, package = "robustHD")
    cars = TopGear; rm(TopGear)
    dim(cars) # [1] 297  32

    ## [1] 297  32

    rownames(cars) = paste(cars[,1],cars[,2])
    # Now the rownames are make and model of the cars.
    colnames(cars)

    ##  [1] "Maker"              "Model"              "Type"
    ##  [4] "Fuel"               "Price"              "Cylinders"
    ##  [7] "Displacement"       "DriveWheel"         "BHP"
    ## [10] "Torque"             "Acceleration"       "TopSpeed"
    ## [13] "MPG"                "Weight"             "Length"
    ## [16] "Width"              "Height"             "AdaptiveHeadlights"
    ## [19] "AdjustableSteering" "AlarmSystem"        "Automatic"
    ## [22] "Bluetooth"          "ClimateControl"     "CruiseControl"
    ## [25] "ElectricSeats"      "Leather"            "ParkingSensors"
    ## [28] "PowerSteering"      "SatNav"             "ESP"
    ## [31] "Verdict"            "Origin"

    colnames(cars)[4:17] = c("fuel","price","cyl","displ","drive",
                             "hp","torque","accel","topspeed",
                             "MPG","weight","length","width",
                             "height")
    summary(cars$accel) # zero minimum is impossible

    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
    ##   0.000   5.900   9.100   8.839  11.400  16.900

    rownames(cars)[which(cars$accel == 0)]

    ## [1] "Citroen C5 Tourer" "Ford Mondeo"       "Lotus Elise"
    ## [4] "Renault Twizy"     "Ssangyong Rodius"

    # [1] "Citroen C5 Tourer" "Ford Mondeo"   "Lotus Elise"
    # [4] "Renault Twizy"     "Ssangyong Rodius"
    cars$accel[cars$accel == 0] = NA
    summary(cars$accel) # OK

    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    ##    2.50    6.20    9.20    8.99   11.50   16.90       5

    cars$weight[order(cars$weight)[1:4]]

    ## [1] 210 450 490 550

    rownames(cars)[order(cars$weight)[1:4]]

    ## [1] "Peugeot 107"      "Renault Twizy"    "Morgan 3 Wheeler" "Caterham Super 7"

    cars$weight[cars$weight == 210] = NA
    summary(cars$weight) # OK

    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    ##     450    1250    1496    1541    1778    2705      34

    # save(cars, file = "Topgear.RData")
    # load("Topgear.RData")

## Numerical example in the introduction

    summary(cars$topspeed) # in mph

    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    ##    50.0   112.0   126.0   132.7   151.0   252.0       4

    summary(cars$displ)    # in cc

    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    ##     647    1560    1995    2504    2988    7993       9

    summary(cars$length)   # in mm

    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    ##    2337    4157    4464    4427    4766    5612      11

    cars$length = cars$length/1000 # in meters

    fit = lm(hp ~ topspeed + length + displ, data = cars)
    summary(fit)

    ##
    ## Call:
    ## lm(formula = hp ~ topspeed + length + displ, data = cars)
    ##
    ## Residuals:
    ##      Min       1Q   Median       3Q      Max
    ## -142.034  -20.667   -2.715   15.966  174.020
    ##
    ## Coefficients:
    ##               Estimate Std. Error t value Pr(>|t|)
    ## (Intercept) -2.069e+02  2.861e+01  -7.232 4.78e-12 ***
    ## topspeed     2.466e+00  1.373e-01  17.963  < 2e-16 ***
    ## length      -1.313e+01  6.187e+00  -2.122   0.0347 *
    ## displ        6.255e-02  2.808e-03  22.275  < 2e-16 ***
    ## ---
    ## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    ##
    ## Residual standard error: 37.72 on 274 degrees of freedom
    ##   (19 observations deleted due to missingness)
    ## Multiple R-squared:  0.9405, Adjusted R-squared:  0.9399
    ## F-statistic:  1445 on 3 and 274 DF,  p-value: < 2.2e-16

    predsplot(fit, main = "Top Gear data")

    ##
    ## Prediction terms in the model:
    ##         prediction term   stdev up/down
    ##                topspeed  68.380      up
    ##                  length   5.817    down
    ##                   displ  91.790      up
    ##  Total prediction of hp 149.200

    fact = 0.51
    width = fact*10; height = fact*8
    maxnchar = 6
    main = "Top Gear data"
    pdf(file = "topgear_numerical_predsplot.pdf",
        width = width, height = height)
    predsplot(fit, main=main, maxchar.level = maxnchar)

    ##
    ## Prediction terms in the model:
    ##         prediction term   stdev up/down
    ##                topspeed  68.380      up
    ##                  length   5.817    down
    ##                   displ  91.790      up
    ##  Total prediction of hp 149.200

    dev.off()

    ## png
    ##   2

    predscor(fit, sort.by.stdev = FALSE)

    ## Correlation matrix of the prediction terms:
    ##          topspeed length displ
    ## topspeed     1.00  -0.45  0.80
    ## length      -0.45   1.00 -0.56
    ## displ        0.80  -0.56  1.00

    # fact = 0.6
    # width = fact*10; height = fact*8
    # pdf(file = "topgear_numerical_predscor.pdf",
    #     width = height, height = height)
    # predscor(fit, sort.by.stdev = FALSE)
    # dev.off()

## Figure 2 and TopGear figures in Supplementary Material:

    cars$GPM = 1/cars$MPG

    fit4 = lm(GPM ~ accel + drive + weight + fuel, data = cars)
    summary(fit4)

    ##
    ## Call:
    ## lm(formula = GPM ~ accel + drive + weight + fuel, data = cars)
    ##
    ## Residuals:
    ##       Min        1Q    Median        3Q       Max
    ## -0.026997 -0.004301  0.000268  0.003660  0.055643
    ##
    ## Coefficients:
    ##               Estimate Std. Error t value Pr(>|t|)
    ## (Intercept)  1.681e-02  4.884e-03   3.443 0.000677 ***
    ## accel       -1.356e-03  2.459e-04  -5.516 8.81e-08 ***
    ## driveFront  -2.927e-03  1.619e-03  -1.808 0.071853 .
    ## driveRear   -2.745e-04  1.577e-03  -0.174 0.861992
    ## weight       1.131e-05  1.841e-06   6.143 3.25e-09 ***
    ## fuelPetrol   8.427e-03  1.246e-03   6.761 9.98e-11 ***
    ## ---
    ## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    ##
    ## Residual standard error: 0.007973 on 245 degrees of freedom
    ##   (46 observations deleted due to missingness)
    ## Multiple R-squared:  0.6058, Adjusted R-squared:  0.5977
    ## F-statistic: 75.29 on 5 and 245 DF,  p-value: < 2.2e-16

    ## Figure 2:
    ##
    fact = 0.52
    width = fact*10; height = fact*8
    maxnchar = 6
    main = "Top Gear data"
    # pdf(file = "topgear_4_predsplot.pdf",
    #     width = width, height = height)
    predsplot(fit4, main=main, maxchar.level = maxnchar)

    ##
    ## Prediction terms in the model:
    ##          prediction term    stdev up/down
    ##                    accel 0.004329    down
    ##                    drive 0.001400
    ##                   weight 0.004490      up
    ##                     fuel 0.004104
    ##  Total prediction of GPM 0.009783

    # dev.off()

## Three figures in the Supplementary Material:

    ##
    # fact = 0.6
    # width = fact*10; height = fact*8
    # pdf(file = "topgear_4_predscor.pdf",
    #     width = height, height = height)
    predscor(fit4, sort.by.stdev = FALSE)

    ## Correlation matrix of the prediction terms:
    ##        accel drive weight  fuel
    ## accel   1.00  0.65   0.49  0.31
    ## drive   0.65  1.00   0.62  0.08
    ## weight  0.49  0.62   1.00 -0.23
    ## fuel    0.31  0.08  -0.23  1.00

    # dev.off()

    car = "Bentley Continental"
    # pdf(file = "topgear_4_predsplot_1_dens.pdf",
    #     width = width, height = height)
    predsplot(fit4, main = main, casetoshow=car,
              displaytype = "density",
              maxchar.level = maxnchar,
              xlab = paste0("prediction for ",car))

    ##
    ##  Prediction terms for case Bentley Continental:
    ##          prediction term    value
    ##                    accel +0.00621
    ##                    drive +0.00152
    ##                   weight +0.00857
    ##                     fuel +0.00322
    ##                      SUM +0.01952
    ##               centercept  0.02599
    ##  Total prediction of GPM  0.04551

    # dev.off()

    car = "Kia Rio"
    # pdf(file = "topgear_4_predsplot_2_stairs.pdf",
    #     width = width, height = height)
    predsplot(fit4, main = main, casetoshow=car,
              staircase = TRUE, maxchar.level = maxnchar,
              xlab = paste0("prediction for ",car))

    ##
    ##  Prediction terms for case Kia Rio:
    ##          prediction term    value
    ##                    accel -0.00884
    ##                    drive -0.00141
    ##                   weight -0.00420
    ##                     fuel -0.00520
    ##                      SUM -0.01966
    ##               centercept  0.02599
    ##  Total prediction of GPM  0.00633

    # dev.off()

## Test combination of expressions and types

We add a logical variable (AlarmSystem) as well as a character variable (SatNav)

    summary(cars$AlarmSystem)

    ## no/optional    standard
    ##         112         185

    cars$alarm = (cars$AlarmSystem == "standard")
    summary(cars$alarm)

    ##    Mode   FALSE    TRUE
    ## logical     112     185

    summary(cars$SatNav)

    ##       no optional standard
    ##       86      116       95

    cars$navig = "y"
    cars$navig[cars$SatNav == "no"] = "n"
    summary(cars$navig)

    ##    Length     Class      Mode
    ##       297 character character

    table(cars$navig)

    ##
    ##   n   y
    ##  86 211

    class(cars$navig)

    ## [1] "character"

    str(cars)

    ## 'data.frame':    297 obs. of  35 variables:
    ##  $ Maker             : Factor w/ 51 levels "Alfa Romeo","Aston Martin",..: 1 1 2 2 2 2 2 2 2 3 ...
    ##  $ Model             : Factor w/ 296 levels "1 Series","1 Series Convertible",..: 139 186 101 102 103 262 266 267 268 29 ...
    ##  $ Type              : Factor w/ 297 levels "107 1.0 68 Active 5d",..: 139 190 100 101 102 263 269 268 267 30 ...
    ##  $ fuel              : Factor w/ 2 levels "Diesel","Petrol": 1 2 2 2 2 2 2 2 2 2 ...
    ##  $ price             : num  21250 15155 30995 131995 141995 ...
    ##  $ cyl               : num  4 4 4 12 12 12 12 8 8 4 ...
    ##  $ displ             : num  1598 1368 1329 5935 5935 ...
    ##  $ drive             : Factor w/ 3 levels "4WD","Front",..: 2 2 2 3 3 3 3 3 3 2 ...
    ##  $ hp                : num  105 105 98 517 517 510 573 420 420 86 ...
    ##  $ torque            : num  236 95 92 457 457 420 457 346 346 118 ...
    ##  $ accel             : num  11.3 10.7 11.8 4.6 4.6 4.2 4.1 4.7 4.7 11.7 ...
    ##  $ topspeed          : num  115 116 106 183 183 190 183 180 180 112 ...
    ##  $ MPG               : num  64 49 56 19 19 17 19 20 20 55 ...
    ##  $ weight            : num  1385 1090 988 1785 1890 ...
    ##  $ length            : num  4.35 4.06 3.08 4.72 4.72 ...
    ##  $ width             : num  1798 1720 1680 NA NA ...
    ##  $ height            : num  1465 1446 1500 1282 1282 ...
    ##  $ AdaptiveHeadlights: Factor w/ 3 levels "no","optional",..: 2 2 1 3 3 1 3 1 1 2 ...
    ##  $ AdjustableSteering: Factor w/ 2 levels "no","standard": 2 2 2 2 2 2 2 2 2 2 ...
    ##  $ AlarmSystem       : Factor w/ 2 levels "no/optional",..: 2 2 1 1 1 2 2 2 2 2 ...
    ##  $ Automatic         : Factor w/ 3 levels "no","optional",..: 1 1 2 3 3 1 3 2 2 1 ...
    ##  $ Bluetooth         : Factor w/ 3 levels "no","optional",..: 3 3 3 3 3 3 3 2 2 3 ...
    ##  $ ClimateControl    : Factor w/ 3 levels "no","optional",..: 3 2 3 3 3 3 3 3 3 2 ...
    ##  $ CruiseControl     : Factor w/ 3 levels "no","optional",..: 3 3 3 3 3 3 3 2 2 2 ...
    ##  $ ElectricSeats     : Factor w/ 3 levels "no","optional",..: 2 1 1 3 3 3 3 3 3 1 ...
    ##  $ Leather           : Factor w/ 3 levels "no","optional",..: 2 2 1 3 3 3 3 3 3 2 ...
    ##  $ ParkingSensors    : Factor w/ 3 levels "no","optional",..: 2 3 1 3 3 3 3 3 3 2 ...
    ##  $ PowerSteering     : Factor w/ 2 levels "no","standard": 2 2 2 2 2 2 2 2 2 2 ...
    ##  $ SatNav            : Factor w/ 3 levels "no","optional",..: 2 2 3 3 3 3 3 2 2 2 ...
    ##  $ ESP               : Factor w/ 3 levels "no","optional",..: 3 3 3 3 3 3 3 3 3 3 ...
    ##  $ Verdict           : num  6 5 7 7 7 7 7 8 7 6 ...
    ##  $ Origin            : Factor w/ 3 levels "Asia","Europe",..: 2 2 2 2 2 2 2 2 2 2 ...
    ##  $ GPM               : num  0.0156 0.0204 0.0179 0.0526 0.0526 ...
    ##  $ alarm             : logi  TRUE TRUE FALSE FALSE FALSE TRUE ...
    ##  $ navig             : chr  "y" "y" "y" "y" ...

    fitcombin = lm(1/MPG ~ accel + log(weight) + accel:torque + alarm + navig, data = cars)
    summary(fitcombin)

    ##
    ## Call:
    ## lm(formula = 1/MPG ~ accel + log(weight) + accel:torque + alarm +
    ##     navig, data = cars)
    ##
    ## Residuals:
    ##       Min        1Q    Median        3Q       Max
    ## -0.026131 -0.005201 -0.001251  0.004847  0.056823
    ##
    ## Coefficients:
    ##                Estimate Std. Error t value Pr(>|t|)
    ## (Intercept)  -1.018e-01  3.347e-02  -3.040  0.00262 **
    ## accel        -2.115e-03  2.461e-04  -8.591 9.87e-16 ***
    ## log(weight)   2.135e-02  4.709e-03   4.534 9.01e-06 ***
    ## alarmTRUE    -2.450e-03  1.343e-03  -1.824  0.06932 .
    ## navigy       -1.693e-03  1.367e-03  -1.239  0.21667
    ## accel:torque -3.403e-06  1.394e-06  -2.442  0.01532 *
    ## ---
    ## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    ##
    ## Residual standard error: 0.008684 on 247 degrees of freedom
    ##   (44 observations deleted due to missingness)
    ## Multiple R-squared:  0.5293, Adjusted R-squared:  0.5198
    ## F-statistic: 55.56 on 5 and 247 DF,  p-value: < 2.2e-16

    fact = 0.45
    width = fact*10; height = fact*8
    main = "Example with transformation, interaction, logical, character"
    # pdf(file = "topgear_logical+char_predsplot.pdf", width = width, height = height)
    predsplot(fitcombin, main=main)

    ##
    ## Prediction terms in the model:
    ##            prediction term     stdev up/down
    ##                      accel 0.0067300    down
    ##                log(weight) 0.0054000      up
    ##                      alarm 0.0011630
    ##                      navig 0.0007587
    ##               accel:torque 0.0024290
    ##  Total prediction of 1/MPG 0.0091180

    # dev.off()

    fact = 0.6
    width = fact*10; height = fact*8
    # pdf(file = "topgear_logical+char_predscor.pdf",
    #     width = height, height = height)
    predscor(fitcombin)

    ## Correlation matrix of the prediction terms:
    ##              accel log(weight) accel:torque alarm navig
    ## accel         1.00        0.53        -0.09 -0.37 -0.33
    ## log(weight)   0.53        1.00        -0.75 -0.43 -0.35
    ## accel:torque -0.09       -0.75         1.00  0.26  0.18
    ## alarm        -0.37       -0.43         0.26  1.00  0.38
    ## navig        -0.33       -0.35         0.18  0.38  1.00

    # dev.off()

# Titanic data

We start by loading the data, turning the pclass and sex variables into factors.

    data(data_titanic, package = "classmap")
    titanic = data_titanic; rm(data_titanic)
    dim(titanic) # 1309  13

    ## [1] 1309   13

    # A data frame with 1309 observations on the following variables.
    #   passengerId: a unique identifier for each passenger.
    #   pclass: travel class of the passenger.
    #   name: name of the passenger.
    #   sex: sex of the passenger.
    #   age: age of the passenger.
    #   sibsp: number of siblings and spouses traveling with the passenger.
    #   parch: number of parents and children traveling with the passenger.
    #   ticket: ticket number of the passenger.
    #   fare: fare paid for the ticket.
    #   Cabin: cabin number of the passenger.
    #   embarked: Port of embarkation. Takes the values
    #             C (Cherbourg), Q (Queenstown) and
    #             S (Southampton).
    #   y: factor indicating casualty or survivor.
    #   dataType: vector taking the values “train” or “test”
    #             indicating whether the observation belongs
    #             to training or test data.
    #
    colnames(titanic) = c("passengerId","pclass","name","sex",
                       "age", "sibsp", "parch", "ticket",
                       "fare", "cabin", "embarked", "survival",
                       "dataType")
    str(titanic)

    ## 'data.frame':    1309 obs. of  13 variables:
    ##  $ passengerId: int  1 2 3 4 5 6 7 8 9 10 ...
    ##  $ pclass     : int  3 1 3 1 3 3 1 3 3 2 ...
    ##  $ name       : chr  "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
    ##  $ sex        : chr  "male" "female" "female" "female" ...
    ##  $ age        : num  22 38 26 35 35 NA 54 2 27 14 ...
    ##  $ sibsp      : int  1 1 0 1 0 0 0 3 0 1 ...
    ##  $ parch      : int  0 0 0 0 0 0 0 1 2 0 ...
    ##  $ ticket     : chr  "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
    ##  $ fare       : num  7.25 71.28 7.92 53.1 8.05 ...
    ##  $ cabin      : chr  "" "C85" "" "C123" ...
    ##  $ embarked   : chr  "S" "C" "S" "S" ...
    ##  $ survival   : Factor w/ 2 levels "casualty","survived": 1 2 2 2 1 1 1 1 2 2 ...
    ##  $ dataType   : chr  "train" "train" "train" "train" ...

    unique(titanic$pclass) # 3 1 2

    ## [1] 3 1 2

    titanic$pclass = factor(titanic$pclass, levels = unique(titanic$pclass))
    #

    unique(titanic$sex)

    ## [1] "male"   "female"

    titanic$sex = factor(titanic$sex, levels = unique(titanic$sex) )
    titanic$sex = factor(titanic$sex, labels = c("M","F"))
    head(titanic)

    ##   passengerId pclass                                                name sex
    ## 1           1      3                             Braund, Mr. Owen Harris   M
    ## 2           2      1 Cumings, Mrs. John Bradley (Florence Briggs Thayer)   F
    ## 3           3      3                              Heikkinen, Miss. Laina   F
    ## 4           4      1        Futrelle, Mrs. Jacques Heath (Lily May Peel)   F
    ## 5           5      3                            Allen, Mr. William Henry   M
    ## 6           6      3                                    Moran, Mr. James   M
    ##   age sibsp parch           ticket    fare cabin embarked survival dataType
    ## 1  22     1     0        A/5 21171  7.2500              S casualty    train
    ## 2  38     1     0         PC 17599 71.2833   C85        C survived    train
    ## 3  26     0     0 STON/O2. 3101282  7.9250              S survived    train
    ## 4  35     1     0           113803 53.1000  C123        S survived    train
    ## 5  35     0     0           373450  8.0500              S casualty    train
    ## 6  NA     0     0           330877  8.4583              Q casualty    train

    # save(titanic, file="Titanic.RData")
    # load("Titanic.RData")

Now fit a logistic regression model.

    fit5 <- glm(survival ~ sex + age + sibsp + parch + pclass,
                family=binomial, data = titanic)
    summary(fit5)

    ##
    ## Call:
    ## glm(formula = survival ~ sex + age + sibsp + parch + pclass,
    ##     family = binomial, data = titanic)
    ##
    ## Coefficients:
    ##              Estimate Std. Error z value Pr(>|z|)
    ## (Intercept) -1.002093   0.221287  -4.528 5.94e-06 ***
    ## sexF         2.556861   0.173270  14.756  < 2e-16 ***
    ## age         -0.039489   0.006634  -5.952 2.64e-09 ***
    ## sibsp       -0.352914   0.105349  -3.350 0.000808 ***
    ## parch        0.074361   0.099907   0.744 0.456697
    ## pclass1      2.352022   0.228803  10.280  < 2e-16 ***
    ## pclass2      0.985265   0.199384   4.942 7.75e-07 ***
    ## ---
    ## 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:  970.12  on 1039  degrees of freedom
    ##   (263 observations deleted due to missingness)
    ## AIC: 984.12
    ##
    ## Number of Fisher Scoring iterations: 4

## Figure 3:

    fact = 0.5
    width = fact*10; height = fact*8
    main = "Titanic data"
    # pdf(file = "titanic_5_predsplot_dens.pdf",
    #     width = width, height = height)
    predsplot(fit5, main=main, displaytype = "density")

    ##
    ## Prediction terms in the model:
    ##                      prediction term   stdev up/down
    ##                                  sex 1.23600
    ##                                  age 0.56920    down
    ##                                sibsp 0.32190    down
    ##                                parch 0.06244      up
    ##                               pclass 0.98130
    ##  Total linear prediction of survival 1.67000
    ##
    ## The glm fit used the logit link function.

    # The glm fit used the logit link function.
    # dev.off()

    # With other options for density estimation:
    predsplot(fit5, main=main, displaytype = "density",
              bw = "SJ", adjust = 0.5)

    ##
    ## Prediction terms in the model:
    ##                      prediction term   stdev up/down
    ##                                  sex 1.23600
    ##                                  age 0.56920    down
    ##                                sibsp 0.32190    down
    ##                                parch 0.06244      up
    ##                               pclass 0.98130
    ##  Total linear prediction of survival 1.67000
    ##
    ## The glm fit used the logit link function.

## Three figures in Supplementary Material:

    # pdf(file = "titanic_5_predsplot_1.pdf",
    #     width = width, height = height)
    predsplot(fit5, main = main, casetoshow=1)

    ##
    ##  Prediction terms for case 1:
    ##                                 prediction term    value
    ##                                             sex -0.94843
    ##                                             age +0.31122
    ##                                           sibsp -0.17544
    ##                                           parch -0.03128
    ##                                          pclass -0.88444
    ##                                             SUM -1.72839
    ##                                      centercept -0.49537
    ##             Total linear prediction of survival -2.22376
    ##  Total prediction of survival in response units  0.09764
    ##
    ## The glm fit used the logit link function.

    # dev.off()

    # pdf(file = "titanic_5_predsplot_2_stairs.pdf",
    #     width = width, height = height)
    predsplot(fit5, main = main, casetoshow=2, staircase = TRUE)

    ##
    ##  Prediction terms for case 2:
    ##                                 prediction term    value
    ##                                             sex +1.60843
    ##                                             age -0.32060
    ##                                           sibsp -0.17544
    ##                                           parch -0.03128
    ##                                          pclass +1.46758
    ##                                             SUM +2.54868
    ##                                      centercept -0.49537
    ##             Total linear prediction of survival  2.05331
    ##  Total prediction of survival in response units  0.88628
    ##
    ## The glm fit used the logit link function.

    # dev.off()

    # fact = 0.6
    # width = fact*10; height = fact*8
    # pdf(file = "titanic_5_predscor.pdf",
    #     width = height, height = height)
    predscor(fit5, sort.by.stdev = FALSE)

    ## Correlation matrix of the prediction terms:
    ##          sex   age sibsp parch pclass
    ## sex     1.00  0.06 -0.10  0.22   0.14
    ## age     0.06  1.00 -0.24  0.15  -0.41
    ## sibsp  -0.10 -0.24  1.00 -0.37   0.04
    ## parch   0.22  0.15 -0.37  1.00  -0.02
    ## pclass  0.14 -0.41  0.04 -0.02   1.00

    # dev.off()

# German credit data

    data(german.credit, package = "fairml")
    credit = german.credit; rm(german.credit)
    dim(credit) # 1000 21

    ## [1] 1000   21

    str(credit)

    ## 'data.frame':    1000 obs. of  21 variables:
    ##  $ Account_status          : Factor w/ 4 levels "< 0 DM",">= 200 DM",..: 1 3 4 1 1 4 4 3 4 3 ...
    ##  $ Duration                : num  6 48 12 42 24 36 24 36 12 30 ...
    ##  $ Credit_history          : Factor w/ 5 levels "all credits at this bank paid back duly",..: 2 4 2 4 3 4 4 4 4 2 ...
    ##  $ Purpose                 : Factor w/ 10 levels "business","car (new)",..: 8 8 5 6 2 5 6 3 8 2 ...
    ##  $ Credit_amount           : num  1169 5951 2096 7882 4870 ...
    ##  $ Savings_bonds           : Factor w/ 5 levels "< 100 DM",">= 1000 DM",..: 5 1 1 1 1 5 4 1 2 1 ...
    ##  $ Present_employment_since: Factor w/ 5 levels "< 1 year",">= 7 years",..: 2 3 4 4 3 3 2 3 4 5 ...
    ##  $ Installment_rate        : num  4 2 2 2 3 2 3 2 2 4 ...
    ##  $ Other_debtors_guarantors: Factor w/ 3 levels "co-applicant",..: 3 3 3 2 3 3 3 3 3 3 ...
    ##  $ Resident_since          : num  4 2 3 4 4 4 4 2 4 2 ...
    ##  $ Property                : Factor w/ 4 levels "building society savings agreement / life insurance",..: 3 3 3 1 4 4 1 2 3 2 ...
    ##  $ Age                     : num  67 22 49 45 53 35 53 35 61 28 ...
    ##  $ Other_installment_plans : Factor w/ 3 levels "bank","none",..: 2 2 2 2 2 2 2 2 2 2 ...
    ##  $ Housing                 : Factor w/ 3 levels "rent","own","for free": 2 2 2 3 3 3 2 1 2 2 ...
    ##  $ Existing_credits        : num  2 1 1 1 2 1 1 1 1 2 ...
    ##  $ Job                     : Factor w/ 4 levels "management / self-employed / highly qualified employee / officer",..: 2 2 4 2 2 4 2 1 4 1 ...
    ##  $ People_maintenance_for  : num  1 1 2 2 2 2 1 1 1 1 ...
    ##  $ Telephone               : Factor w/ 2 levels "none","yes": 2 1 1 1 1 2 1 2 1 1 ...
    ##  $ Foreign_worker          : Factor w/ 2 levels "no","yes": 2 2 2 2 2 2 2 2 2 2 ...
    ##  $ Credit_risk             : Factor w/ 2 levels "BAD","GOOD": 2 1 2 2 1 2 2 2 2 1 ...
    ##  $ Gender                  : Factor w/ 2 levels "Female","Male": 1 2 1 1 1 1 1 1 1 1 ...

    #
    # Shorten variable names for plotting:
    colnames(credit) <- c("checking","months","history","purpose","amount","savings","employment","rate","guarantors","residence","property","age","inst_plans","housing","nloans","job","nclients","phone","foreign","credit","sex")
    #
    # Give factors sex and purpose shorter labels for plotting:
    credit$sex = factor(as.numeric(credit$sex), labels = c("F","M"))
    levels(credit$purpose)

    ##  [1] "business"              "car (new)"             "car (used)"
    ##  [4] "domestic appliances"   "education"             "furniture / equipment"
    ##  [7] "others"                "radio / television"    "repairs"
    ## [10] "retrainin"

    # [10] "retrainin"
    levels(credit$purpose) = c("business","n.car","u.car","appliances","education","furniture","other","TV","repairs","retraining")
    # save(credit, file = "German_credit.RData")
    # load("German_credit.RData")

Now fit a logistic regression model

    fit7 <- glm(credit ~ months + purpose + amount + rate + age +
                nclients + sex, family=binomial, data = credit)

## Figure in Supplementary Material:

    main = "German credit data"
    # fact = 0.48
    # width = fact*10; height = fact*8
    # pdf(file = "germancredit_7_predsplot.pdf",
    #     width = width, height = height)
    predsplot(fit7, main = main)

    ##
    ## Prediction terms in the model:
    ##                    prediction term   stdev up/down
    ##                             months 0.37690    down
    ##                            purpose 0.51700
    ##                             amount 0.26380    down
    ##                               rate 0.27320    down
    ##                                age 0.24350      up
    ##                           nclients 0.07078    down
    ##                                sex 0.21110
    ##  Total linear prediction of credit 0.80900
    ##
    ## The glm fit used the logit link function.

    # dev.off()

## Figure 4:

    # fact = 0.48
    # width = fact*10; height = fact*8
    # pdf(file = "germancredit_7_predsplot_1.pdf",
    #     width = width, height = height)
    predsplot(fit7, main = main, casetoshow=1,
              displaytype = "density")

    ##
    ##  Prediction terms for case 1:
    ##                               prediction term    value
    ##                                        months +0.46584
    ##                                       purpose +0.37611
    ##                                        amount +0.19645
    ##                                          rate -0.25082
    ##                                           age +0.67325
    ##                                      nclients +0.03030
    ##                                           sex +0.14143
    ##                                           SUM +1.63255
    ##                                    centercept  0.95998
    ##             Total linear prediction of credit  2.59253
    ##  Total prediction of credit in response units  0.93038
    ##
    ## The glm fit used the logit link function.

    # dev.off()

## Figure 5:

    # pdf(file = "germancredit_7_predsplot_2_stairs.pdf",
    #     width = width, height = height)
    predsplot(fit7, main = main, casetoshow=2, staircase = TRUE)

    ##
    ##  Prediction terms for case 2:
    ##                               prediction term    value
    ##                                        months -0.84700
    ##                                       purpose +0.37611
    ##                                        amount -0.25041
    ##                                          rate +0.23763
    ##                                           age -0.28994
    ##                                      nclients +0.03030
    ##                                           sex -0.31479
    ##                                           SUM -1.05811
    ##                                    centercept  0.95998
    ##             Total linear prediction of credit -0.09813
    ##  Total prediction of credit in response units  0.47549
    ##
    ## The glm fit used the logit link function.

    # dev.off()

## Figure 6:

    # fact = 0.6
    # width = fact*10; height = fact*8
    # pdf(file = "germancredit_7_predscor_equalsizes.pdf",
    #     width = height, height = height)
    predscor(fit7, sort.by.stdev = FALSE, cell.length = "equal")

    ## Correlation matrix of the prediction terms:
    ##          months purpose amount  rate   age nclients   sex
    ## months     1.00   -0.12   0.62  0.07  0.04    -0.02 -0.08
    ## purpose   -0.12    1.00  -0.12 -0.01 -0.03     0.04  0.05
    ## amount     0.62   -0.12   1.00 -0.27 -0.03     0.02 -0.09
    ## rate       0.07   -0.01  -0.27  1.00 -0.06    -0.07 -0.09
    ## age        0.04   -0.03  -0.03 -0.06  1.00    -0.12  0.16
    ## nclients  -0.02    0.04   0.02 -0.07 -0.12     1.00 -0.20
    ## sex       -0.08    0.05  -0.09 -0.09  0.16    -0.20  1.00

    # dev.off()
    #
    # pdf(file = "germancredit_7_predscor.pdf",
    #     width = height, height = height)
    predscor(fit7, sort.by.stdev = FALSE)

    ## Correlation matrix of the prediction terms:
    ##          months purpose amount  rate   age nclients   sex
    ## months     1.00   -0.12   0.62  0.07  0.04    -0.02 -0.08
    ## purpose   -0.12    1.00  -0.12 -0.01 -0.03     0.04  0.05
    ## amount     0.62   -0.12   1.00 -0.27 -0.03     0.02 -0.09
    ## rate       0.07   -0.01  -0.27  1.00 -0.06    -0.07 -0.09
    ## age        0.04   -0.03  -0.03 -0.06  1.00    -0.12  0.16
    ## nclients  -0.02    0.04   0.02 -0.07 -0.12     1.00 -0.20
    ## sex       -0.08    0.05  -0.09 -0.09  0.16    -0.20  1.00

    # dev.off()

## Two figures in Supplementary Material:

    ## Prediction for a new case:
    newc = list("u.car", 36, 2, 6000, 55, "F", 1)
    names(newc) = c("purpose","months","rate","amount",
                    "age","sex","nclients")
    # fact = 0.48
    # width = fact*10; height = fact*8
    # pdf(file = "germancredit_7_predsplot_new_stairs.pdf",
    #     width = width, height = height)
    predsplot(fit7, main = main, casetoshow = newc,
              staircase = TRUE)

    ##
    ##  The case to show is:
    ## $purpose
    ## [1] "u.car"
    ##
    ## $months
    ## [1] 36
    ##
    ## $rate
    ## [1] 2
    ##
    ## $amount
    ## [1] 6000
    ##
    ## $age
    ## [1] 55
    ##
    ## $sex
    ## [1] "F"
    ##
    ## $nclients
    ## [1] 1
    ##
    ##
    ##  Prediction terms for the new case:
    ##                               prediction term    value
    ##                                        months -0.47190
    ##                                       purpose +1.02816
    ##                                        amount -0.25499
    ##                                          rate +0.23763
    ##                                           age +0.41640
    ##                                      nclients +0.03030
    ##                                           sex +0.14143
    ##                                           SUM +1.12701
    ##                                    centercept  0.95998
    ##             Total linear prediction of credit  2.08699
    ##  Total prediction of credit in response units  0.88963
    ##
    ## The glm fit used the logit link function.

    # dev.off()

    ## Figure with profile:
    # pdf(file = "germancredit_7_predsplot_1_dens_profile.pdf",
    #     width = width, height = height)
    predsplot(fit7, main = main, casetoshow=1,
                   displaytype = "density", profile = TRUE)

    ##
    ##  Prediction terms for case 1:
    ##                               prediction term    value
    ##                                        months +0.46584
    ##                                       purpose +0.37611
    ##                                        amount +0.19645
    ##                                          rate -0.25082
    ##                                           age +0.67325
    ##                                      nclients +0.03030
    ##                                           sex +0.14143
    ##                                           SUM +1.63255
    ##                                    centercept  0.95998
    ##             Total linear prediction of credit  2.59253
    ##  Total prediction of credit in response units  0.93038
    ##
    ## The glm fit used the logit link function.

    # dev.off()

# Artificial example to illustrate high correlation:

    credit$x1 = credit$months + credit$nclients
    credit$x2 = credit$months - credit$nclients
    cor(credit$x1,credit$x2) # 0.998199

    ## [1] 0.9981994

    # But minus that for prediction terms!

    fitart <- glm(credit ~ x1 + x2 + purpose + amount + rate + age +
               sex, family=binomial, data = credit)

    ## Figure 7:
    ##
    # fact = 0.48
    # width = fact*10; height = fact*8
    # main = "German credit data with artificial variables x1 and x2"
    # pdf(file = "germancredit_7_artif_predsplot.pdf",
    #     width = width, height = height)
    predsplot(fitart, main = main)

    ##
    ## Prediction terms in the model:
    ##                    prediction term  stdev up/down
    ##                                 x1 1.3670    down
    ##                                 x2 0.9913      up
    ##                            purpose 0.5170
    ##                             amount 0.2638    down
    ##                               rate 0.2732    down
    ##                                age 0.2435      up
    ##                                sex 0.2111
    ##  Total linear prediction of credit 0.8090
    ##
    ## The glm fit used the logit link function.

    # dev.off()

    ## Figure 8:
    ##
    # fact = 0.6
    # width = fact*10; height = fact*8
    # pdf(file = "germancredit_7_artif_predscor.pdf",
    #     width = height, height = height)
    predscor(fitart, sort.by.stdev = FALSE)

    ## Correlation matrix of the prediction terms:
    ##            x1    x2 purpose amount  rate   age   sex
    ## x1       1.00 -1.00   -0.12   0.63  0.07  0.03 -0.09
    ## x2      -1.00  1.00    0.12  -0.62 -0.08 -0.04  0.08
    ## purpose -0.12  0.12    1.00  -0.12 -0.01 -0.03  0.05
    ## amount   0.63 -0.62   -0.12   1.00 -0.27 -0.03 -0.09
    ## rate     0.07 -0.08   -0.01  -0.27  1.00 -0.06 -0.09
    ## age      0.03 -0.04   -0.03  -0.03 -0.06  1.00  0.16
    ## sex     -0.09  0.08    0.05  -0.09 -0.09  0.16  1.00

    # dev.off()