cNORM works 'out of the box' in many application scenarios, especially with sufficiently large datasets and when the explanatory variable accounts for a substantial amount of variance of the raw scores (for example, when there's a clear age trend). However, there are cases that are more challenging. We strongly recommend checking the generated solutions for plausibility and manually adjusting parameters if necessary. Similar to factor analyses, model selection is a multi-stage process typically requiring the calculation and comparison of different models based on various quality criteria. For cNORM, there are three main quality criteria: R2, model simplicity, and model plausibility/consistency. The latter must be particularly considered at the model boundaries.
In summary:
Occasionally, inconsistent models may occur, particularly in extreme performance ranges, or in tests with strong floor or ceiling effects. These inconsistencies manifest, for example, in intersecting percentile lines ('plotPercentiles()') or when the modeling process generates corresponding warnings ('checkConsistency()'). Since version cNORM 3.2, automatic checks have been built into the 'cnorm()' function to help ensure that models with inconsistencies are not returned. However, these are only rough checks, and in individual cases, intersecting percentile lines may still occur.
Possible solutions:
# Plots a percentile diagram of the current model
plotPercentiles(model, data)
# Plots a series of percentile diagrams for up to 10 predictors
plotPercentileSeries(model, data, end=10)
Our simulations indicate that relatively reliable models can be calculated with as few as 50 cases per age group (see figure). Nevertheless, we recommend maintaining a minimum sample size of 100 per age group (or per width of the window when using the 'sliding window' approach). This recommendation is primarily based on the fact that the representativeness of the normative sample is a crucial influencing factor. Achieving representativeness is often difficult with group sizes of less than 100 individuals. When the sample size is too small, not only does it reduce the power of the applied statistical procedures, but it also becomes challenging to stratify the sample across all relevant variables.
While cNORM can partially compensate for minor violations of representativeness or small sample sizes in individual age groups (since the models are calculated based on the entire dataset), establishing a high-quality normative sample should remain a priority when generating test norms.
Possible solutions:
Since version 1.1.8, cNORM automatically uses polynomial regression to assess the relationsship between the raw scores and the explanatory variable. If there is only a weak relationship, cNORM generates a warning message. In such cases, it's worth considering whether including the explanatory variable in the calculation of norms is truly meaningful, or whether a single norm table might suffice. When the explanatory variable accounts for only a small proportion of variance, the models may sometimes be unstable, and the target of R2 ≥ .99 for the overall model might not be achieved.
Possible solutions:
The model likely exhibits overfitting, for example, because the parameter 't' was set too high, the explanatory variable accounts for limited variance, too many predictors were used, or the scale generally lacks reliability, etc. Wavy percentile lines can also result from small sample sizes in individual groups, as in the above example with n = 50. In some cases, wavy percentile lines might also indicate that the cNORM package is reaching its performance limits. Usually, it's advisable to use a more simply structured model with fewer terms.
Possible solutions:
In the above example, the parameter 't' was set to t = 5 with a group size of only 50. When reducing the parameter to t = 3 and simultaneously decreasing the number of terms from 21 to just 7, the following model results:
You could use discrete age groups instead. When specifying a grouping variable in the 'cnorm()' function, ranking is performed using this grouping variable. However, for the modeling to work properly, the grouping variable must correspond to the age variable. This means: The values of the grouping variable should reflect the mean age of the respective age groups.
Possible solutions:
# Creates a grouping variable with 10 equal-sized groups
# from a continuous age variableADHD$group <- getGroups(ADHD$age, n = 10)
Cases can be weighted using the 'weights' parameter. Additionally, cNORM includes the 'computeWeights()' function for generating weights using raking. This can help reduce the effect of unbalanced normative samples.
![]() |
Jamovi |
Overview |
![]() |