These functions compute the Potential for Change Index for one or multiple (sub-)determinants, the room for improvement (an intermediate estimate), and produce a convenient table with an overview of all (sub-)determinants. Note that for determinant selection purposes, quantitative estimates such as the Potential for Change Index should never be used without also thoroughly inspecting the visualisations of the univariate distributions and the confidence intervals for the associations to the ultimate intervention targets (usually the target behavior or a proxy measure). For this purpose, the Confidence Interval-Based Estimation of Relevance plots can be used (see CIBER()).

determinant_selection_table(
  data,
  determinants,
  target,
  determinantLabels = NULL,
  targetLabel = NULL,
  sortBy = NULL,
  sortByAbs = TRUE,
  decreasing = TRUE,
  digits = 3,
  increasesAreImprovements = TRUE,
  minimum = base::min,
  maximum = base::max,
  center = base::mean,
  weight = stats::cor,
  type = NULL,
  minimumArgs = list(na.rm = TRUE),
  maximumArgs = list(na.rm = TRUE),
  centerArgs = list(na.rm = TRUE),
  weightArgs = list(use = "complete.obs"),
  potentialScale = NULL,
  headingLevel = 3,
  output = behaviorchange::opts$get("tableOutput")
)

determinantSelectionTable_partial(
  x,
  digits = attr(x, "digits"),
  headingLevel = attr(x, "headingLevel"),
  echoPartial = FALSE,
  partialFile = NULL,
  quiet = TRUE,
  ...
)

# S3 method for determinantSelectionTable
knit_print(
  x,
  digits = attr(x, "digits"),
  headingLevel = attr(x, "headingLevel"),
  echoPartial = FALSE,
  partialFile = NULL,
  quiet = TRUE,
  ...
)

# S3 method for determinantSelectionTable
print(
  x,
  digits = attr(x, "digits"),
  headingLevel = attr(x, "headingLevel"),
  output = attr(x, "output"),
  forceKnitrOutput = FALSE,
  ...
)

potential_for_change_index(
  data,
  determinants,
  target,
  increasesAreImprovements = TRUE,
  sampleLevel = FALSE,
  minimum = base::min,
  maximum = base::max,
  center = base::mean,
  weight = stats::cor,
  type = NULL,
  minimumArgs = list(na.rm = TRUE),
  maximumArgs = list(na.rm = TRUE),
  centerArgs = list(na.rm = TRUE),
  weightArgs = list(use = "complete.obs")
)

room_for_improvement(
  x,
  increasesAreImprovements = TRUE,
  sampleLevel = FALSE,
  minimum = base::min,
  maximum = base::max,
  center = base::mean,
  minimumArgs = list(na.rm = TRUE),
  maximumArgs = list(na.rm = TRUE),
  centerArgs = list(na.rm = TRUE),
  varName = NULL
)

Arguments

data

The dataframe containing the variables.

determinants

The name(s) of the determinant(s).

target

The target (e.g. behavior or intention).

determinantLabels, targetLabel

Optionally, labels to use for the (sub-)determinants and the target. The determinantLabels must have the same order as the determinants vector.

sortBy

The column to sort the results by; if not NULL, a number from 1-6 that corresponds to the six columns of the Determinant Selection Table.

sortByAbs

Whether to sort by raw values (FALSE) or their absolute value (TRUE).

decreasing

Whether to sort in decreasing (TRUE) or increasing (FALSE) order.

digits

The number of digits to round to.

increasesAreImprovements

Whether increases are improvements (TRUE) or decreases are improvements (FALSE).

minimum, maximum

The minimum and maximum, as functions that take a vector and return the minimum and maximum scores, as numbers, or as vectors of numbers specifying the minimum and maximum to use for each column in x or determinants, or a lists of functions specifying the functions to use for each column in x or determinants.

center

For the sample-level version, a function that takes a vector and returns the center (e.g. mean, median, etc), or a list of functions specifying the function to use for each column in x or determinants.

weight

The function to return the weight/multiplier to use in the computation.

type

The type of potential for change index. Currently implemented are type '1' and type '2' - see details for more information.

minimumArgs, maximumArgs, centerArgs, weightArgs

lists with arguments to pass to the corresponding functions. Note that these are not vectorized.

potentialScale

The scale with minimum and maximum possible values for the Potential for Change index. If NULL, the minimum is set to 0 and the maximum is set to the highest observed value.

headingLevel

The number of hashes to print in front of the headings when printing while knitting

output

Whether to only output to the viewer (if possible; output='viewer'), or only to the console (output='console'), or to both (output=c('viewer', 'console')). Note that displaying in the viewer requires the htmltools package.

x

For room for improvement, either a numeric vector with scores on a (sub-)determinant, or a data frame with multiple such vectors. For the Determinant Selection Table functions, the object to print/knit.

echoPartial

Whether to show the executed code in the R Markdown partial (TRUE) or not (FALSE).

partialFile

This can be used to specify a custom partial file. The file will have object x available.

quiet

Passed on to knitr::knit() whether it should e chatty (FALSE) or quiet (TRUE).

...

Any additional arguments are passed to the default print method by the print method, and to rmdpartials::partial() when knitting a RMarkdown partial.

forceKnitrOutput

Force knitr output.

sampleLevel

Whether to return sample-level estimates (TRUE) or individual-level estimates (FALSE).

varName

For internal use.

Value

For the individual-level version, a vector or data frame with the same dimensions as provided; for the sample-level version, if a vector is provided, a single number, and if a data frame is provided, a vector with as many values as the data frame has columns. For Determinant Selection Table, a data frame.

Details

The Potential for Change index was developed by Keegan et al. and is a numerical representation of a number of important features in CIBER() plots (for more details, please see the references below). It turned out a similar measure, the Intervention Potential, was developed by Huber & Mosler (2013). The latter uses regression coefficients as weights, which is problematic for a number of reasons (see Crutzen, Peters & Noijen, 2017), and has therefore not been implemented as a default, but it is possible to use regression coefficients by specifying a custom weight function.

The original Potential for Change Index was conceptualized to optimize intervention tailoring and improve the prediction of individual-level intervention effectiveness. A second conceptualization of the Potential for Change Index can facilitate sub-determinant selection.

In addition to using the minimum, maximum, center, and weight functions to specify custom functions, specific types have also been implemented to quickly use a prespecified combination of functions.

The first (type = '1') is computed as follows:

  • For sub-determinants with a positive zero-order correlation with behavior, the sample mean is subtracted from the observed maximum score, and the result is multiplied by the zero-order correlation;

  • For sub-determinants with a negative zero-order correlation with behavior, the sample mean is subtracted from the observed minimum score, and the result is multiplied by the zero-order correlation.

The second (type = '2') is computed as follows:

  • For sub-determinants with a positive zero-order correlation with behavior, the sample mean is subtracted from the .95 quantile of the scores, and the result is multiplied by the squared zero-order correlation (i.e. the proportion of explained variance);

  • For sub-determinants with a negative zero-order correlation with behavior, the sample mean is subtracted from the .05 quantile of the scores, and the result is multiplied by the squared zero-order correlation (i.e. the proportion of explained variance);

The second variant effectively takes the 5% trimmed maximum and minimum, rendering it less sensitive to outliers, penalizes weak associations with behavior more severely, and decreases sensitivity to differences between correlations. These differences should render the second variant a bit more robust over different samples.

The room for improvement is one of the ingredients of the Potential for Change Index or P_delta, a generalized version of the Intervention Potential. The Determinant Selection Table efficiently presents the Potential for Change Indices for a set of (sub-)determinants.

References

Knittle, K. P., Peters, G.-J. Y., Heino, M. T. J., Tobias, R., & Hankonen, N. (2019). Potential for change: New metrics for tailoring and predicting response to behavior change interventions. doi: 10/ghqmg3

Huber, A. C. & Mosler, H.-J. (2013) Determining behavioral factors for interventions to increase safe water consumption: a cross-sectional field study in rural Ethiopia, International Journal of Environmental Health Research, 23:2, 96-107 doi: 10.1080/09603123.2012.699032

Examples

### Get example data
dat <- get(data("BBC_pp15.1", package="behaviorchange"));

### Individual-level version, for one sub-determinant
P_delta_example <-
  behaviorchange::potential_for_change_index(
    data=dat,
    determinants='highDose_attitude',
    target='highDose_intention'
  );

head(P_delta_example);
#> [1]       NA 1.549225       NA       NA       NA 3.098451
hist(P_delta_example);

### Sample-level version
behaviorchange::potential_for_change_index(
  data=dat,
  determinants='highDose_attitude',
  target='highDose_intention',
  sampleLevel = TRUE
);
#> [1] 1.783223

### Individual-level for multiple determinants
P_delta_example <-
  behaviorchange::potential_for_change_index(
    data=dat,
    determinants=c('highDose_attitude', 'highDose_perceivedNorm'),
    target='highDose_intention'
  );
head(P_delta_example);
#>   highDose_attitude highDose_perceivedNorm
#> 1                NA                     NA
#> 2          1.541445               1.516051
#> 3                NA                     NA
#> 4                NA                     NA
#> 5                NA                     NA
#> 6          3.082890               2.274077

### Sample-level version for multiple determinants
behaviorchange::potential_for_change_index(
  data=dat,
  determinants=c('highDose_attitude', 'highDose_perceivedNorm'),
  target='highDose_intention',
  sampleLevel = TRUE
);
#>      highDose_attitude highDose_perceivedNorm 
#>               1.774267               1.596873 

### Get the Potential for Change Index Type 2
behaviorchange::potential_for_change_index(
  data=dat,
  determinants=c('highDose_attitude', 'highDose_perceivedNorm'),
  target='highDose_intention',
  type = '2',
  sampleLevel = TRUE
);
#>      highDose_attitude highDose_perceivedNorm 
#>              0.6445454              0.5516014 

### Get a Determinant Selection Table
behaviorchange::determinant_selection_table(
  data=dat,
  determinants = c('highDose_AttBeliefs_long',
                   'highDose_AttBeliefs_intensity',
                   'highDose_AttBeliefs_euphoria'),
  target = 'highDose_intention',
  sortBy = 6
);
#>                     determinant lower   current upper    weight   p_delta
#> 3  highDose_AttBeliefs_euphoria    -3 0.8356808     3 0.3850852 0.8334474
#> 1      highDose_AttBeliefs_long    -3 1.2685185     3 0.1801973 0.2915168
#> 2 highDose_AttBeliefs_intensity    -1 2.0418605     3 0.1179815 0.1080198

### R Markdown partials can smoothly be included in RMarkdown documents
behaviorchange::determinantSelectionTable_partial(
  behaviorchange::determinant_selection_table(
    data=dat,
    determinants = c('highDose_AttBeliefs_long',
                     'highDose_AttBeliefs_intensity',
                     'highDose_AttBeliefs_euphoria'),
    target = 'highDose_intention',
    sortBy = 6
  )
);

#> No viewer found, probably documenting or testing
#> 
#> 
#> <div style="display:block;clear:both;" class="behaviorchange-determinant-selection-table-start"></div>
#> <div class="behaviorchange-determinant-selection-table-container">
#> 
#> 
#> 
#> 
#> 
#>  Determinant Selection Table
#> 
#> 
#> 
#> <table class="table" style="font-family: arial; margin-left: auto; margin-right: auto;">
#>  <thead>
#>   <tr>
#>    <th style="text-align:left;"> (Sub-)determinant </th>
#>    <th style="text-align:left;"> Lower bound </th>
#>    <th style="text-align:left;"> Current </th>
#>    <th style="text-align:left;"> Upper bound </th>
#>    <th style="text-align:left;"> Weight </th>
#>    <th style="text-align:left;"> Potential for Change Index </th>
#>   </tr>
#>  </thead>
#> <tbody>
#>   <tr>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">highDose_AttBeliefs_euphoria</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">-3</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">0.836</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">3</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">0.385</span> </td>
#>    <td style="text-align:left;"> <span style=" font-weight: bold;    color: rgba(68, 1, 84, 1) !important;padding: 5px; font-size: 16px;">0.833</span> </td>
#>   </tr>
#>   <tr>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">highDose_AttBeliefs_long</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">-3</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">1.269</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">3</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">0.18</span> </td>
#>    <td style="text-align:left;"> <span style=" font-weight: bold;    color: rgba(32, 164, 134, 1) !important;padding: 5px; font-size: 11px;">0.292</span> </td>
#>   </tr>
#>   <tr>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">highDose_AttBeliefs_intensity</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">-1</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">2.042</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">3</span> </td>
#>    <td style="text-align:left;"> <span style="     padding: 5px; ">0.118</span> </td>
#>    <td style="text-align:left;"> <span style=" font-weight: bold;    color: rgba(112, 207, 87, 1) !important;padding: 5px; font-size: 9px;">0.108</span> </td>
#>   </tr>
#> </tbody>
#> </table>
#> 
#> 
#> 
#> </div>
#> <div style="display:block;clear:both;" class="behaviorchange-determinant-selection-table-end"></div>

### Room for improvement for one variable
head(
  room_for_improvement(
    dat$highDose_AttBeliefs_long
  )
);
#> [1] NA  1 NA NA NA  3

room_for_improvement(
  dat$highDose_AttBeliefs_long,
  sampleLevel = TRUE
);
#> [1] 1.731481

### For multiple (sub-)determinants
head(
  room_for_improvement(
    dat[, c('highDose_AttBeliefs_long',
            'highDose_AttBeliefs_intensity',
            'highDose_AttBeliefs_euphoria')]
  )
);
#>   highDose_AttBeliefs_long highDose_AttBeliefs_intensity
#> 1                       NA                            NA
#> 2                        1                             1
#> 3                       NA                            NA
#> 4                       NA                            NA
#> 5                       NA                            NA
#> 6                        3                             2
#>   highDose_AttBeliefs_euphoria
#> 1                           NA
#> 2                            2
#> 3                           NA
#> 4                           NA
#> 5                           NA
#> 6                            5

room_for_improvement(
  dat[, c('highDose_AttBeliefs_long',
          'highDose_AttBeliefs_intensity',
          'highDose_AttBeliefs_euphoria')],
  sampleLevel = TRUE
);
#>   highDose_AttBeliefs_long highDose_AttBeliefs_intensity
#> 1                 1.731481                     0.9581395
#>   highDose_AttBeliefs_euphoria
#> 1                     2.164319