From 8cf937705600e0ae721e949daa2337739933aa99 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Thu, 23 Mar 2023 09:37:00 +0100 Subject: [PATCH] Update site --- docs/articles/manual/manual.html | 141 +++++++++--------- .../figure-html/plot-v2-1.png | Bin 73506 -> 74167 bytes docs/news/index.html | 2 +- docs/pkgdown.yml | 2 +- docs/search.json | 2 +- 5 files changed, 75 insertions(+), 72 deletions(-) diff --git a/docs/articles/manual/manual.html b/docs/articles/manual/manual.html index 5016223..f934f6b 100644 --- a/docs/articles/manual/manual.html +++ b/docs/articles/manual/manual.html @@ -88,7 +88,7 @@

Abstract

-

Many longitudinal studies collect data that have irregular observation times, often requiring the application of linear mixed models with time-varying outcomes. This paper presents an alternative that splits the quantitative analysis into two steps. The first step converts irregularly observed data into a set of repeated measures through the broken stick model. The second step estimates the parameters of scientific interest from the repeated measurements at the subject level. The broken stick model approximates each subject’s trajectory by a series of connected straight lines. The breakpoints, specified by the user, divide the time axis into consecutive intervals common to all subjects. Specification of the model requires just three variables: time, measurement and subject. The model is a special case of the linear mixed model, with time as a linear \(B\)-spline and subject as the grouping factor. The main assumptions are: subjects are exchangeable, trajectories between consecutive breakpoints are straight, random effects follow a multivariate normal distribution, and unobserved data are missing at random. The R package brokenstick v2.4.0 offers tools to calculate, predict, impute and visualise broken stick estimates. The package supports two optimisation methods, including options to constrain the variance-covariance matrix of the random effects. We demonstrate six applications of the model: detection of critical periods, estimation of the time-to-time correlations, profile analysis, curve interpolation, multiple imputation and personalised prediction of future outcomes by curve matching.

+

Many longitudinal studies collect data that have irregular observation times, often requiring the application of linear mixed models with time-varying outcomes. This paper presents an alternative that splits the quantitative analysis into two steps. The first step converts irregularly observed data into a set of repeated measures through the broken stick model. The second step estimates the parameters of scientific interest from the repeated measurements at the subject level. The broken stick model approximates each subject’s trajectory by a series of connected straight lines. The breakpoints, specified by the user, divide the time axis into consecutive intervals common to all subjects. Specification of the model requires just three variables: time, measurement and subject. The model is a special case of the linear mixed model, with time as a linear \(B\)-spline and subject as the grouping factor. The main assumptions are: subjects are exchangeable, trajectories between consecutive breakpoints are straight, random effects follow a multivariate normal distribution, and unobserved data are missing at random. The R package brokenstick v2.5.0 offers tools to calculate, predict, impute and visualise broken stick estimates. The package supports two optimisation methods, including options to constrain the variance-covariance matrix of the random effects. We demonstrate six applications of the model: detection of critical periods, estimation of the time-to-time correlations, profile analysis, curve interpolation, multiple imputation and personalised prediction of future outcomes by curve matching.

@@ -96,12 +96,12 @@

Most longitudinal studies plan data collection to occur at a fixed set of time points. In practice, the realized times can differ — sometimes substantially — from the scheduled times. There may be many reasons for such differences. For example, we planned a visit at the weekend or during a holiday, the subject did not show up, the measurement device was out of order, or the investigator fell ill. Varying observation times may also result from combining data from multiple studies, each collected according to its own design. Timing variation can be substantial in observational studies, especially if the survey lacks a pre-specified schedule. Longitudinal data with timing differences between subjects are said to be irregular.

Irregular observation times present significant challenges for quantitative analysis. For example, it is not easy to calculate the time-to-time correlation matrix if the data spread thinly over time. It might also be complex to predict the future from past data if subject times differ. Observation times may also relate to the process of interest. For example, more severely ill patients get measured more frequently; unmotivated cohort members respond more rarely, and so on. Conventional methods like MANOVA, regression or cluster analysis break down if observation times differ or if drop-out is selective.

-

While irregular observation times occur all over science, there is no universal or principled approach to resolve the problem. One straightforward fix is to take only those dates for which data are available (e.g., dates when stocks are traded), thus ignoring the times when markets are closed. One may also create bins of time intervals around the planned times, thereby ignoring within-period differences. Another ad-hoc method predicts the value at the scheduled time from neighboring data, e.g., by linear interpolation or smoothing, typically reducing the variability in the data. Some quick fixes create data sets where the timing problem seems to have “gone away”, which may tempt the analyzingt to ignore the potential effects of data patch-up on the substantive conclusions. While convenient and straightforward, the thoughtless application of these fixes introduces significant spurious relations over time, especially if the spacing of observations is highly irregular (Rehfeld et al. 2011). Binning can lead to “surprisingly large” biases (Towers 2014). If timing variation is related to the outcome of interest, these methods may result in biased estimates and exaggerated claims (Pullenayegum and Lim 2016).

-

The linear mixed model for longitudinal data (Laird and Ware 1982; Fitzmaurice, Laird, and Ware 2011) is the standard for analyzing irregular data. The model represents each subject’s observed curve by a parametric function of time. The parameter estimates of this function are specific to each subject and modeled as random effects. The linear mixed model is beneficial for irregular data. It borrows strength across different realizations of the same process, summarizing each trajectory by a small number of parameters that vary over subjects. The analyst can break down the distribution of these random effects as a function of individual characteristics. The linear mixed model is attractive when the number of measurements differs between individuals or when the measurements are taken at different times.

-

This paper explores the use of the broken stick model to transform irregularly observed data into repeated measures. The broken stick model describes a curve by a series of connected straight lines. The model has a long history and is known under many other names, among others, segmented straight lines (Bellman and Roth 1969), piece-wise regression (Toms and Lesperance 2003), structural change models (Bai and Perron 2003), broken line smoothing (Koutsoyiannis 2000) and segmented regression (Lerman 1980). The term broken stick goes back to at least MacArthur (1957), who used it in an analogy to indicate the abundance of species. Most of the literature on the broken stick model concentrates on the problem of finding optimal times at which the lines should connect. Instead, the present paper will focus on the problem of summarizing irregular individual trajectories by estimates made at a pre-specified time grid. This time grid is identical for all individuals, but it need not be equidistant. Our model formulation is a special case of the linear mixed model, with time modeled as a set of random effects coded as a linear \(B\)-spline and subjects as the grouping factor. The output of the transformation is a set of repeated measures, where every subject obtains a score on every time point.

-

Many R packages offer tools for interpolation. The splines package ( Core Team 2020) and the akima package (Akima et al. 2021) contains classic interpolation methods for one- and two-dimensional smoothing. Most contributed packages concentrate on time series or spatial interpolation. See Li and Heap (2014) and Lepot, Aubin, and Clemens (2017) for overviews of the different concepts and methodologies. Most interpolation techniques rely on neighboring information, in time, space or both. The broken stick model addresses the problem where many independent replications provide short irregular multivariate time series, say of 5-30 time points. The scientific interest is to dynamically predict and update future observations. The model applies the linear mixed model to increase stability for such series by borrowing information across replicates. As there are no satisfactory solutions to this problem, the brokenstick package intends to fill this gap. Package brokenstick is available from the Comprehensive R Archive Network at https://CRAN.R-project.org/package=brokenstick.

-

Substantive researchers often favor repeated measures over the use of linear mixed models because of their simplicity. For example, we can easily fit a subject-level model to predict future outcomes conditional on earlier data with repeated measures data. While such simple regression models may be less efficient than modelling the complete data (Diggle et al. 2002, sec. 6.1), increased insight may be more valuable than increased precision.

-

The broken stick model requires a specification of a sensible set of time points at which the measurements ideally should have been taken. For each subject, the model predicts or imputes hypothetical observations at those times, so the substantive analysis applies to the repeated measures instead of the irregular data. This strategy is akin to Diggle’s multi-stage model-fitting approach (Diggle 1988). The envisioned two-step analytic process aims to provide the best of both worlds.

+

While irregular observation times occur all over science, there is no universal or principled approach to resolve the problem. One straightforward fix is to take only those dates for which data are available (e.g., dates when stocks are traded), thus ignoring the times when markets are closed. One may also create bins of time intervals around the planned times, thereby ignoring within-period differences. Another ad-hoc method predicts the value at the scheduled time from neighboring data, e.g., by linear interpolation or smoothing, typically reducing the variability in the data. Some quick fixes create data sets where the timing problem seems to have “gone away”, which may tempt the analyzingt to ignore the potential effects of data patch-up on the substantive conclusions. While convenient and straightforward, the thoughtless application of these fixes introduces significant spurious relations over time, especially if the spacing of observations is highly irregular (Rehfeld et al. 2011). Binning can lead to “surprisingly large” biases (Towers 2014). If timing variation is related to the outcome of interest, these methods may result in biased estimates and exaggerated claims (Pullenayegum and Lim 2016).

+

The linear mixed model for longitudinal data (Laird and Ware 1982; Fitzmaurice, Laird, and Ware 2011) is the standard for analyzing irregular data. The model represents each subject’s observed curve by a parametric function of time. The parameter estimates of this function are specific to each subject and modeled as random effects. The linear mixed model is beneficial for irregular data. It borrows strength across different realizations of the same process, summarizing each trajectory by a small number of parameters that vary over subjects. The analyst can break down the distribution of these random effects as a function of individual characteristics. The linear mixed model is attractive when the number of measurements differs between individuals or when the measurements are taken at different times.

+

This paper explores the use of the broken stick model to transform irregularly observed data into repeated measures. The broken stick model describes a curve by a series of connected straight lines. The model has a long history and is known under many other names, among others, segmented straight lines (Bellman and Roth 1969), piece-wise regression (Toms and Lesperance 2003), structural change models (Bai and Perron 2003), broken line smoothing (Koutsoyiannis 2000) and segmented regression (Lerman 1980). The term broken stick goes back to at least MacArthur (1957), who used it in an analogy to indicate the abundance of species. Most of the literature on the broken stick model concentrates on the problem of finding optimal times at which the lines should connect. Instead, the present paper will focus on the problem of summarizing irregular individual trajectories by estimates made at a pre-specified time grid. This time grid is identical for all individuals, but it need not be equidistant. Our model formulation is a special case of the linear mixed model, with time modeled as a set of random effects coded as a linear \(B\)-spline and subjects as the grouping factor. The output of the transformation is a set of repeated measures, where every subject obtains a score on every time point.

+

Many R packages offer tools for interpolation. The splines package (Team, n.d.) and the akima package (Akima et al. 2021) contains classic interpolation methods for one- and two-dimensional smoothing. Most contributed packages concentrate on time series or spatial interpolation. See Li and Heap (2014) and Lepot, Aubin, and Clemens (2017) for overviews of the different concepts and methodologies. Most interpolation techniques rely on neighboring information, in time, space or both. The broken stick model addresses the problem where many independent replications provide short irregular multivariate time series, say of 5-30 time points. The scientific interest is to dynamically predict and update future observations. The model applies the linear mixed model to increase stability for such series by borrowing information across replicates. As there are no satisfactory solutions to this problem, the brokenstick package (van Buuren 2023) intends to fill this gap. Package brokenstick is available from the Comprehensive R Archive Network at https://CRAN.R-project.org/package=brokenstick.

+

Substantive researchers often favor repeated measures over the use of linear mixed models because of their simplicity. For example, we can easily fit a subject-level model to predict future outcomes conditional on earlier data with repeated measures data. While such simple regression models may be less efficient than modelling the complete data (Diggle et al. 2002, sec. 6.1), increased insight may be more valuable than increased precision.

+

The broken stick model requires a specification of a sensible set of time points at which the measurements ideally should have been taken. For each subject, the model predicts or imputes hypothetical observations at those times, so the substantive analysis applies to the repeated measures instead of the irregular data. This strategy is akin to Diggle’s multi-stage model-fitting approach (Diggle 1988). The envisioned two-step analytic process aims to provide the best of both worlds.

Some applications of the broken stick model are:

-

The original motivation for developing the broken stick model was to facilitate the statistical analysis and testing of critical ages in the onset of childhood obesity (de Kroon et al. 2010), with extensions to multiple imputation (van Buuren 2018b). There is good support in R for fitting child growth data. We mention some related approaches. Methods for estimating growth references with parametric models are gamlss() from gamlss (Stasinopoulos and Rigby 2007) and its Bayesian incarnation bamlss() from bamlss (Umlauf et al. 2021). Nonparametric alternatives that estimate quantiles directly are rq() from quantreg (Koenker et al. 2018) and expectreg.ls() from expectreg (Otto-Sobotka et al. 2021). Methods for modelling and smoothing growth curves fit trajectories per child include smooth.basisPar() from fda (Ramsay, Graves, and Hooker 2021), gam() from mgcv (Wood 2011), loess() and smooth.spline() from base stats ( Core Team 2020). Models that smooth by borrowing strength across children are face.sparse() from face (Xiao et al. 2021), lmer() from lme4 (Bates et al. 2015), and sitar() from sitar (Cole 2022). The broken stick model fits in the latter tradition, and features an intuitive parametrization of each individual growth curve as a series of connected straight lines. See Anderson et al. (2019) for an overview and comparison of these methods.

-

The present paper highlights various computational tools from the brokenstick v2.4.0 package. The package contains tools to fit the broken stick model to data, export the fitted model’s parameters, create imputed values of the model, and predict broken stick estimates for new data. Also, the text illustrates how the tool helps to solve various analytic problems.

+

The original motivation for developing the broken stick model was to facilitate the statistical analysis and testing of critical ages in the onset of childhood obesity (de Kroon et al. 2010), with extensions to multiple imputation (van Buuren 2018b). There is good support in R for fitting child growth data. We mention some related approaches. Methods for estimating growth references with parametric models are gamlss() from gamlss (Stasinopoulos and Rigby 2007) and its Bayesian incarnation bamlss() from bamlss (Umlauf et al. 2021). Nonparametric alternatives that estimate quantiles directly are rq() from quantreg (Koenker et al. 2018) and expectreg.ls() from expectreg (Otto-Sobotka et al. 2021). Methods for modelling and smoothing growth curves fit trajectories per child include smooth.basisPar() from fda (Ramsay, Graves, and Hooker 2021), gam() from mgcv (Wood 2011), loess() and smooth.spline() from base stats (Team, n.d.). Models that smooth by borrowing strength across children are face.sparse() from face (Xiao et al. 2021), lmer() from lme4 (Bates et al. 2015), and sitar() from sitar (Cole 2022). The broken stick model fits in the latter tradition, and features an intuitive parametrization of each individual growth curve as a series of connected straight lines. See Anderson et al. (2019) for an overview and comparison of these methods.

+

The present paper highlights various computational tools from the brokenstick v2.5.0 package. The package contains tools to fit the broken stick model to data, export the fitted model’s parameters, create imputed values of the model, and predict broken stick estimates for new data. Also, the text illustrates how the tool helps to solve various analytic problems.

2 Illustration of broken stick model

-

As a first step, let us study the variation in the age of measurement of 200 children from the SMOCC study (Herngreen et al. 1994). Lokku et al. (2020) suggest the abacus plot to visualize this variation.

+

As a first step, let us study the variation in the age of measurement of 200 children from the SMOCC study (Herngreen et al. 1994). Lokku et al. (2020) suggest the abacus plot to visualize this variation.

Abacus plot of observation times for the first 20 children of the SMOCC data. Data collection was done through 10 waves. Each dot represents the age at which an observation was made. The variability in timing between children rises with age.

@@ -139,7 +139,7 @@

Knot values are rounded to simplify the presentation. Figure 2 shows the individual trajectories of three children. The blue points coincide with the observed data, whereas the red curves are calculated according to the broken stick model.

There are two fitted models. The simpler model (top) uses just two line segments. The first line starts at birth and ends at the age of exactly 1 year. The second line spans the period between 1 to 2 years. Note that the two lines connect at the breakpoint, the age of 1 year. The red curves for the two-line model are a crude approximation to the data.

We can create a better model by setting breakpoints equal to the scheduled ages. Since there are 10 scheduled ages, we construct nine straight lines. In contrast to the two-line model, the nine-line broken stick model is sensitive to small bumps in the observed trajectory and closely fits the empirical data. The residual variance of the nine-line model is low (0.059), and the proportion of explained variance in SDS is high (0.98).

-

While the observation times in the data differ between children, the broken stick curves use identical time points across subjects. The idea is now that we can add the broken stick estimates to the child-level data by a long-to-wide conversion and analyze supplemented columns as repeated measures. A repeated measures analysis is usually simpler than the equivalent for the temporally misaligned data. For example, it is easy to calculate mean profiles for arbitrary groups, estimate the time-to-time covariance matrix, or build predictive models at the child level. See Hand and Taylor (1987) for a lucid overview of linear techniques for repeated measures.

+

While the observation times in the data differ between children, the broken stick curves use identical time points across subjects. The idea is now that we can add the broken stick estimates to the child-level data by a long-to-wide conversion and analyze supplemented columns as repeated measures. A repeated measures analysis is usually simpler than the equivalent for the temporally misaligned data. For example, it is easy to calculate mean profiles for arbitrary groups, estimate the time-to-time covariance matrix, or build predictive models at the child level. See Hand and Taylor (1987) for a lucid overview of linear techniques for repeated measures.

@@ -149,7 +149,7 @@

3.1 Notation

-

We adopt the notation of Fitzmaurice, Laird, and Ware (2011). Let \(Y_{ij}\) denote the response variable for the \(i^{\rm th}\) subject on the \(j^{\rm th}\) measurement occasion at time \(t_{ij}\). Data are collected in a sample of \(N\) persons \(i=1,\dots,N\). Let repeated measurements for the \(i^{\rm th}\) subject be grouped as

+

We adopt the notation of Fitzmaurice, Laird, and Ware (2011). Let \(Y_{ij}\) denote the response variable for the \(i^{\rm th}\) subject on the \(j^{\rm th}\) measurement occasion at time \(t_{ij}\). Data are collected in a sample of \(N\) persons \(i=1,\dots,N\). Let repeated measurements for the \(i^{\rm th}\) subject be grouped as

\[ Y_i = \left( \begin{array} {l} Y_{i1} \\ Y_{i2} \\ \vdots \\ Y_{in_i} \end{array} \right), \quad i = 1, \dots, N. \]

@@ -175,7 +175,7 @@

\kappa_0 = \kappa_1 < \dots < \kappa_k < \kappa_{k+1} \]

The internal knots \(\kappa_1, \dots, \kappa_k\) correspond to the set of ages for which we obtain broken stick estimates, and it could be specified by the user. The left boundary knot \(\kappa_0 = \kappa_1\) is left-anchored to the minimum time \(\min(t_{ij})\) in the data. This point defines the starting event of the participant, such as birth or study enrollment. The right hand boundary knot is \(\kappa_{k+1} \geq \max(t_{ij})\).

-

The second-order \(B\)-spline (de Boor 1978, 32),

+

The second-order \(B\)-spline (de Boor 1978, 32),

\[ H_s(t) = \left\{ \begin{array} {l@{\quad,\quad}l} (t-\kappa_{s-1})/(\kappa_s - \kappa_{s-1}) & \kappa_{s-1} < t \leq \kappa_s,\\ @@ -184,7 +184,7 @@

\end{array} \right. \]

is applied to \(t_{ij}\) to obtain \((k+1)\) transformed variables \(x_{is} = t_{ij}\) with \(s = 1,\dots,k+1\). These variables can conveniently be grouped into the \(n_i \times (k+1)\) matrix of covariates \(X_i = (x_{i1}, \dots, x_{ik}, x_{i(k+1)})\). Each row in \(X_i\) has only one or two non-zero elements, which sum to 1.

-

Using this \(X_i\), the broken stick model is a special case (with \(Z_i = X_i\)) of the two-stage random-effects model (Laird and Ware 1982)

+

Using this \(X_i\), the broken stick model is a special case (with \(Z_i = X_i\)) of the two-stage random-effects model (Laird and Ware 1982)

\[ Y_i = X_i\beta + X_ib_i + \epsilon_i \]

@@ -205,7 +205,7 @@

3.3 Model assumptions

-

At the person level, we assume \(b_i \sim N(0, \Omega)\), i.e., the random coefficients of the subjects have a multivariate normal distribution with zero mean and a \((k+1) \times (k+1)\) covariance matrix \(\Omega\). The base model allows the elements of \(\Omega\) to vary freely. For time-dependent data, constrained versions for \(\Omega\) are also of interest (Fitzmaurice, Laird, and Ware 2011, Ch. 7). Section 4.2 highlights two such extensions. We also assume that the covariance between \(b_i\) and \(\epsilon_i\) is zero. For simplicity, this paper is restricted to the case where \(X_i\) includes only time, and no other covariates.

+

At the person level, we assume \(b_i \sim N(0, \Omega)\), i.e., the random coefficients of the subjects have a multivariate normal distribution with zero mean and a \((k+1) \times (k+1)\) covariance matrix \(\Omega\). The base model allows the elements of \(\Omega\) to vary freely. For time-dependent data, constrained versions for \(\Omega\) are also of interest (Fitzmaurice, Laird, and Ware 2011, Ch. 7). Section 4.2 highlights two such extensions. We also assume that the covariance between \(b_i\) and \(\epsilon_i\) is zero. For simplicity, this paper is restricted to the case where \(X_i\) includes only time, and no other covariates.

The broken stick model builds upon three main modeling assumptions:

  • The trajectory between break ages follows a straight line. This assumption may fail for processes that are convex or concave in time. For example, human height growth in centimeters is concave in time, so setting breakpoints far apart introduces a systematic negative bias. Modeling height SDS instead of raw height will prevent this bias.
  • @@ -222,7 +222,7 @@

    \[ [Y_{i,\kappa_s}^{\rm lo}, Y_{i,\kappa_s}^{\rm hi}] = \gamma_{is} \pm t_{(1-\alpha/2;N-1)}\sigma, \] -where \(t_{(1-\alpha/2;N-1)}\) is the \(100(1-\alpha/2)\) percentile of Student’s \(t\)-distribution with \(N - 1\) degrees of freedom. For example, the 50% prediction interval \(\gamma_{is} \pm 0.68\sigma\) will contain 50% of true values. For normal \(Y_i\), the length of the 50% prediction interval is equivalent to the interquartile range (IQR). If the residual variation \(\sigma^2\) is small (say \(\sigma^2 < 0.1\)), the IQR is about 0.22, so half of the true values will be within 0.22 SD of \(\gamma_{is}\), a small difference. For large \(\sigma^2\) (e.g., \(\sigma^2 > 0.2\)), the \(\gamma_{i}\) vector is a smoothed representation of \(Y_{i}\). While smoothness amplifies low-frequency features of the trajectories, it could also introduce biases in the subsequent analysis by suppressing high-frequency variation. In that case, the analyst needs to check whether this reduction in variation does not affect the parameters of substantive interest. We may restore high-frequency variation by adding random draws from the residual distribution \(N(0, \sigma^2)\). From there, it is a small step to multiple imputation, a well-developed methodology for drawing valid inferences from incomplete data (Rubin 1987; van Buuren 2018b).

    +where \(t_{(1-\alpha/2;N-1)}\) is the \(100(1-\alpha/2)\) percentile of Student’s \(t\)-distribution with \(N - 1\) degrees of freedom. For example, the 50% prediction interval \(\gamma_{is} \pm 0.68\sigma\) will contain 50% of true values. For normal \(Y_i\), the length of the 50% prediction interval is equivalent to the interquartile range (IQR). If the residual variation \(\sigma^2\) is small (say \(\sigma^2 < 0.1\)), the IQR is about 0.22, so half of the true values will be within 0.22 SD of \(\gamma_{is}\), a small difference. For large \(\sigma^2\) (e.g., \(\sigma^2 > 0.2\)), the \(\gamma_{i}\) vector is a smoothed representation of \(Y_{i}\). While smoothness amplifies low-frequency features of the trajectories, it could also introduce biases in the subsequent analysis by suppressing high-frequency variation. In that case, the analyst needs to check whether this reduction in variation does not affect the parameters of substantive interest. We may restore high-frequency variation by adding random draws from the residual distribution \(N(0, \sigma^2)\). From there, it is a small step to multiple imputation, a well-developed methodology for drawing valid inferences from incomplete data (Rubin 1987; van Buuren 2018b).

    If \(n_i \gg k\) then the broken stick model provides a parsimonious representation of the measurements. Reversely, if \(n_i \ll k\) then the model infers plausible values for subject \(i\) by building strength across persons. The broken stick model converts \(n_i\) irregularly observed measurements into a new set of \(k\) values \(\gamma_{is}\) at common ages \(\kappa_1, ..., \kappa_k\), \(s = 1,\dots, k\).

    Since each row in \(X_i\) sums to unity, the broken stick model does not have a global intercept. The linear \(B\)-spline coding effectively replaces the global random intercept term by \(k + 1\) local intercepts, one at each break age. The local intercept summarizes the information available in the adjacent left and right age intervals and ignores any information beyond the two adjacent knots. The broken stick estimates are thus primarily local. Outcome data observed outside the two adjacent age intervals influence the broken stick estimates only through the subject-level part of the model, in particular through \(\Omega\).

@@ -275,7 +275,7 @@

4.2 Estimation steps explained

-

We may break up the estimation process into two main steps. The first step calculates the matrix of \(B\)-splines for the time variable age by the core splines::bs() ( Core Team 2020) function:

+

We may break up the estimation process into two main steps. The first step calculates the matrix of \(B\)-splines for the time variable age by the core splines::bs() (Team, n.d.) function:

 library("splines")
 data <- brokenstick::smocc_200
@@ -293,7 +293,7 @@ 

## [6,] 0.000 0.494 0.5058 0 0

The numerical example shows that the bs() function transforms the age variable into five columns, the \(B\)-spline basis, with names like age_0 and age_0.5. If age coincides with one of these (e.g., as in the top row), then the corresponding column receives a 1. In all other cases, age distributes over two adjacent columns. Setting degree = 1 specifies a \(B\)-spline and gives the broken stick model its name and its characteristic shape.

Although not strictly needed, all applications in this paper assume that the left boundary knot marks the start of time, e.g., birth or day of enrollment. There are some subtleties in using splines::bs() to create a linear \(B\)-spline basis. Matrix X has values in the range \([0, 1]\) and a maximum of two non-zero values per row that sum to \(1\). These conditions require that Boundary.knots span at least the range of the data. This requirement is easy to achieve by setting Boundary.knots = range(data$age), which is done by default. Also, we need to ensure that the range of knots is not outside Boundary.knots. We may achieve that by setting Boundary.knots to include at least range(knots). In practice, the user does not need to worry about boundaries since the brokenstick() function takes care of both conditions by expanding the boundary range when needed. The primary reason for setting explicit boundaries is to make them independent of the data.

-

The second step is to specify the model and estimate its parameters. We have two methods for this: "kr" and "lmer". Method "lmer" relies on the popular function lme4::lmer() (Bates et al. 2015) to fit a linear mixed normal model.

+

The second step is to specify the model and estimate its parameters. We have two methods for this: "kr" and "lmer". Method "lmer" relies on the popular function lme4::lmer() (Bates et al. 2015) to fit a linear mixed normal model.

 data <- cbind(brokenstick::smocc_200[, c("id", "age", "hgt_z")], X)
 ctl_lmer <- lme4::lmerControl(
@@ -315,11 +315,11 @@ 

## 10002 -0.278 -0.206 -0.46 -0.477 -0.223 ## 10003 1.681 1.969 1.28 1.115 -0.256

The calculation time of lme4::lmer() rapidly increases with the number of random effects. More than ten random effects (knots) takes significant time, and beyond 15 knots is generally impossible to fit. For example, using a dataset with 33,000 records and 2,600 individuals, an M1 Max processor takes 8 seconds (5 knots), 107 seconds (9 knots), 403 seconds (12 knots) and 1172 seconds (15 knots).

-

The brokenstick package provides another alternative, the Kasim-Raudenbush (KR) sampler (Kasim and Raudenbush 1998). The method simulates draws from the posterior distributions of parameters from a two-level normal model with heterogeneous within-subject variances. The speed of the Kasim-Raudenbush sampler is almost insensitive to the number of random effects and depends primarily on the total number of iterations and somewhat on sample size. Execution of the KR method for the same problem takes 15 seconds (5 knots), 17 seconds (9 knots), 19 seconds (12 knots) and 20 seconds (15 knots). The method is available as the function kr() in the brokenstick package and is the default since version 2.0.0. The control_kr() function tweaks estimation options:

+

The brokenstick package provides another alternative, the Kasim-Raudenbush (KR) sampler (Kasim and Raudenbush 1998). The method simulates draws from the posterior distributions of parameters from a two-level normal model with heterogeneous within-subject variances. The speed of the Kasim-Raudenbush sampler is almost insensitive to the number of random effects and depends primarily on the total number of iterations and somewhat on sample size. Execution of the KR method for the same problem takes 15 seconds (5 knots), 17 seconds (9 knots), 19 seconds (12 knots) and 20 seconds (15 knots). The method is available as the function kr() in the brokenstick package and is the default since version 2.0.0. The control_kr() function tweaks estimation options:

 ctl_kr <- control_kr()
 mod_kr <- kr(y = data$hgt_z, x = X, g = data$id, control = ctl_kr)
-

The call to control_kr() produces a list with settings for the sampler according to the conventions of the coda package (Plummer et al. 2006). The defaults in control_kr() should be reasonable across a wide range of cases. The list component mod_kr$mod contains various objects of class "mcmc" with the sampling history and detailed results. For example, inspect the fixed effect estimates as

+

The call to control_kr() produces a list with settings for the sampler according to the conventions of the coda package (Plummer et al. 2006). The defaults in control_kr() should be reasonable across a wide range of cases. The list component mod_kr$mod contains various objects of class "mcmc" with the sampling history and detailed results. For example, inspect the fixed effect estimates as

 library("coda")
 summary(mod_kr$mod$beta)
@@ -361,9 +361,9 @@

## 3 10003 1.68 1.97 1.28 1.12

The argument shape = "wide" specifies the form of the return value. The broken stick estimates from the kr and lmer methods are similar, but not identical. In fact, substantial discrepancies may occur in areas where data are sparse, for example, at the right boundary knot. Apart from being faster for more complex models, the KR-sampler opens up interesting analytic options:

    -
  1. It is relatively easy to constrain the fitted covariance of random effects, \(\Omega\), to a matrix of simple structure. Informing the sampler of the time-dependent structure of the random effect leads to stabler estimates of \(\Omega\). The package currently implements two correlations models. These models express the correlation \(\rho(t_1, t_2)\) between two Z -scores \(Z_1\) and \(Z_2\) at successive ages \(t_1\) and \(t_2\) as a function of those ages. The Argyle model (Argyle, Seheult, and Wooff 2008) is \(\rho(t_1, t_2) = \exp(-\lambda|T_1-T_2|)\), where \(T_i = \log(\tau+t_i)\) is a logarithmic rescaling of the time axis and \(\rho=exp(-\lambda)\). The Cole correlation model (Cole 1995) describes the Fisher-transformed correlation as a function of the average \((t_1+t_2)/2\) and the difference \((t_2-t_1)\), including two multiplicative terms. Note that both models were proposed in the context of child growth, so may fit less well for other types of time-dependent data.

  2. +
  3. It is relatively easy to constrain the fitted covariance of random effects, \(\Omega\), to a matrix of simple structure. Informing the sampler of the time-dependent structure of the random effect leads to stabler estimates of \(\Omega\). The package currently implements two correlations models. These models express the correlation \(\rho(t_1, t_2)\) between two Z -scores \(Z_1\) and \(Z_2\) at successive ages \(t_1\) and \(t_2\) as a function of those ages. The Argyle model (Argyle, Seheult, and Wooff 2008) is \(\rho(t_1, t_2) = \exp(-\lambda|T_1-T_2|)\), where \(T_i = \log(\tau+t_i)\) is a logarithmic rescaling of the time axis and \(\rho=exp(-\lambda)\). The Cole correlation model (Cole 1995) describes the Fisher-transformed correlation as a function of the average \((t_1+t_2)/2\) and the difference \((t_2-t_1)\), including two multiplicative terms. Note that both models were proposed in the context of child growth, so may fit less well for other types of time-dependent data.

  4. The Kasim-Raudenbush sampler fits the slightly more general linear-mixed model with heterogeneous within-subject variances, i.e., with a residual variance \(\sigma_i^2\) per subject \(i\) instead of the global residual \(\sigma^2\). This makes it easier to identify, study and weight subjects based on how well they fit the model.

  5. -
  6. A third option is to simulate imputations as an extra step to the sampler. For subjects with large \(\sigma_i^2\), the random effect estimates are a too smooth representation of the data, leading to inappropriate variance estimates when those estimates are analyzed as “just data”. Section 11.3 of van Buuren (2018b) pioneered a solution that constructs multiple trajectories by adding a proper amount of residual noise to random effect estimates. The variance estimation then proceeds according to the principles of multiple imputation (Rubin 1987).

  7. +
  8. A third option is to simulate imputations as an extra step to the sampler. For subjects with large \(\sigma_i^2\), the random effect estimates are a too smooth representation of the data, leading to inappropriate variance estimates when those estimates are analyzed as “just data”. Section 11.3 of van Buuren (2018b) pioneered a solution that constructs multiple trajectories by adding a proper amount of residual noise to random effect estimates. The variance estimation then proceeds according to the principles of multiple imputation (Rubin 1987).

@@ -491,7 +491,7 @@

5.2 Data preparation

-

Before we can fit the model, the data need to be in shape. The brokenstick() function takes tidy data in the long-form. Every row in the data corresponds to one visit. Two columns identify a visit: a subject variable and a time variable. Thus, if subject one has three visits and subject two has five visits, the combined data will have eight records. This section uses the built-in smocc_200 data, containing the heights of 200 children measured at ten visits up to two years (Herngreen et al. 1994).

+

Before we can fit the model, the data need to be in shape. The brokenstick() function takes tidy data in the long-form. Every row in the data corresponds to one visit. Two columns identify a visit: a subject variable and a time variable. Thus, if subject one has three visits and subject two has five visits, the combined data will have eight records. This section uses the built-in smocc_200 data, containing the heights of 200 children measured at ten visits up to two years (Herngreen et al. 1994).

 library("brokenstick")
 head(smocc_200, 3)
@@ -507,7 +507,7 @@

5.3 Transformation to Standard Deviation Scores (SDS)

-

The broken stick model can fit observations in either the raw scale \(Y\) (cm, kg, and so on) or as a \(Z\)-score. Under a normal distribution with mean \(\mu\) and standard deviation \(\sigma\) the \(Z\)-score for a data value \(Y\) is defined as \(Z = (Y - \mu)/\sigma\). In statistics, it is customary to estimate \(\mu\) and \(\sigma\) from the data, but we can also take those values from an external reference table. For example, heights of boys with an age \(t\) follow an approximate normal distribution with an age-specific mean \(\mu_t\) and an age-specific standard deviation \(\sigma_t\). A reference table consists of estimates of \(\mu_t\) and \(\sigma_t\) at different ages \(t\). We calculate the standard deviation score (SDS) for a boy with height \(Y\) at age \(t\) as \(Z = (Y - \mu_t)/\sigma_t\), with \(\mu_t\) and \(\sigma_t\) taken from the reference table. We can compare this \(Z\)-score directly to the reference population, or compare two measurements taken at different ages with the age effect removed. SDS calculation is standard methodology in child growth, and is available under many distributions. See Stasinopoulos and Rigby (2007) for details.

+

The broken stick model can fit observations in either the raw scale \(Y\) (cm, kg, and so on) or as a \(Z\)-score. Under a normal distribution with mean \(\mu\) and standard deviation \(\sigma\) the \(Z\)-score for a data value \(Y\) is defined as \(Z = (Y - \mu)/\sigma\). In statistics, it is customary to estimate \(\mu\) and \(\sigma\) from the data, but we can also take those values from an external reference table. For example, heights of boys with an age \(t\) follow an approximate normal distribution with an age-specific mean \(\mu_t\) and an age-specific standard deviation \(\sigma_t\). A reference table consists of estimates of \(\mu_t\) and \(\sigma_t\) at different ages \(t\). We calculate the standard deviation score (SDS) for a boy with height \(Y\) at age \(t\) as \(Z = (Y - \mu_t)/\sigma_t\), with \(\mu_t\) and \(\sigma_t\) taken from the reference table. We can compare this \(Z\)-score directly to the reference population, or compare two measurements taken at different ages with the age effect removed. SDS calculation is standard methodology in child growth, and is available under many distributions. See Stasinopoulos and Rigby (2007) for details.

Analysis of \(Z\)-scores is preferable to the raw scale for several reasons:

  1. A growth curve that follows a centile in the reference distribution translates into a horizontal line in the \(Z\)-score scale, which simplifies modeling;
  2. @@ -515,8 +515,8 @@

  3. Analysis of \(Z\)-scores removes the overpowering impact of age and sex on growth, so it becomes easier to highlight interesting variation within and between children;
  4. Fitting \(Z\)-score data leads to fewer convergence issues.
-

In the area of child growth, it is easy to convert raw measurements into the \(Z\)-score scale, fit the model, and convert back to the raw scale afterwards, if desired. There are several R packages that assist in the calculations: AGD (van Buuren 2018a), anthro (Schumacher, Borghi, and Polonsky 2020), childsds (Vogel 2020), growthstandards (Hafen 2021), nlreferences (van Buuren 2021b), sitar (Cole 2022) and zscorer (Myatt and Guevarra 2019).

-

The smocc_200 data contains the height measurement both in the original scale in cm (hgt) and the \(Z\)-score scale (hgt_z) relative to the height references from the Fourth Dutch Growth study (Fredriks et al. 2000). For illustration, let us calculate and check height SDS using the AGD package.

+

In the area of child growth, it is easy to convert raw measurements into the \(Z\)-score scale, fit the model, and convert back to the raw scale afterwards, if desired. There are several R packages that assist in the calculations: AGD (van Buuren 2018a), anthro (Schumacher, Borghi, and Polonsky 2020), childsds (Vogel 2020), growthstandards (Hafen 2021), nlreferences (van Buuren 2021b), sitar (Cole 2022) and zscorer (Myatt and Guevarra 2019).

+

The smocc_200 data contains the height measurement both in the original scale in cm (hgt) and the \(Z\)-score scale (hgt_z) relative to the height references from the Fourth Dutch Growth study (Fredriks et al. 2000). For illustration, let us calculate and check height SDS using the AGD package.

 library("AGD")
 z <- with(smocc_200, y2z(y = hgt, x = age, sex = ifelse(
@@ -717,7 +717,7 @@ 

Alice contributes only two data points in the first half-year. The model expects that her height SDS will be around $-$1 SD at the age of two years. Using the data up to 1.1 years, the model predicts that Fred’s growth curve remains around -2.0 SD until Fred is 1.5 years, and then increases to around -1.8 SD. While both predicted trajectories are extreme extrapolations, the example illustrates that it is possible to make informed predictions using just a handful of data points.

-

The brokenstick:::EB() function implements the empirical Bayes (EB) estimate (Skrondal and Rabe‐Hesketh (2009), p. 683). The procedure is the workhorse underlying the predict() method.

+

The brokenstick:::EB() function implements the empirical Bayes (EB) estimate (Skrondal and Rabe‐Hesketh (2009), p. 683). The procedure is the workhorse underlying the predict() method.

@@ -730,7 +730,7 @@

Figure 7: Comparison between predicted (vertical) and observed (horizontal) height in the SDS scale (left) and CM scale (right) in the SMOCC data. The model almost perfectly recreates the observed data.

-

Figure 7 is the scatter plot of the observed versus predicted values and provides a visual representation of the accuracy of the prediction of the model in height SDS and cm scales. Both plots suggest an excellent fit between the observed and fitted data. The percentage of explained variance for the height SDS is high: 98.1%. The standard deviation of the residuals is equal to 0.077 SD, a small value in the \(Z\)-scale. When back-converted to centimeters, the scatter plot of the observed versus predicted values is even a little tighter. The estimate of the proportion of explained variance is close to perfection: 99.9%. The standard deviation of the residuals is 4 mm, about the size of the technical error of measurement (TEM) for duplicate measurements in infants (Ismail et al. 2016, Table 2). The out-of-sample predictive behavior is comparable. If we randomly split the data 100 times into 2/3 training data and 1/3 test data and calculate the proportion in the test data, we obtain even slightly higher out-of-sample values: 98.4% and 99.9% over the 100 replications.

+

Figure 7 is the scatter plot of the observed versus predicted values and provides a visual representation of the accuracy of the prediction of the model in height SDS and cm scales. Both plots suggest an excellent fit between the observed and fitted data. The percentage of explained variance for the height SDS is high: 98.1%. The standard deviation of the residuals is equal to 0.077 SD, a small value in the \(Z\)-scale. When back-converted to centimeters, the scatter plot of the observed versus predicted values is even a little tighter. The estimate of the proportion of explained variance is close to perfection: 99.9%. The standard deviation of the residuals is 4 mm, about the size of the technical error of measurement (TEM) for duplicate measurements in infants (Ismail et al. 2016, Table 2). The out-of-sample predictive behavior is comparable. If we randomly split the data 100 times into 2/3 training data and 1/3 test data and calculate the proportion in the test data, we obtain even slightly higher out-of-sample values: 98.4% and 99.9% over the 100 replications.

The model is as good as it can get. The uncertainties associated with the transformation from varying observation times to repeated measures will be small. For all practical purposes, the results from a linear mixed or multilevel model and a repeated measures model are likely to be same.

@@ -785,15 +785,15 @@

6.1 Critical periods

-

The following question motivated the development of the broken stick model: At what ages do children become overweight? Knowing the answer to this question provides handles for preventive interventions to counter obesity. Dietz (1994) suggested the existence of three critical periods for obesity at adult age: The prenatal period, the period of adiposity rebound (roughly around the age of 5-6 years), and adolescence. Obesity formed in these periods is likely to increase the obesity risk at adult age and its complications.

-

A growth period, bounded by ages \(T_1\) and \(T_2\), is critical for adult overweight if the following criteria hold (de Kroon et al. 2010):

+

The following question motivated the development of the broken stick model: At what ages do children become overweight? Knowing the answer to this question provides handles for preventive interventions to counter obesity. Dietz (1994) suggested the existence of three critical periods for obesity at adult age: The prenatal period, the period of adiposity rebound (roughly around the age of 5-6 years), and adolescence. Obesity formed in these periods is likely to increase the obesity risk at adult age and its complications.

+

A growth period, bounded by ages \(T_1\) and \(T_2\), is critical for adult overweight if the following criteria hold (de Kroon et al. 2010):

  1. There is a significant difference in mean gain score \(Z_2-Z_1\) between subjects with and without adult overweight;
  2. The gain score \(Z_2-Z_1\) has an independent contribution over \(Z_2\) to the prediction of \(Z_{\rm adult}\). It not only matters where you were at \(T_2\) but also how you got there;
  3. \(Z_2\) correlates highly with \(Z_{\rm adult}\), so it is easier (i.e., with higher sensitivity and specificity) to identify children at risk for adult overweight.
-

de Kroon et al. (2010) found that the age interval 2-6 years met all criteria for a critical period. Our re-analysis tests the requirements for the following age intervals: Birth-4 months, 4 months-1 year, 1-2 years, 2-4 years, 4-6 years, 6-10 years and 10-14 years. Hence, we define the following break ages:

+

de Kroon et al. (2010) found that the age interval 2-6 years met all criteria for a critical period. Our re-analysis tests the requirements for the following age intervals: Birth-4 months, 4 months-1 year, 1-2 years, 2-4 years, 4-6 years, 6-10 years and 10-14 years. Hence, we define the following break ages:

 knots <- round(c(0, 1/3, 1, 2, 4, 6, 10, 14, 24, 29), 3)
 labels <- c("birth", "4m", "1y", "2y", "4y", "6y", "10y", "14y", "24y",
@@ -804,7 +804,7 @@ 

Figure 8: Scatter plot of BMI SDS and log(age + 0.2) for the Terneuzen cohort data. The plot shows differential amounts of clustering of measurements around the specified break ages. Clustering is tighter at some ages (birth, 1y, 14y) than at others (4m, 2y, 24y).

-

The Terneuzen Birth Cohort (de Kroon et al. 2008) comprises of 2604 children born around the year 1980 in Terneuzen, The Netherlands. Figure 8 shows the body mass index (BMI) standard deviation scores (SDS) against age in a random subset of 306 children. While we may easily recognize scheduled visits at birth, 1y and 14y, the figure shows that observations at other periods are less structured. Compared to the analysis in de Kroon et al. (2010), we removed the knots at 8 days and 18 years (because these appear in sparse data areas) and added knots at 4, 14 and 24 years. For aesthetic reasons, we set the right boundary knot to 29y, slightly higher than the maximum age in the data.

+

The Terneuzen Birth Cohort (de Kroon et al. 2008) comprises of 2604 children born around the year 1980 in Terneuzen, The Netherlands. Figure 8 shows the body mass index (BMI) standard deviation scores (SDS) against age in a random subset of 306 children. While we may easily recognize scheduled visits at birth, 1y and 14y, the figure shows that observations at other periods are less structured. Compared to the analysis in de Kroon et al. (2010), we removed the knots at 8 days and 18 years (because these appear in sparse data areas) and added knots at 4, 14 and 24 years. For aesthetic reasons, we set the right boundary knot to 29y, slightly higher than the maximum age in the data.

 ctl <- lme4::lmerControl(
   check.conv.grad = lme4::.makeCC("warning", 0.02, NULL),
@@ -823,7 +823,7 @@ 

Figure 9: Observed and fitted BMI SDS trajectories of six subjects as predicted by the lmer (red) and Argyle (green) models. The figure illustrates that fitted trajectories from the Argyle model are stabler in areas with sparse data.

-

Figure 9 shows the observed and fitted BMI SDS trajectories for both models. The per cent explained variance of BMI SDS is similar in both: 84 per cent. For the lmer model, the fitted trajectory for subject 8 reveals a pretty rough estimate at the age of 24y. Persons 1259 and 7460 have very low (-2.5 SD) and high (+2.5 SD) BMI SDS at adult age, respectively. Note that the model pulls the adult BMI SDS estimates (in red) towards the global mean, due to the well-known bias-variance trade off (Gelman and Hill 2007, 394). Pulling is more vigorous at the extremes. The effect is negligible for more average trajectories, such as for subject 2447. In the Argyle model, the trajectories are slightly smoother and more stable at adult ages with limited data. The rough estimate for subject 8 has gone. There is still some gravity towards the global mean at knot 24y for persons 1259 and 7460, but it is of lesser magnitude. All fitted trajectories are well behaved. We, therefore, select the kr solution for further analysis.

+

Figure 9 shows the observed and fitted BMI SDS trajectories for both models. The per cent explained variance of BMI SDS is similar in both: 84 per cent. For the lmer model, the fitted trajectory for subject 8 reveals a pretty rough estimate at the age of 24y. Persons 1259 and 7460 have very low (-2.5 SD) and high (+2.5 SD) BMI SDS at adult age, respectively. Note that the model pulls the adult BMI SDS estimates (in red) towards the global mean, due to the well-known bias-variance trade off (Gelman and Hill 2007, 394). Pulling is more vigorous at the extremes. The effect is negligible for more average trajectories, such as for subject 2447. In the Argyle model, the trajectories are slightly smoother and more stable at adult ages with limited data. The rough estimate for subject 8 has gone. There is still some gravity towards the global mean at knot 24y for persons 1259 and 7460, but it is of lesser magnitude. All fitted trajectories are well behaved. We, therefore, select the kr solution for further analysis.

To identify critical periods, we need to predict adult overweight. In Figure 9, only three out of six subjects had a BMI measurement at adult age. Since we do not want the results to overly depend on fitted extrapolations, we restrict the analysis sample to persons with an adult measurement. The following lines extract the repeated measures for 92 (out of 306) individuals for whom we observed adult BMI.

 tbc1 <- mice::tbc %>% 
@@ -865,17 +865,17 @@ 

## 2 89 63.4 1 10.8 15.2 0.00019 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

-

Model m1 predicts adult BMI SDS from BMI SDS 6y, and explains 45.3 per cent of the variance. Model m2 extends the model with the pre-gain between 4y and 6y. If the pre-gain improves the prediction, then it matters how much you gained between 4y and 6y. In that case, we would call the interval 4y-6y a critical period. Here we found that model 2 explain 53.6 per cent variance, thus 8.3 per cent more. The anova statement performs the formal test. In this case, the pre-gain is significant over the last predictor at 6y. Thus, interval 4y-6y classifies as a critical period. We can repeat these analyzes for other age intervals, similar to Table 3 in Kenward (1987).

+

Model m1 predicts adult BMI SDS from BMI SDS 6y, and explains 45.3 per cent of the variance. Model m2 extends the model with the pre-gain between 4y and 6y. If the pre-gain improves the prediction, then it matters how much you gained between 4y and 6y. In that case, we would call the interval 4y-6y a critical period. Here we found that model 2 explain 53.6 per cent variance, thus 8.3 per cent more. The anova statement performs the formal test. In this case, the pre-gain is significant over the last predictor at 6y. Thus, interval 4y-6y classifies as a critical period. We can repeat these analyzes for other age intervals, similar to Table 3 in Kenward (1987).

6.2 Time-to-time correlations

-

The conditional gain score is defined as (Cole 1995)

+

The conditional gain score is defined as (Cole 1995)

\[ {\rm conditional}\ Z_{\rm gain} = \frac{Z_2 - rZ_1}{\sqrt{1-r^2}}, \]

-

where \(Z_1\) and \(Z_2\) are the standard deviation scores at times \(T_1\) and \(T_2\), with \(T_2>T_1\), and where \(r\) is the correlation between \(Z_1\) and \(Z_2\). The conditional gain corrects for regression to the mean, which is its selling point over traditional velocity measures and is less sensitive to measurement error (van Buuren 2007). A practical difficulty is to obtain \(r\) for a given \(T_1\) and \(T_2\). The time-to-time correlation matrix needs to be known. Also, we need to interpolate \(r\) if \(T_1\) or \(T_2\) differs from the tabulated ages.

+

where \(Z_1\) and \(Z_2\) are the standard deviation scores at times \(T_1\) and \(T_2\), with \(T_2>T_1\), and where \(r\) is the correlation between \(Z_1\) and \(Z_2\). The conditional gain corrects for regression to the mean, which is its selling point over traditional velocity measures and is less sensitive to measurement error (van Buuren 2007). A practical difficulty is to obtain \(r\) for a given \(T_1\) and \(T_2\). The time-to-time correlation matrix needs to be known. Also, we need to interpolate \(r\) if \(T_1\) or \(T_2\) differs from the tabulated ages.

The broken stick model provides an estimate of the time-to-time correlation matrix. The brokenstick object stores the variance-covariance matrix \(\Omega\) of the random effects. For a perfectly fitting model (with \(\sigma^2 = 0\)) \(\Omega\) equals the time-to-time covariance matrix, so then get_omega(fit, cor = TRUE) gives the desired time-to-time correlation matrix. If \(\sigma^2 > 0\) then \(\Omega\) overestimates the covariances between the observed data. In general, we need to add the within-residual variance estimate to the diagonal, thus \(\Omega + \hat\sigma^2 I(n_i)\) to estimate the time-to-time covariance matrix.

 fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, 
@@ -904,8 +904,8 @@ 

6.3 Profile analysis

-

Profile analysis (Morrison 1976; Johnson and Wichern 1988) refers linear multivariate linear methods to test for differences in population means or treatment effects, typically by regression analysis or multivariate analysis of variance (MANOVA). These methods assume independence of subjects, organize the data at the subject level, and express parameters of interest by linear combinations of outcomes, like change scores, means or other derived quantities.

-

Krone et al. (2020) report a statistical analysis using the linear mixed model with time-varying individual subject data. This section re-analyzes the data from their Figure 4 using the broken stick model. The data are available as the brokenstick::weightloss object.

+

Profile analysis (Morrison 1976; Johnson and Wichern 1988) refers linear multivariate linear methods to test for differences in population means or treatment effects, typically by regression analysis or multivariate analysis of variance (MANOVA). These methods assume independence of subjects, organize the data at the subject level, and express parameters of interest by linear combinations of outcomes, like change scores, means or other derived quantities.

+

Krone et al. (2020) report a statistical analysis using the linear mixed model with time-varying individual subject data. This section re-analyzes the data from their Figure 4 using the broken stick model. The data are available as the brokenstick::weightloss object.

 data <- brokenstick::weightloss
 ggplot(data, aes(day, body_weight, group = subject, color = condition)) +
@@ -921,7 +921,7 @@ 

Figure 11: Daily body weight (KG) for 12 subjects followed for 63 days under one of three conditions. The graph illustrates the irregular nature of the data. Some trajectories are almost complete and regular, whereas others miss many daily measurements or display surprising jumps around their average weight level.

-

Figure 11 charts daily body weight measurements of twelve individuals who were followed for nine weeks. The investigators subdivided the total duration into three periods of three weeks. Period one (week 1-3) acted as a control period. During period 2 (week 4-6), the investigators stimulated participants to restrict food intake, and during period 3 (week 7-9) the experimenters promoted physical activity. Subjects 4 and 12 received the interventions in the reverse order. See Krone et al. (2020) for more detail.

+

Figure 11 charts daily body weight measurements of twelve individuals who were followed for nine weeks. The investigators subdivided the total duration into three periods of three weeks. Period one (week 1-3) acted as a control period. During period 2 (week 4-6), the investigators stimulated participants to restrict food intake, and during period 3 (week 7-9) the experimenters promoted physical activity. Subjects 4 and 12 received the interventions in the reverse order. See Krone et al. (2020) for more detail.

Most of these subjects adhere quite well to the data collection design. Some trajectories show gaps due to missed measurements. The most extreme example is the trajectory that hovers around the value of 95 kilograms (KG). Other curves display stretches of lines, suggesting that missed measurements were linearly interpolated. One of the series shows some surprising spikes, likely to be measurement errors. All in all, these data perfectly illustrate the inescapable imperfections of real data.

The remainder of the section discusses two ways to estimate the effect of diet and physical activity on body weight.

@@ -1104,7 +1104,7 @@

6.5 Multiple imputation

Remember from Section 5.5 that the broken stick estimates are conditional means. We may be tempted to analyze these estimates as if they were “just data”, but they do not have the same variability as the real data. For example, suppose we calculate the correlation matrix of the broken stick estimates. We know that the values in this matrix will exceed those from the underlying observed data. Not accounting for this fact leads to overconfident predictions and results that are too good to be true.

-

Multiple imputation (Rubin 1987; van Buuren 2018b) restores variability by adding noise. We may fit standard complete-data software to the imputed data, and obtain valid regression weights, confidence intervals and \(p\) values under a wide range of conditions.

+

Multiple imputation (Rubin 1987; van Buuren 2018b) restores variability by adding noise. We may fit standard complete-data software to the imputed data, and obtain valid regression weights, confidence intervals and \(p\) values under a wide range of conditions.

By default, method kr executes 200 iterations of the Kasim-Raudenbush sampler. The nimp argument to the control_kr() function specifies the number of multiple imputations. The following call to the brokenstick() function creates and plots 20 imputations for each missing outcome (hgt_z here).

 knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4)
@@ -1145,14 +1145,14 @@ 

6.6 Curve matching

-

Curve matching (van Buuren 2014) is a tool to assist in the interpretation and prediction of individual growth curves. The idea is as follows. Suppose we measure the growth of the target child up to half a year and plot the measurements onto his or her growth chart. Curve matching is a nearest-neighbor technique that relies on historical growth data. It finds, say, ten other children who are similar to the target child, and adds the curves of those matches to the child’s chart. If the matching is done right, then the bundle of historic growth curves suggests how the target child will develop in the future.

+

Curve matching (van Buuren 2014) is a tool to assist in the interpretation and prediction of individual growth curves. The idea is as follows. Suppose we measure the growth of the target child up to half a year and plot the measurements onto his or her growth chart. Curve matching is a nearest-neighbor technique that relies on historical growth data. It finds, say, ten other children who are similar to the target child, and adds the curves of those matches to the child’s chart. If the matching is done right, then the bundle of historic growth curves suggests how the target child will develop in the future.

Curve matching. Predict infant length at 14 months given the length data up to 6 months using 10 matches. The red curve is the observed data for the target child. The bundle of gray curves are observed length curves from other children that match the trajectory of the target child up to month 6. The blue line represents the most likely future trajectory for the target child towards month 14. The variation between the gray curves represents the amount of uncertainty of the trajectory prediction.

Figure 16: Curve matching. Predict infant length at 14 months given the length data up to 6 months using 10 matches. The red curve is the observed data for the target child. The bundle of gray curves are observed length curves from other children that match the trajectory of the target child up to month 6. The blue line represents the most likely future trajectory for the target child towards month 14. The variation between the gray curves represents the amount of uncertainty of the trajectory prediction.

-

Figure 16 is a screen shot of a demo Shiny app of the Joint Automatic Measurement and Evaluation System (JAMES). The red curve corresponds to five measurements of the target child made during the first six months. The ten gray curves are historic growth curves from the ten matched children. We may define similarity in many ways. Here we use a linear model to predict length at the age of 14m from previous length data. The distance between the target child and another child is equal to the difference between their predicted values. The procedure lifts the data of the matches from the database, and plots the observed growth curves onto the chart as gray curves. This method for finding nearest neighbors is known as predictive mean matching and has grown into a powerful technique for missing data (van Buuren 2018b). The bundle of gray curves indicates possible future trajectories of the target child. The wider the bundle, the more uncertain future growth will be (Toet et al. 2019). The mean of the bundle is the most likely path. Graphically it is the dotted blue curve between the last measurement and the age of the outcome.

+

Figure 16 is a screen shot of a demo Shiny app of the Joint Automatic Measurement and Evaluation System (JAMES). The red curve corresponds to five measurements of the target child made during the first six months. The ten gray curves are historic growth curves from the ten matched children. We may define similarity in many ways. Here we use a linear model to predict length at the age of 14m from previous length data. The distance between the target child and another child is equal to the difference between their predicted values. The procedure lifts the data of the matches from the database, and plots the observed growth curves onto the chart as gray curves. This method for finding nearest neighbors is known as predictive mean matching and has grown into a powerful technique for missing data (van Buuren 2018b). The bundle of gray curves indicates possible future trajectories of the target child. The wider the bundle, the more uncertain future growth will be (Toet et al. 2019). The mean of the bundle is the most likely path. Graphically it is the dotted blue curve between the last measurement and the age of the outcome.

Let’s look at a numerical example. We split the data into one target child and 199 donor children, and fit a broken stick model to the donor set.

 donor_data <- smocc_200 %>% 
@@ -1216,7 +1216,7 @@ 

## 0.00422 0.00578 0.01833 0.01889 0.02507 0.02657 0.03069 0.03744 0.05118 ## 11049 ## 0.05922

-

The above steps contain the basic ingredients of the find_matches() function in the chartplotter package (van Buuren 2021a). Finally, let us study the observed and fitted trajectories of the ten matches.

+

The above steps contain the basic ingredients of the find_matches() function in the chartplotter package (van Buuren 2021a). Finally, let us study the observed and fitted trajectories of the ten matches.

 ids <- as.numeric(names(matches))
 plot(fit, group = ids, 
@@ -1254,14 +1254,14 @@ 

7.3 Current limitations

The broken stick model, as presented here, uses just three variables: time, measurement and group. This design choice simplifies interpretation and estimation. The lack of covariates in the model implies that the transformation from irregular data to repeated measures is identical for every subject. As long as the residual error is small, the relations with not-in-the-model variables thus remain intact. The possibility to include covariates in a second-round enhances modular modern analytic pipelines. Yet, some will prefer the direct estimation of all effects in one more extensive analysis. The current package does not support covariates.

-

The broken stick method is intended for aligning observations, where every individual has the same number and location of breakpoints. The technique assumes that subjects share the same time axis. In our applications, synchronization at the start was most natural (e.g., birth, start of experiment), which is easy to do. In some cases, one might prefer an anchor in the middle, e.g., at menarche, which occurs at different ages for different individuals (Naumova, Must, and Laird 2001), and the scientific interest is on what happens before and after the anchor. It could also make sense to fasten the end, e.g., at graduation or death. The choice of the anchor may matter less for cyclic processes. For example, in weekly data it may be more important to anchor on day of the week than on the actual date or age. Irrespective of the actual timings of the observed data, the number and location of breakpoints is identical for all subjects. The method is less suited for applications where there is no sensible common time axis, or when the breakpoints should vary between individuals.

+

The broken stick method is intended for aligning observations, where every individual has the same number and location of breakpoints. The technique assumes that subjects share the same time axis. In our applications, synchronization at the start was most natural (e.g., birth, start of experiment), which is easy to do. In some cases, one might prefer an anchor in the middle, e.g., at menarche, which occurs at different ages for different individuals (Naumova, Must, and Laird 2001), and the scientific interest is on what happens before and after the anchor. It could also make sense to fasten the end, e.g., at graduation or death. The choice of the anchor may matter less for cyclic processes. For example, in weekly data it may be more important to anchor on day of the week than on the actual date or age. Irrespective of the actual timings of the observed data, the number and location of breakpoints is identical for all subjects. The method is less suited for applications where there is no sensible common time axis, or when the breakpoints should vary between individuals.

7.4 Software

-

The Kasim-Raudenbush sampler (Kasim and Raudenbush 1998) is both fast and flexible. It produces estimates of the residual error variance per subject, can accommodate for correlation models and supports multiple imputation out-of-the-box. More research is needed to establish its statistical properties especially compared to lmer() and other established methods. It would also be interesting to study the suitability of the correlation models implemented in the lme4qtl package (Ziyatdinov et al. 2018). As no training data are stored, instances of the light "brokenstick" class objects are tiny, often 15–20 Kb.

-

Features not implemented, but that could be useful in future versions include a separate impute() function that inputs class "brokenstick" and returns class "mids", a Trelliscope (Hafen and Schloerke 2020) viewer to quickly peruse hundreds of individual model fits, an extension to multivariate time-varying and child-level data, and a generalization to degree > 1 to support quadratic and cubic splines.

+

The Kasim-Raudenbush sampler (Kasim and Raudenbush 1998) is both fast and flexible. It produces estimates of the residual error variance per subject, can accommodate for correlation models and supports multiple imputation out-of-the-box. More research is needed to establish its statistical properties especially compared to lmer() and other established methods. It would also be interesting to study the suitability of the correlation models implemented in the lme4qtl package (Ziyatdinov et al. 2018). As no training data are stored, instances of the light "brokenstick" class objects are tiny, often 15–20 Kb.

+

Features not implemented, but that could be useful in future versions include a separate impute() function that inputs class "brokenstick" and returns class "mids", a Trelliscope (Hafen and Schloerke 2020) viewer to quickly peruse hundreds of individual model fits, an extension to multivariate time-varying and child-level data, and a generalization to degree > 1 to support quadratic and cubic splines.

@@ -1281,7 +1281,7 @@

Computational setup

-

I am running a Mac Studio, MacOS Venture, V 13.1, 32GB RAM with R version 4.2.2 (2022-10-31) and brokenstick version 2.4.0 (2022-10-30).

+

I am running a Mac Studio, MacOS Venture, V 13.1, 32GB RAM with R version 4.2.2 (2022-10-31) and brokenstick version 2.5.0 (2023-03-22).

Acknowledgment @@ -1293,7 +1293,7 @@

Literature
-Akima, H., A. Gebhardt, T. Petzold, and M. Mächler. 2021. : Interpolation of Irregularly and Regularly Spaced Data. https://CRAN.R-project.org/package=akima. +Akima, H., A. Gebhardt, T. Petzold, and M. Mächler. 2021. akima: Interpolation of Irregularly and Regularly Spaced Data. R package version 0.6-3.4. https://CRAN.R-project.org/package=akima.
Anderson, C., R. Hafen, O. Sofrygin, L. Ryan, and HBGDki Community. 2019. “Comparing Predictive Abilities of Longitudinal Child Growth Models.” Statistics in Medicine 38 (19): 3555–70. https://doi.org/10.1002/sim.7693. @@ -1305,7 +1305,7 @@

Literaturehttps://doi.org/10.1002/jae.659.

-Bates, D., M. Mächler, B. Bolker, and S. Walker. 2015. “Fitting Linear Mixed-Effects Models Using .” Journal of Statistical Software 67 (1): 1–48. https://doi.org/10.18637/jss.v067.i01. +Bates, D., M. Mächler, B. Bolker, and S. Walker. 2015. “Fitting Linear Mixed-Effects Models Using lme4.” Journal of Statistical Software 67 (1): 1–48. https://doi.org/10.18637/jss.v067.i01.
Bellman, R., and R. Roth. 1969. “Curve Fitting by Segmented Straight Lines.” Journal of the American Statistical Association 64 (327): 1079–84. https://doi.org/10.1080/01621459.1969.10501038. @@ -1314,10 +1314,7 @@

Literaturehttps://doi.org/10.1136/adc.73.1.8.

-———. 2022. : Super Imposition by Translation and Rotation Growth Curve Analysis. https://CRAN.R-project.org/package=sitar. -
-
-Core Team. 2020. : A Language and Environment for Statistical Computing. Vienna, Austria: Foundation for Statistical Computing. https://www.R-project.org/. +———. 2022. sitar: Super Imposition by Translation and Rotation Growth Curve Analysis. R package version 1.3.0. https://CRAN.R-project.org/package=sitar.
de Boor, C. 1978. A Practical Guide to Splines. New York: Springer-Verlag. @@ -1347,10 +1344,10 @@

Literature -Hafen, R. 2021. : Anthropometric Growth Standard Calculations. https://github.com/ki-tools/growthstandards. +Hafen, R. 2021. growthstandards: Anthropometric Growth Standard Calculations. R package version 0.1.5. https://github.com/ki-tools/growthstandards.

-Hafen, R., and B. Schloerke. 2020. : Create Interactive Trelliscope Displays. https://CRAN.R-project.org/package=trelliscopejs. +Hafen, R., and B. Schloerke. 2020. trelliscopejs: Create Interactive Trelliscope Displays. R package version 0.2.6. https://CRAN.R-project.org/package=trelliscopejs.
Hand, D. J., and C. C. Taylor. 1987. Multivariate Analysis of Variance and Repeated Measures: A Practical Approach for Behavioural Scientists. Boca Raton, FL: CRC press. @@ -1371,7 +1368,7 @@

Literaturehttps://doi.org/10.2307/2347788.

-Koenker, R., S. Portnoy, P. T. Ng, A. Zeileis, P. Grosjean, and B. D. Ripley. 2018. : Quantile Regression. https://CRAN.R-project.org/package=quantreg. +Koenker, R., S. Portnoy, P. T. Ng, A. Zeileis, P. Grosjean, and B. D. Ripley. 2018. quantreg: Quantile Regression. R package version 5.35. https://CRAN.R-project.org/package=quantreg.
Koutsoyiannis, D. 2000. “Broken Line Smoothing: A Simple Method for Interpolating and Smoothing Data Series.” Environmental Modelling & Software 15 (2): 139–49. https://doi.org/10.1016/s1364-8152(99)00026-2. @@ -1401,22 +1398,22 @@

Literature -Myatt, M., and E. Guevarra. 2019. : Child Anthropometry z-Score Calculator. https://CRAN.R-project.org/package=zscorer. +Myatt, M., and E. Guevarra. 2019. zscorer: Child Anthropometry z-Score Calculator. R package version 0.3.1. https://CRAN.R-project.org/package=zscorer.

Naumova, E. N., A. Must, and N. M. Laird. 2001. “Tutorial in Biostatistics: Evaluating the Impact of ’Critical Periods’ in Longitudinal Studies of Growth Using Piecewise Mixed Effects Models.” International Journal of Epidemiology 30: 1332–41. https://doi.org/10.1093/ije/30.6.1332.
-Otto-Sobotka, F., E. Spiegel, S. Schnabel, L. Schulze Waltrup, P. Eilers, T. Kneib, and G. Kauermann. 2021. : Expectile and Quantile Regression. https://CRAN.R-project.org/package=expectreg. +Otto-Sobotka, F., E. Spiegel, S. Schnabel, L. Schulze Waltrup, P. Eilers, T. Kneib, and G. Kauermann. 2021. expectreg: Expectile and Quantile Regression. R package version 0.52. https://CRAN.R-project.org/package=expectreg.
-Plummer, M., N. Best, K. Cowles, and K. Vines. 2006. “: Convergence Diagnosis and Output Analysis for MCMC.” News 6 (1): 7–11. https://doi.org/10.1111/2041-210x.13727/v1/review2. +Plummer, M., N. Best, K. Cowles, and K. Vines. 2006. coda: Convergence Diagnosis and Output Analysis for MCMC.” R News 6 (1): 7–11. https://doi.org/10.1111/2041-210x.13727/v1/review2.
Pullenayegum, E. M., and L. S. H. Lim. 2016. “Longitudinal Data Subject to Irregular Observation: A Review of Methods with a Focus on Visit Processes, Assumptions, and Study Design.” Statistical Methods in Medical Research 25 (6): 2992–3014. https://doi.org/10.1177/0962280214536537.
-Ramsay, J. O., S. Graves, and G. Hooker. 2021. : Functional Data Analysis. https://CRAN.R-project.org/package=fda. +Ramsay, J. O., S. Graves, and G. Hooker. 2021. fda: Functional Data Analysis. R package version 5.6.0. https://CRAN.R-project.org/package=fda.
Rehfeld, K., N. Marwan, J. Heitzig, and J. Kurths. 2011. “Comparison of Correlation Analysis Techniques for Irregularly Sampled Time Series.” Nonlinear Processes in Geophysics 18 (3): 389–404. https://doi.org/10.5194/npg-18-389-2011. @@ -1425,13 +1422,16 @@

Literature -Schumacher, D., E. Borghi, and J. Polonsky. 2020. : Computation of the WHO Child Growth Standards. https://CRAN.R-project.org/package=anthro. +Schumacher, D., E. Borghi, and J. Polonsky. 2020. anthro: Computation of the WHO Child Growth Standards. R package version 1.0.0. https://CRAN.R-project.org/package=anthro.

Skrondal, A., and S. Rabe‐Hesketh. 2009. “Prediction in Multilevel Generalized Linear Models.” Journal of the Royal Statistical Society A 172 (3): 659–87. https://doi.org/10.1111/j.1467-985x.2009.00587.x.
-Stasinopoulos, D. M., and R. A. Rigby. 2007. “Generalized Additive Models for Location Scale and Shape (GAMLSS) in .” Journal of Statistical Software 23 (7): 1–46. https://doi.org/10.18637/jss.v023.i07. +Stasinopoulos, D. M., and R. A. Rigby. 2007. “Generalized Additive Models for Location Scale and Shape (GAMLSS) in R.” Journal of Statistical Software 23 (7): 1–46. https://doi.org/10.18637/jss.v023.i07. +
+
+Team, R Core. n.d. R: A Language and Environment for Statistical Computing.
Toet, A., J. B. F. van Erp, E. M. Boertjes, and S. van Buuren. 2019. “Graphical Uncertainty Representations for Ensemble Predictions.” Information Visualization 18 (4): 373–83. https://doi.org/10.1177/1473871618807121. @@ -1443,7 +1443,7 @@

Literaturehttps://doi.org/10.1016/j.physletb.2014.06.023.

-Umlauf, N., N. Klein, T. Simon, and A. Zeileis. 2021. “: A Lego Toolbox for Flexible Bayesian Regression (and Beyond).” Journal of Statistical Software 100 (4): 1–53. https://doi.org/10.18637/jss.v100.i04. +Umlauf, N., N. Klein, T. Simon, and A. Zeileis. 2021. bamlss: A Lego Toolbox for Flexible Bayesian Regression (and Beyond).” Journal of Statistical Software 100 (4): 1–53. https://doi.org/10.18637/jss.v100.i04.
van Buuren, S. 2007. “Growth References.” In Growth Disorders. 2nd Edition, edited by C. Kelnar, M. Savage, P. Saenger, and C. Cowell, 165–81. London: Hodder Arnold. @@ -1452,28 +1452,31 @@

Literaturehttps://doi.org/10.1159/000365398.

-———. 2018a. : Analysis of Growth Data. https://CRAN.R-project.org/package=AGD. +———. 2018a. AGD: Analysis of Growth Data. R package version 0.39. https://CRAN.R-project.org/package=AGD.
———. 2018b. Flexible Imputation of Missing Data. 2nd ed. Boca Raton, FL: CRC Press. https://stefvanbuuren.name/fimd.
-———. 2021a. : Analysing and Plotting Growth Curves. https://github.com/growthcharts/chartplotter. +———. 2021a. chartplotter: Analysing and Plotting Growth Curves. R package version 0.31.1. https://github.com/growthcharts/chartplotter.
-———. 2021b. : Growth References for Children Living in the Netherlands. https://github.com/growthcharts/nlreferences. +———. 2021b. nlreferences: Growth References for Children Living in the Netherlands. R package version 0.15.0. https://github.com/growthcharts/nlreferences. +
+
+———. 2023. brokenstick: Broken Stick Model for Irregular Longitudinal Data. R package version 2.5.0. https://CRAN.R-project.org/package=brokenstick.
-Vogel, M. 2020. : Data and Methods Around Reference Values in Pediatrics. https://CRAN.R-project.org/package=childsds. +Vogel, M. 2020. childsds: Data and Methods Around Reference Values in Pediatrics. R package version 0.8.0. https://CRAN.R-project.org/package=childsds.
Wood, S. N. 2011. “Fast Stable Restricted Maximum Likelihood and Marginal Likelihood Estimation of Semiparametric Generalized Linear Models.” Journal of the Royal Statistical Society B 73 (1): 3–36. https://doi.org/10.1111/j.1467-9868.2010.00749.x.
-Xiao, L., C. Li, W. Checkley, and C. Crainiceanu. 2021. : Fast Covariance Estimation for Sparse Functional Data. https://CRAN.R-project.org/package=face. +Xiao, L., C. Li, W. Checkley, and C. Crainiceanu. 2021. face: Fast Covariance Estimation for Sparse Functional Data. R package version 0.1-6. https://CRAN.R-project.org/package=face.
-Ziyatdinov, A., M. Vázquez-Santiago, H. Brunel, A. Martinez-Perez, H. Aschard, and J. M. Soria. 2018. “: Linear Mixed Models with Flexible Covariance Structure for Genetic Studies of Related Individuals.” BMC Bioinformatics 19 (1): 1–5. https://doi.org/10.1101/139816. +Ziyatdinov, A., M. Vázquez-Santiago, H. Brunel, A. Martinez-Perez, H. Aschard, and J. M. Soria. 2018. lme4qtl: Linear Mixed Models with Flexible Covariance Structure for Genetic Studies of Related Individuals.” BMC Bioinformatics 19 (1): 1–5. https://doi.org/10.1101/139816.

diff --git a/docs/articles/oldfriends_files/figure-html/plot-v2-1.png b/docs/articles/oldfriends_files/figure-html/plot-v2-1.png index d717ec294c37aedaccb650554aaa12d31d67784e..2273343654ec8d38f23b80aff17c460e4a760da6 100644 GIT binary patch literal 74167 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 !UO{BpoN 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

k@-ekL`ofUz4~ca+&-lq z)KCS_xV&&dG6bo&i&ZSd*sNL4b|X(RKj(a_8j<;9ljd{10q9I%6f?)?GzGRjGf)fo zQmmv>e>VI|AeHu}Ma}HO;*9_)b-Ln)2iI7){IoqUF|`_~o1C+I}&`;4`#njsj(b+-;YYYB*nDU#)TmrUQg3q-E+AOuuDHfwO^1HG=Ir+N?q z0s_EkO5)L%)9Mb5dLbO$3v;B~PGn)7;Cvr8wsiXHf~TkFFG0?ieCbrt(#l#|AG*mS z$XsKmdQ1V;@PnWG#iFQw#{R4x+TM<_&y{Zf^+6Ugk$_`k^*}H+>+*WylAj>uR1m*IXT@LcCWr}2DCu@!SzqtT& z3KnLFBUWURVx_x)I zrs}+>4 zzO+DowB@p2-#AxmtGFVpcrG0}jNNOR7FCbA=^1-;h( z{^Nez5rdJNOp-RYq3jXZd~GZ!o_`O20jK=Wwi@_^UDfUT>xDrYkff^z8tqZZj}{EP zrb&%&X%hNT+~tsA;c*#=$AzggEnRK#B-b9>@D&Oq9}dqTQI^gGOHLO!lu&&LyBy+{ zcdb+2w8Vuz(lqXhq0ssIq0SjpKay$64=~+;?5eCko8T8OcKeWx$Mvgg-Yf{gA_`GF z)dpqoa~nvvEbx5e6)3{dZdK9zz zh~3a(AD*Xsu~}etpv-6`Z+Th7qZdfQR%0q#R90GmxC0~cO@%ZZzUwcH%k;lD?25Lv zsi}nL6a(kq^kk;p^cd$8DJ2Om$r8|60 zfvXo#v!`^uNPGb&+etn>I5R^IbEw+GQr?wXD!y-LjSEs`c2QDR~MPyg~&(o@M;s{4y< zR|A`^oiIu>c|`&z$wd-t=>^eRp%-fX_Kf zK*zKL8I^)obN$lc(Npy-$Fm9ZN%X|eSPH4|@X@%Ye$q1Y)n*l~4&VPGf`v?aBH>iU z$Y0NfTN9>CDI9cEJW11)>#z_O2T&+E8lV4u=jC;#d%ARQZ`n0>0^`r`eqV7lS4Li~ zsy}2+2H5rQW9)x;f1^VN%KdH@%c_0EqxwF?CZ_U?XyP~#N7?X~(TzyxT*l5%>dd47 z*EqBD#=fv5mz}k7Lq9m+>N5?_9p^)J6X5P2R7Qy`I0n7RO?p;%cQqH7L{GL+21gLRoLQ)U ze`5i?J7oBHPO6s;@w9?tYDLy}GNM$=Lw=E$=@();1?i;6W4ru4mo$O^0on7?JpDC& znoc`tg|dfgA58rJXL0ggv}5bh3LU4NY{Z5*N!Y)`iEwo|5}LDUuwUUA-RPfovo+1d zzV@+5!`g`)e3nRhtmZuG*w|Ni1-10a$0NSXbZP#*5QIind6uoB&)3%Ig0L~U*0mch zQQd4IpysSgT{X#+7S3y>%bxPu)aMcTj_zBNlqL3h+m_(vG}{XgdxaUV_c;MW%?cM} zndBprVp&zFjLVeC@;RG)#d1O>fw9D;kzd7$qFHXrO~NCwNtF_C+}o z2Wb`98=_;M7~jkMkMgK(sN!z}_s~|d zI*ufA;XLutZ2rnqIN0iBxXb8`j=qA&4^Fd-3MdDBjSZ-em<>E35C{1%Qz^sxo8MZ> z9E-C->4WmKld^dqo0`*q%*{EOqzs9@)^I65X==@WA6cgqW4S{)to#x8u*CvB(kym& zmwJI6Au_GtkSCFqG1#(%`>{5l88YOHHVl{%su zEo>$5B~LnN(6FogOjCDsLzO@_=~RN<>uXQ0s?~632p;ZHNCOh9UC2_)WVc~P{8IUP zX!#0AHCxh>xN4-Y4yYG1)+9UHOaI;wfhgJFW<)s_TVEGr^@0fG@q8io;>~z5!5)}H zmxnAl5@U7hkKypmktH~n0-!0PnQ*mNQ&nRG0`Z+3erKq@7o!gQ^;7-yX))b@4b^`& z!TGpeM_Nz%kJ#V{W|OQLE@(L>MmV>?+aKj|!o9tI`(xCa8i(BtA(bQ{!lh)(HPo7z z=ZZD*QXsos`5mBIHD@0LfK2r%2oQ7QIXC9)gKx6o$P#7hgx$3wuVgMFk=gBt)uSGb zVkOMdFMp;Pyes+~{${b0opI(mFQwRFcJ~llK>7K1=V$-3?Ts0jO-Bsnj}mcGMWoh? z@xzf`>tpKae!{rvcA;oD*lP2J6vG>;&GdJot^oPF-=t9jb^tBgq@+T!;W z^^Xnh2=Xl$5vyO0I1jycz4~3R2tDvYH(?3QQ5;0*a&%Bd3XLI|dcUaWGwgi8qS$5H zR}c5%v+ckT&e_X$1C);s9ZNsCef@Vwu(E%dpLzT#6$Fz<3j(Bu3S7(?LLB&X@6}YE zt(~mZZ$+hYV0&p9`0a8+8+~6PM%fLTOD|q|l1-J;bT>#{`6r90;51F-yO+q(3Yws3 z;hIxKmOS$pbCqc#P>TN8)mE+IjALlWn{k|@m&?#yui_kWcDvek!g&&UeBvMY#Dn!j z==NW0n4jG+i~v1g(17F>A0ww^wGe*6+RqW)NA51*R{MlsTwdH6g@EEoj|4<@sw3?a&V zUlB+VF@?y|$&ns7#$Ltywp2n<*YHc=pmS&R^lycis>(6OT!ofr*~M0>8^45#;s@lu zo{RM@gr3U0Q~JTBQXTQQr(IOXXQn_(&iXy}joHi6C*7F;k+G-VO!2L)mG8#PLr}ap zxy~sF!Yv+B#PaxC@ixV(%jj~+?Y#FsY2pJu#&eIaQYHCyFC!}kxq`Mo;tN2n+{tw1 z{T8=XLzVOczp{uMYc6F7R#7=Jq>Ae@FQ%~7Gimt?;-VO`YgP*f@l5^~)c}vw(Lv(C z&#sAA3?+}UKupDiAgdUDt&UQ!sx9S5>$K_QQ62^{mU)6q@h`(N@mmP8&b~# zldM6?%irhAN`AFK2rW>xEO4-*Lwv~{A0M;89bHW0Z7s?;Y}h>Cr}7CQ6m+{pT)Jb3 z;MSAx=?Qbt#LY$a`GN|MVE#%4YECd<*c`)ac*mnuN9{CM7QL(VJW@vWO!F`Qd=LM{ z^F+qX$Gvnr+tEqs<3tetJ*Ap$7?jj*j4R9(&jCS{iu$7q#fg+m0##auy4{ zr7NpwiJ-Sr(^3sAYZg*z zWB*>v4WCAH30`PQ1j1sg(TD87WWZ$xkq=NhUc^)bl+VG-(e(|;)|O7@vUlk^ z`l?PCCfHx`Y3)FixDRA{{BLH#meEE~HQ^MYeBj)w@22YUhWB#8{uCHFSLwsg9bl=1 za4mN~APucT-^X;NrpHs47xobxJB(T0j1mnTrc1d!<=*vH(tH?A{eL_Z3id{(L#VD4 zhHS#poh9ATTXU!95XX*n412V74@u;MbAXb5%`nwJHg&L}>z+c;(j)n{p$ev{NBA8r z?1t;{Avhiq!$tX!?t7K=f0SdM^yv4*ex`R9aoErF-<&TMY9ws<-tCn%<0r&+&k(0g z&E?Kll}AmsVJmbp(TVXvi$7HngY8G7WGcTZk4l=t>PU2lrq%Om^UZIHz-j*fXu#+g zF-L4_qAw>2vbRGIs*32o9bZ3#1USYbbN4qf4D%c8<@)eQ_(UUT3X%RM4YzRk(ZVDP z&j&4FDeRZJC~A9f@OT7o;FnFW=m!B<8pFRf4=p=S%*~9UPEvPrzx-51asTaa;hpQs z-Q-xrSrXQ1kOE@DhkZkJ;YRu)%B`Lm?F$5)N$G^c^HB*%bd@Y{E*Jd(5ZC{V*F*df zeg;W;aTM68>?ftR4_PY&bh+zHCz6AR+S0MaM(RPw_(XXe%W40AY=L<3tFtq z^PER#dE!F>BgpJ3^n`+0{&&=FSK_#6d`L>Dv%m1ePERK~fPvvvXWKzO_WX@j)11Yykn!s%2?s%_tXP%XC>KFrTRv@I zvyM;!L*Nhc|2!hc7qnsDw2<8uUOC{&K~7&6p?V+Z9Yr3tW<1v)-O#v1@#Nr>8f%() zO8q9huv{Z}0cyqHF%`y*i9lExMf{r|*zSm#h1j$m3<#yy*Vje9^yI zj=uPm@&pq9csSsEWmS#_#ni^ErG>sLxZFL%qShYxwg;aExX)6V%s|{Zf+SwSrSy4k z7PD<#2XC=p4=F!&c6zHuL#Bo+`fG%h2-GzW12wsfwN-Ea$(jS(d&)@ON8xBR|6ob+8b@9ysR7JTA}UD6MZl+IS2hfd_#JkWmxAn3Kd7S~Y7fiKr)(R(4; z9$K<|2Ho8@5OmNOEdH{CD3};@MmiO?v5$%>uBU|yAI6X(@eG`Ar(k$ZD*X(lN8qC0 zSxH!P;^2;Tt4H3PDp_8spxA4%!imTE+NwoOO@FCa>Au)k*k`ddS0pTQT~(BjD&TSvcL;75A9P3+7eY>ADA7IEjSmn+^i+4k=J zI%i|6F1CC zi)88uNx6|ikv8>P_eLXZ53Aet-5Il)eJtOtPk4DjFLy`?ZU>mpt=)!J8u@X#B+mw-m`83D z39r8z9wRgAV9IQN_K7q&;N%-ljJ3;~beG;>C>~3xNjXD)WYc_&0|DhMQAJvhBJ3Y8 zadmBu$}yi+62fl(P2CKNq#jzEg$4fGrMR+C6sY9kX9`F5aK z?u{0YfU}N>pWl5gF~r&R+HF#>!W4br@I%M!+*~tLo7?rx4fvxO+W8_gog5T%tB~U< z5Y1Me+zIQ<(VI$7uoGuXR%c6QxbZ1QnOm#^KI0~Em6lSMadPuki8!+G!rvrydl<3)>_>KV^?7Sp$?>lN^Es29gGCm?3n-Bz}4Tfm_s^S z-XUltpZqE}_+h7}&*l{tzOvWNx4;Ue!ZDnx3hvnIkn-5D4$O~%Qh>vjPuPjV!v?(!B7_}<>?XA!q^)-7;RTUHz z3=)45-QM1Uhmyh_MetazdZsj-HMDyb_CBaS5i0(|+f{P&;6T&I=eCwOFkKoMgH)XY zGx>OjJo-a8t4?iEliDOYsX$S1Fw(@tK>tf6%FV5<5l{uQiK&Adumbe!S58pLs(Nz9 zy2F!gc6m7~rY8@VNpI7Iwk3LK;}s3Iy5YgWjs~HL^WkzEZMq<}%!s9WOzrEo_bYJZ zY9muq)N}Q)5mYXu-gd6c;%54)&iGWsfCqvI57%j2g>`&4}+vL3SmXxQH1QYy(6(y>;3IP$W5=hx&*{Jd<5#U(>3omz&W)UBgd3np9vi1 z)VA~aV`6|Uw2>kC7ofCwi?B#0ZR9G=lZOtkIYn9UWQs%Z~U5DQtRSsDD(W+B05ke%XgGZpuFt~uUO%+ z|IEtkwD3{rTCjP8E75lFD4+aSjP%(oH65GULhix_Pbbgoh&&v73B^RV)}g9O*x z-)>G7ke%=l(InUoKL8#Gn@nOS>NNnwFCccs#N!e~@EC@wpkOQQgdujK@>FYj;WA6>Wj*WA-h2oT^1~bKP1c&yj_&*z=dYtLTx5GUVr+|=n z_138LnY=4BF?R9R$&3*>dkn?vy5#q{_st%yE$#Qa+>K=1-e|VWlekAJE@D~9@JCx$xiBcXxrnH zgk=I{Di*b!lFj>_J^|Nr-RIlOB1V@jYU|^hbAH}2gDGU0TZRw5F>seWQ2w*hHJOW3 zjHPlbGlb2Lt|J5r*Xym#`Ge{zUY<^~Bb?5+6UyIIeK?A|{HDqqtEPPHZcC5z4~tqZBDBV5}ucp-*<+u16a7Hr#C{vi)V{?HO9 zKS>&GsXTRR*NAdr0Dr6AkZhRU3kmzNR&fNvTCe3Zlafus&UQHPQ}_M7=hoiKz1`m8 z=Y-=w*Nfm2oX^MxrzSSo!GIV44%oRThraYCsr%tD*4kPF^4YI)UrM(6MNZ-JW*-ld z&7r;@n<9P&g#!_vg-vWM+%yooe{iZoH;c2WitcZ=#%gUzbA{k8AHdPTXqZ*~n3xo9 zw))f4Eb870*V7Vm?ctoRqW5reVT9y-(}tg-RV<2Wrliw9cf=A)yoZ|zWNbdj^K4gw zw6ya$|9J`$D0xVfGOjdv1yt|rvDRAAAJZi}jT1kTjmgRO2e6A$rkpjmeF!S8e4wvW zBK>33X3vVZ{3y>Hf{*cc62|y*Dh>{oxX1EM8gJLjdu`-J1j5s|^ zVx$}FaZP&YDV$X^SXs%b>tf`^*Xeh*hbTQ0ba@kzP%Dmu5{b?m78z}#H&B5=k85tq z1i4?v2GLc(^PQUq(!_UCV$E(r{qTO5kw|ru!Q;sc;U2p`4%G-#o_wYxoxGx+VrRqi zuXyqg5~S-A=>{_QnjLQQqw|qABcGXKM2v^j$8ewV4JxNd&$0RhE{U_AH7AQAQAiRo z{67)^dZ_~8>R^l@)lj|Nwt0V@NoJ7eR^M4G96i-$YP6Y>MUF2+()0fO)YN5mo>2d* z^}E^a_C@T+5UgdwEZAKAL!-C0$XZC!$CiyKYdVk@N3w{RbaLi0c(MRH*?IAoK`oV6 zltt=I;(F(-i%_=oPgbvM;vdzmm*Q5)A^EfZ%a-Izse~;gnH>*@lMhGSxVF;mSna&C z<%U|4)%_+_Mp#i1gQ>*%?5)y;oE8PrM|D??M1^ z(7Q}Qf-Oz?>3j}3dr~w-zKJ7e7yj4-2oKla`$^E8=l}X5R`baMHvL#}$e%5z=wZ-z z|FrDiPQd(77@m6%f#AG@{L#_MPf?qDI><$AepADG%-nwO9kF1 z{&#jSurXzL_p|*tCVQ&|7?B~$&;KRU^Ett1Q;#DcX!RVPdT5X=)qkJAD73`y(lxJf zu|pODi4XkuzSV*cIvU8!&`34lAw?7jS+Irqhkn{2K^1uv{b8HPTA&;WqD=dD_?8V^ zyP40W6tq|+uS^(zIZ8nMWnccYxWndbg5?k@5!r5I>(b|7vY=_H;J>*5^6398=-Wl; z$MF?NZGi?F=gTO1c!)acKNRyn!0|)|6l)l(N=o?|4x_>Uz6A9nOz7Y_u)<2-sV)Bx zIl&#DX64)XPZqOw(H=tldti43uSXrb#-IBE zfcyUC`wy4^2o*S`sxyL-cA#eV2THZ-bd*+>e%^GUojDYrzkb!t9v;UKJh^HLXC>U- zOxXLv#?~v@K`4DHeA%4ATUwa)!hNOc4Tp}98~hQum}`?ksTZyT#eptF3Lm9w9{AXz{6l7 zKQs5i=jQx#eZ2-68k$+N66eyS>~MyP-28XwnNbkxizA|_UU z_C#5L^a6^##N)8+Zw%NYHMN!TgoK3HVVzA(-Q2)Z>U1QQ zp({zeym?p&ubse29ISYDHmaPZGkBwp1!mq?Hyf^}#1d%6CM3k48=nxel-T3!Ehnt+ z=QWuyk9Zn^LYj3)9BF`LX))qhyVG2_tuJ6%;_}^2{}yq$^QF&wPp4y9Zm;S0mw4X zUm5o#uB*{vD-Z-dp7j6?1p|D5s;0s#x69EFgxk zxx&OSVIeVwg120S&y@zU26nD*j(-6V_#`udg13tXtKt;{u`S)PP1JX{W9`1i`MN5_bikV%E;t5n7B7*oYg#v7xm)}vl9JVp` z)={g=qxUMBo1)ggh#cWxnl1a$dTtX1bvfqrD;44R>Cy@DNBsu04eWJ5klXBb`*m^g zi*^A21wHn z{q(3i$>awM#r!VOIZml&h!5B#bYp%Y!1sPPVUxov{v=Izl&U$=vL!57P6$y(`KyE% z*(8zo{Zx~0^+TDh)UwPs$6Z&y#H{w>_n-iv)F!Q5N6oB!{<>oJevi9ajewaR8KMsP z%Q}Ul_AWFh8lc>{YLSqTcdM7>Y2nBUgoF4Y%@Z_wJu=PgLc<5TONTk8|3e>lx*Ls< z-M0CnL$%Svt%ELU#n&_tG{my(d+zV180PW5H9qEHh!AyR^LNNFvbY!XBt<(CYp;xi z6uq+)AEC69rKs-J5-aQsffs`-!a?nsj@)&2?b-p?;Ql)=Q5Q$;>@4{J!i>L z+L-wl9f(N&UzTw1tFFBqBYR~llgf7U^_Tf^2L^$YJAx(8>mJ5g!uhfC>6}I#hpiCo z(z2ssYlukDU(R+fcf8utai5{@ox6CJJfTav+9U-knl7r6nWpZhXtUy+l8!-mt}d>o@exy>@ARp6qVA7h zOk_ZR?8w4FaQ<%n%k(4l=8TQoCOU5?x}BHvo3DFv_fREsug8xY12ch)b#VgK0A4Ne z4ET-jvc;ylw1!u$0e1NCuUz(|v3q~bhRwp^_rCxkzQ3`fA=TIjgB}i|UaakgHvH}# zoZW1#%#iSX6CXc6%#{Nw>ucIfl~3eI=*j&-Qoku)@eup7!S-gH8al{AolRo-*L^+$ zli-7$-Q97MD8YhmQZM-_L%(K?a=k61AlSV8qgAgu;Ao~`SfR5NMZ~Ew?ah}JBmxuX zwRlbIz1h0ZPUBwln%P>b*!|`UgN3(!jGmw-URgl_RYl()4P|-CDMDmYv;G7Z!V+OV zz$s$reI$W{im30t5(NDjN{=1YZKj>@^XLng?Q|A~?_oepp5g7bCaLBhH1{bl!&&9# zCaiZxQey6vSlk~nm@7b_c5_@ZqbZy=T|U3tA2G*KG=tie>>60GIlty02X0)X(>1@D zGJ3yi{h`+MiFc+d_UCJ7b;xczh7D&$%Sk3Jz}ld!S>LHy`06GXGdnvQdEF#U!G^U4 z8v+vfX^v}>3O>>Pa=J9TiA0A4|b=xr_%E3`OJfmA;fcl zHuhil>T`weKpQ}rn8o|Miy?7d*iimYZM!$u4fm#2D=t1$+wJ^HDB8AuKYJ|MYN{P7 z72s*1EAMr4>}fpZ|8`Ipy4RYX<7plYhU@@CQUebw*PHnw;D!9$*r;8iS&?zrn4X?K z3xW$@q7dQ5G_f{!c4E!6%_hiYNJvOv2!XZhha)kGfcxcATq!?Bj3PJ>N>Mly#G(2Y(@Hpg0I*us@n9+x||9*Co^ zvL&yQPi9X*-bcHc=P74@hIckkgtBn%u5y3tQ)7>*3x?HBKte)l0%(J{dj!C`w~c84 z5(eANnLZ+qt2g^7ZtQ*&+zTKV$wA_EuX_JBgZ=D^lCj72VKb< zRf30DLtlU4OO$p(KEPA2S=`4jcyQDbBg4*+Kw%&Q$F zTH{&6C0nHhFwkp3f;N|h(CHQ=_;=OTwG46zX7RTTpu141m{g@*>Kg0&9Vi_(Dr%5u zEGoD8qsiDRfJS&D$-5oBTjhIi^%6a`X|Va$g;MqiZ|5SzXJhLXts-cMiLX^VUFKId z0s|%w6B(%+#Lqk}6qTCe$F46BIH-kg>R%?9RUPmHq)T(--ZUFm&+fZ)kxskY5MF`l z=}Ze@w9qdPEz4(>1l6*MobEZN^m65x8cq9e0j30%&%c5SbRNLNsqZwvdHtPQ$gw~A z5hEj`wUrgYMU`_kC>5BA;eV^;<;xT@~5Gv?E;1fbvM z-X4I9j5hiuTwBgMT}dddc}WrI#5`G+9K8UbE-o4X2k7

y-%ZMH(CGywjWbuMyIP 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 literal 73506 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⪚CU27Q@|kD;Y+XR5b&tL>^bUOObXk+t&4ralPNha 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�FYSR)Me9bSoyl*t&bW8i{1>J$(Ms%Z-653 zGvXOWd zlUFyoRH=V$%0=bB|3L^QH-$HN-5*HeKvX zT3hunB*pZP>IpAQ`-K?HFgfqBV?Xd5jtbuS+ZyJIY2_J=b+3^BQlsrb=tn42e|@| zh3m%x&mR-f)CCF4gUpyIwDUt;Q>Q(%N{W>ZF|BIj9?>_~x?bop3PkQ0>-|oF&xP7$EVEPNmgc%W`D1Yzj=GN3 zywFfmTA;Q7MSQ7_m>oHpxZs+Pe(8u4{VxLqXSK0G!7hGU`S?w9ksp7{`y z;`@O@inFN!BG(&#@>UOrkd;<0ksI4E%XZ3q&58A$hb0E9)3Y<d_caQF(h`ybA|NT_kXzJu;IERN$JmxiZK5E zFcXv-bd4|)rDW!v&MM(JAS(p^xV}|s?BRHM-Q$44_1 zdI&(!(npN@C|x7*&If$cyqflB8kq{T2YT@*Jl(J^``lWL_wHTur>LQnf+ksK>cE`u ziFdD;+uXuW>AtuU7Ta>FY?ze+fhD-P61nFnF+ITnhhj}vW#;@gkEsfQVB~MVm2ebU zc8cK$--Khj>1R2ws2Jr7f2GO9@6l_dqs1ceYb$N)LgO!PUXd+&wy;5-_XuesdGFem zxw>!C5A@|qs=5s}S660-&Dcrc1gdgUEyk#~8|!)A=E@LTlTtDSxEWT|yF|I38gbOr z#1OrWc+d(N^0g7_0u1b=g$D=LaiH@b`jcv!TJ(p$gSY%W#^>wN=-?bD;K8w!$2BN0 zN#ndrtrJf0$CgD6w)CClDN$6=0i=LoVuC=ah3DMu+RQ1+l?LM-b3Pj>CZsaU@v}Y0 z!gUTH7}D7ncb=Qbez%p?dZk31`wAx?#2?)rKN^jeA9cz12L2pJp5mQ^0(DMRc9PYD zy$a5zb(LS{aj)c(jBk;?!1eDh>=kKk6?M@*?7PDy6I`7K_e66e2 z{aK+Z=FqyrbxrOy{!=7$QX`v=V9ke_~#+EUgQpRC!>l^{H ze4*J(t+56-^*0>q8>_lNpOXtwP(PkDQBV8uOl-bS=vV+bCo!w>csw(+&N&a_~|py1-#n?-bEtuf$kahgx~@@O)}QJfawiF za!Uc&85{QU&J#(79zg?FXq$=3BM|8N4fR#QWz!MWkqgtTJ7D&;p5-6hSooj;e5(QxXX)qgeztYM+@pxi zJRPlLGBDDV!znu6)M6z`2QDlmOOW=hH`tkRhoB1L&+7?ZUo*YIhS;k=k%fAr1l2V% z_M}DBy(b*tlV`eH(kI0m6n1l($W-lI4TAJxD|Ixn+)XtOF?X_ zVkjEcOIZE^`)DR=YTJ~t3m#>f*pB0P(ElKe4yH419H4AuE&oPrk%r3B)FIWp>7&fD zt}P>ucl*4iZp7C{-b|dMFg|OfjNZRcVM@=SvKUVnpM_;J% zdoC}IXsi8$rO}36eU6mvB$M=Y;G_5ac-QiHK7`=^>FU8y`RN(ux1}j%3m7FSTqv~` zDY3{pc`Al7R+d#>W7HuIMLlX*X`N)U<6 z@y(+2TKCElw|fSK6jzZXfU89qhH7*uh>J2$B8WZA)QGw11vybpSgGD_G#@Z2 z5_}tL6Izu@>Ayr{E-09jdJUkxiq7l$T4=b~*N@`+T~dRU11zggQh0C?HiUUU@t2;` z#oik)|rwHIlHIrYo4cnH*cazOtgDbcWc(V z&q3@F?Fx6TD{LyfQ8(gq>EGRBfypD4Uei1SIAK!F)jl@qDt=)@k3jtA#l`F!I@#tp z%7q`?gv3sqDtZ@<;kQnG)o&mdmb1HK_1f|Q21Bwd;8O{fGPG85%@00}^j7D{M09S>cc4eeTQSJmJ_EC2Q%Mc4iDRYr3I zqPkzu>RaZ-?*{tp&3oZn{U4++TYTvUxGb?ki)|9vfx_Kqe#+K@nbu1`W&B999b=4h|QIs|g7StQIr$WsrMw9oO|YDy14dc#zXK zz~8$!dP0HndZ+=&)3`VPu)01R)w@04!PFb=w}1Wlf)#uUXaLg_bligtSq4(M9U8Wx zr5e`!P(&h~0_~^clwR&IqVI+@QJ=29T$)CE(uSHPQlk?c_aeW}AIm#?!aLi{4S?V=_4g=QOWmVrSuYMp3IjrShl^qHdVo>Q$Enp~St ziv?px3U^B*<;sp_FICVv_>MWYbJxqN{kWEF%#5p(c(#$^3_ZKZmpI<(8;4y&KBVl=>f72RKSy5y-Xj~;L33r(pM56ENnkWb?-FkQkrDauzS{4JQ^3->=UY1_l{2>@R-dE8k4Td$^{>~SDyy-*V@lfrSf6(e^( zVgpv1B2LS+e1##C(G;?9z(8?7!(i|Ko*KWPN8k|v0H))8Db8Hp2RzJP!Jj_Cn(hEa zKYt!5Ag8}!f6#6^uIo*H#ELFJmAYKUSTCl0Nj5*ojvPF$4_}f8Xy`w?2aBtfD=fXlnK=$Il!`dof;(zu@wlF zSirNtga*`fO!ruQfRB6g(rg_{!dAyqN zuIJ5#`2yrv*B^vZsh%f|)+BD^zw|o)71|d>uwX@bs)nmH3B_cmB}mCcL?8H2LOB{i zx3wi5Sj8u)!K&6w*ZX2k0`UA&;cm-*OlGJtqc6{_d)ES5)49N9-9+2QBL4juX?>7? zFzc;%j3>ZCDV!Q>x@rTyAcA9Py`1cF|DOc+-&!{kugi%EIO=w8SSoxwfFC;y8%#Q- zm3wZ}CFTtv37ozvYkPK2m8Dv@O*{dTlbV_u+n1*shoLX^#1{_lV#L2(D>+YW_&-0N z#H*a{YIXta!pgoxWgffxFccGA#E$p$i)nlP&kVEcykHI-qJa+}v!0OAU^Iik4Uk+p|^PmCL*d*BTC)Pvb_r1o{L z7F5c%)#RqT{o?ZQ#?|erJXA+#XOfG=nKEsuPffjqzcLrN?Z7yn zQj)WS%5bhbhgy5}(IwD29Gufau4Au~?r!kh)dYqjo~Th2NZ(6z>U`+d`H*9}=Qq)e z#xIv=F^=q7cNKvsUb}t^F5W$f!2XWrK+DgioD_IHySIzq-Vd{j$JH}r$Ek-GR$hZE zmvAna^V6yFf1gEEr&M=dBH=XbP9F zKIWnsSxe97xg9$&4lO+G{1ZDjDI}2o4b7DqSaX+WV0t%!_ zv+s-u?h7sLr#MMqwhRpow_|c$nWoL}qVU#a1!^3);=J8TcVK?jE4szYG~fjQ5=4fB znNowH_%HP8Ra=P}a)|<}sfxok9KXa4E*_1Af4A|P+&5(p6`{#Fu&3`-rhU8!X4|WS zO#GQRj+aH`bpF|ud@a9SZ?NOYgh~N5pRCDOYBeMLC}B!MRi!Ojw-~96J75j3E*3%Y z+h*_Y;Rb8cG5?kkO6kYlgqM0y*RR@U{l|-JE6JlVXe~)82&k@}MZ@~5_ZuI2gl3LI!UT2ztV7q^hFk!4Ic4{Mw%$9q+q-*~3@D8} zXM7LJ%M(Fs8;wFhvO2K)ziN}z>*tIkX*5dAT38uHZsYeDDwm1=&dJXM#-Wo zZ#bM{q1q_u1bHwG!AlOp*VTuW8~c;i8~atS8#_RG2|7RX$ZG(`OLz`Hfj}y(Nvxw> zn~A*!$)8J0OW~$wXGu?)QScZHmz$g{S0UO6Un3lKyZ(32@j3uQ&=HO zti_Px5m>MH0{vtD$hRS)rK@r01!JRAD(oeBBbL5$=9X(K`^^5trdp50JPEQmAd-YV z1?b6-UpVreA_!Y>{Eff0i+xjx_fVOD2>8>=g!{?_gvx~5O1!(o!wr!H2I|hd?@L$t z&H(BtWo37K`@{h8mSGKl*N-qAsQ*iMS-MQnk9KG-)YBElxt5~ISy?{91f&(=9CVU3 zHBm$%Va>lsU?f&5TmOU}vR|Ujy*}`Eav$GzG4OPHyaaMG7O%x`PiN@>;sYR&??kO~ zHu+OxE#s{Vyz52q>Cf4=lA`U}aD)LZU#I3xzGnW;+zTqfW{E_Nv6DFu65F$-V8&)d z`5om(fF{xP>I?~c+zrr)XTK{z{|$!g?4~ueCl?yQUyvVe;^#Z}rVivFCeIiqc69qf zjMViD-jYzJ)yFLP`$-FyVe&_*Y*=56m16q#zb1-*c|fS{<0o)ihNgAn_FvGfyMV1TVeX>a`S$@9* zeMwulNQhmp04(x>&(P&M zdSyj4uQp{kd=!uO?Eh;4(kEbC__g%EJ#@Z|Hr6)4ruE7hgb0I;^L!oW%v~=vR0D0w z-bKxnuGJ~U-7TH#tFY1iLd1Bf7D)FLh|t3qzg*^?FiQ?BJ75Jr6q#*$kD`mtUcGx* zq{4bvHUC7^l2*bdgS}elb!gU)haQCCUgE-nl@U{Ue#e(*7II@q8mK2vjnltv9|S&S z3+XG3mO*O5_vX4DzC;Q5Mm;!T(zk8jX!e52e=TNud6lZo{p?2GzM6KtvpO5_>UKxT zimkc&mKeJ}Z5Vd(J(|tEj7|+Ux##G9dBT>23fqfsC)3(Vv-m z4hYdgXhl~hJ{FeF1(o)P0^c|6!g;r!wXb9$O+~RD=|tZc6I&)?)}`byPRkSG*A*iU zeV9l?CN4Gwqvuy-1d=;H*k<2qeXsgcxMvElP}4y@UxsPKsr7x$PYI)O^c%g=8y?MO z37eBoivmBjdwAYT#8=EFY^JLQSy+E5Ypk6^mp^q|9V;{I?6T>*y9=cDI4(P#Z}3ni z80p#n<$WUq#aWDT;YwPG2zD=}f_gYpZ}76uKpsrbAcvGI5tZF%N6+C2H(P3boD++` z_uShQlRNIM4^k&{2UE2V__ov-Qeb)`Wo#+;)gqH_#~$p%pdqTV(3`V!f@E{0+NWin zNCPgT={sGul76f)!j}1z?XxcuWg4!#Vyyb!Y%_BgRoH7@%reM@ z^mpI=JY6XY2r5U9uGYB%qQ1g1qg~Mx)9%ncHeS`~Gnxl`vwZ-(dL{0|*XZ5*-j~Sv z>7eXFtUXM;UYXXfWNBR!^1cqTBV;cm*k?D%HGI&2S#UwoAYR+8Xx0Sv&8qi{5b5I7 zRCg#NgzK}zPr1{J331ZghKAe3-YQraPik@arjbp2T%3Z6igWwwUehR$PYZv<{99FZ zzKe*Qqez2@gha#0D418ALlylk^D6~bX3b^4dD;(^PVv#G+l*OZxJUEqUT-ZI$0VPa z9;Wq+F>7%}%K~IA2lsag>6LOxfrFA*`E1yPzdxB=6p(ALvCDKZ{dr=p{?mK=rzn2`5f!VM zn)^u~_GJi#j|Nsd^LceEMZ0q75cLso&oK$N17! zZyYNNPUJQ1sb9Xe4x~@$swt-H6pf>pXM!yvJ*kL(p|Il%<0Qi-Ve*lXl04D*l}zTb zY}z_zn#T}mIDimCluGW?R@|++lELZv8G&L8&PL&be=|&Mo-U#C>E8$}>a?Hervb?_L=jUew zu&x|MqgFToI!Q`OqBq}d4}A5M?G5SC2R0<0r5}=~j6{zZ_sNVWzPmPDAhxB`QU>;iOCUe4bl6 z1}I$QlP~=c_9Ww`$i(z?K;I_!&TYrKtE=YNuE~7}w78&zK4S`2i~w;D2yK3zLT?wg z$!+ko138Iqo_GjnV)pd(e5zymlraVc*7q>sr{0Z}%fxuHRKL_*^4ABIECvW8aN>UD z?!KP2ojaY5J>idFL^*ENHeXgr4YJ-*X)vT|J;P&0)CY+4^^eWyP&NsttF=Og+~+4e zd1YOXU8jidw>O8X;k`L&uOy?pf!3BD8P4Typc`=v9)pi5FQu7&h+ebqkETs)+(CI8 zxGiRa^l4XI%j2kaYHEu3LhYJ3vQHnWd^$lk{}p<%S&Z%DZFghbhRdZJ zZC5Zmx;2^(tj@wW>FK~gknW-&l?y`@t6h)M@9iS@h3e6%X?zb8M4K7EFns6&zL2~l zDfBSh8~gTl%7qc%<);{i2H6166zfTf+~2DHh4yf4wL|X>TtIA=80ec{xUf+1VTGVQ zt^)5N(lGdkCMgI*Ak45j%JS$_<^2A58R;ipl`rRE9CYVj%sZi4t-3<6u4$s7v$2S} z37&>}>p`S3`ps&**`L^N1pgC#7?%jzET_QP4m@^YXmG}J-Q8A6g6l?U#jnClcZb zLYHA60PY9SLGs1E-upi#VoeTkJx3I-Gg?JuJST}6H?}hF$kI+u?103<_-cO|*fLc$ zPhUm9Y2Vn}8htDGaw&(+5y&6)q{R@FXNL3#9|IlzwY(~4H48$3!KTZ??bMy}Eb6Rx)hDYcqXFnZ?8ul z*#@Yp4LyXZt?`~&jg`DNn(#dx?R-oqW1OjGGU-u=VHaqe4D)L*4HRXoCE_l3r8EoLQ;>Y3`pOzWS!t2 z8|$Zza@uW_tr&s>UA}=eXgQX5HEz!)&+hor74EHAGVa|6j*Sv}5*Nvr^@Z`cEnSjD z{sl@!Ws2jbn($&-Ts*D+>VD%YwcdRQ+L{9`y~QPH;+#}drK5V0{E%dD5_jNCm+{Ks z;LUUl^AEj{!?#AeVe0BGfSy}vA#xWbVdhNCB?Qnkm!{*ifxRLlQu!O_^E;#FW3<@v zg2!L6aG~*g50B*{wq|!oi>qTke2;XHL(I=+V=_VuY&VDFgI$ms!!W>7o)^~9yiJiH zXPgAkz%Ng+u5l+VWlDt6)S<)0a$#p;FEQBr2%Ew5cNXrAv%JhSFXG>nm5Yjt_l}N? ze*RqZ5gG+XQN#P(UBKk7PJc;U`?5;9xeEUVls(H`>dy@{!|eHTHfsZH>jz_w(L-EXQfz}pqa z2qG$j04Th*=X~}v=4b%cIKmS33_u0NrGn$#m7kBiWKuQ0_ZViA6pZ<1XkdP1wf-YQDt&V^G*v9)o6X@6uf9kEbUgjZ2N0O0|i8+7l zysR9+s@MI|1@fLlYnPk7K0kgV>WW^yvSsM%>5zB@nu#-PQ(Dhp6c8yyQqS6H3Z>@p z5O|Vn>0B#LnbQ@+0xEuT6XwIAxct;*V*FFXPT2fkY0GTG9v`O zI%GH;pjdGXNsQWblzXL^^pr57iS{?rh^eE0o7vuNILb8N(I-}3BEGa&-bjd0z?mCB zuU%m?8op48tZg*NlO>+_LQOq!JB>2Q^U;$`tec4rE5rYxJKkf~Bza|RLCGBg@#4xF zt95{?4wI`k2>>0w?`K-jr2|^21=c~JqY3j(*A{@}+}(v;z=(M5HXiteDaQl(5<@EK)$cUC*5AK{L$Nj^@zwT7H+iofW zvJm);zwu+p6*V1w7NB>4C=sJ&Y0N}LdTc5tGiMZI#xdggag6SO`kGkh>+rIg=tb#C zpZAel&Nn^UAv$^ZbQ&3=49w_X0B`}cELfN5&qv=isHFCofSY4#jF04jE}Ppk_OOP@ zz1F0hF6Ip)%{}jPWn^_Ub!DcSN7FnQ#4w2GoS4CIT8sfF_pq~PO3Qm9r>#X^5jHBm zIJZ<^-@B`vAAcGkbx=XK(Jt~Io8&s)YR9SE=K2fTNyevvZk8ZI`jPkO@`2ygcv{{Y zYJ?!0;neT6T$h!M=hBNWZECqEcX1jhBv2zFtu3%pgJCkyZ+InY%HSlcxwD;CY_7JN z^pm;}=%(2LIv&m|jbdV?oj=X7N-^^@NxKipe(SX!c6Dd-XXV6NGHg+_4ibu{oYH>* z%lx`Vvo8`ApjaGu?-GqeFjivDS8Xgd9|5RW%#(X3bEVA8%#!|0lj7Ddj?_c0z8tq) z$db6Oy#hYI%xwT-#0_vsdu(B{iI&j_{~nAuxDpNe>!11rBUM4t>E}Lt5WuQ(4y49m zd0SU!4B>qMo$*kl_+edcPz#tb9`mYJ@HrHUjyu?g20`sDd$b@Elhk7UsB^u zvC%t$`l|Q?yabuqfd6|8>u=G@7l%_;-4b`obfhVWDZxwAV2TnR=LOr;rLT#Wt4v`T z4SrQ|CSlD25!yQ!2~+2dQR-%Z8m~{(!T-m7M72m@%u@1|1Gs1sqboIuwOuTPM>=LxAHKxEvSG?ifq4fg}wvwxyn* zpOZiP$ke!9?3}InW1RPsN1P7Ql>?)@xsGa}4I3eJYE^~<4Khi;HdmMI@l?|^I!RYa z#26DFVWF*_2SvR!pswVZ-CbFzl`7zXo3Nb(9e>D{UY|mVc5DyGc_j={4pEJ6FS~f} z_K;xm8}EV+Jx=NOL|E z)wwkF+ZwfAcv;2fvXDF*vB7s~r87oqaJ7yE$OV=rWrn?=*}7bC@BUcne1c#u&sPS`7^T& zT+9bO#w!Di`@GhrR9i~`_P8(BeM0u}IB89g^V(O6Il~bz&B^%%Kym@V$EYdjleE9L zmd;2lX(pvnDu?KZ>Bca)XtRJP1Co8jM4M-;l{$4md}yS^Zo_hUQr z{IT1l;N`(q&f!XPlR+%p1V-{@?ymrGu&*IF8vdOq1OQ~y8=Y?DcrPz=vZFYq!3}vq z02>{)!kItZb5m}XJXsd`e`n6jBGdE&W2A7tdGFNly>V#{m!Qq!MahJHw~I}B5(Mw~ zbW=^=0z1J-GID_xX#mV+X~svEc0LES8GcsjWSu2RyL9y-)x9}a)CJXn4zw=!~F z{;b&SVaNI7kQ9Mk#@=7SzRS+@;=r`wjz5M4M3y{o5g=H1=5Att2~ocAD*?;FGbl@Y z|JRJgm2UVD7~Iwx>c}G1X#gruaG!>+nXj1(^)k)GAFxUTIwnC?Gulb2+b>#bU7Q(v z2x}e|?rJkzeJ6a}=C4V{(pRY-E;brF2%;JfoTxpo&JnG>45_Ms#@7t*pDI}>fuFbr zLv2UOI*#o>N?_&XY4YQ0ESR;O*qsNX0&z4k)-K5%obmaaiafNawvp3cDdICmYnE{2 zk41qicK;d2%SkU5uA$e4hq90hElvxU-reAx?-p)+=tR*JF$1`+wd^CI{=mfIEd76~ z+-8~7uCxNcz|HFyC2|!Tw4mOiBA6?CUBfAwFJbJ#)=|6w$|>MxPS_OXsihSYlk*r=kNUAZLJ59$zEC> zirn5yT-^sCi9kifRnIDa?}o>;gt5?##p-7h=B75%ezWSX77z6|n#UgDjirkO(v+qG zW*o`00c8gP7c?ZCkS58cD5gSfZO4@diuE^PL9LRbqXY&+6XM3^J92#!;@{-R(|K-j zLBICxUi&q$~zxR#`5dQvC58SMHFrK-ley6Z!v;Ov*e8;J939JL} z!Z(N9?vj3Nc;)wYCEGEF%3#j(D5^5|#2aj^J<;?=mJ>i49@lp6mg@)%mkc_^gej)0ot@@ZujR~mPTK_l0V^A^93ZFnT<{&@niXWJE5mz$&cZ`Bdkbv zGM?vTXZl@AG2DMZoRv{b#?nZx9DiW~H_#2a%tUZkq1xW^CUVuL)vN!ee_%aqDlj#G z*8TR2smN8sD|s*LKc>hATz228{f6R^ei2zoKH3W#JYZFE+Cg_7g=9~Bd2V5c-fCCtJ=@GPI=$vnj3+qxk*v= zA@txi_1Dh^IL~F&@+7v{*G+R%F&j}bU8zer8|OXSNDxJ4D^MKVWxS^KI>6=_jU=-x zl_3^j!X>2250>koRaElI*mSOysovlA6V!@t*Fjz^UGxIi9%%(h`AY8#mPXIaWdkBe zm)If}XDkhvj3#lRcXP>Bk7HpMX4F^Xwq54?WdflqPBt+I1ijgfr?CO=7}Epl-Oo*~ z7tlRl<{7~EiZ*(SCH9OjPsfeJv0zJjTLS%8Q<5r+W#E5-N70}?)nv>oYbwXxQ=m|jKBAQQQ$dKIgO7WbwTzy1 zZU)F-9elM9mq1S|91|$smzIs?qvJHKT%yyO{4X@8Ixm>f>p~t)m;PXiODp3DxCoJZ zJI|`X9eXxLSjZO9I}&El6E!J5?oUHHt-yQd##-k>?sFQno{zg;D7UxebrTtEyWx8Q zz29Ywbbe$6MdM!B5eLcd?t-}GcIb~?E8<|z-6)Hr>6)FY<*73LbWSP%v)(*jT`O({ zsUE8wyA+a6ke8YmBwVn_FRPF%Fu*{Kf}{R@qH<_=@SXe*E-dc@Po=y&6);_Pep~en2$ylu7>MY^2QwkuY zHvx&!7>`SJVQK8YOBek<@YI|KXpD0zS~yTl0bW8=o5P-m)Yja$keSBNO4IN8myla~ zfJZqz%EOS5zYbbN-Z)3Bk&;|8WnY1M6_@kp*lWIf91*tk0fInj1E&28yu@Q#f?p z8d^`+-G_>3Kg`OO=3+r59Fh`9SNJj_%IC#&JO6U(Z4r?#vqkJwWxr4^a>Q;rv@HuQ z%9m9fk(*4}FU~uiO#RaN=aIijlUL@6A!-W{viOUz5KKks4u?ol)>IHoZ+>d5B^M;0 z3cMU8A@0e%+4trZt2PA`8f%&ZUe9rCL27>A9166#%mYJ6^mNfEW|;+oeH%jrM_S z!(JNgNR-7ZOZFXjH$2aLwR0{#Tjeq|w@J$rdqh$4WzQV`9p_tSJ8yFtsIHEvlsFv; z@iB?;`O{*cLv`- z2iW^~A-lPI;CN8vaoOk?N-~5w2RzOdN#1--4*3yY1qd7MDhArY14h&Sp5NvTHsV|)uQl;kc;OEqJS<>>I0X>&{OX?D?XSaP+3 zM@m_HytiAA%%Z(bF+ab;a)Jkh-=hRAb`PBDml*X}$*Znv^)Gu42X5|~f1YzXdXL#| zT4u&%@_)!&FXM>s4wP1Q?xEnxf+KtfFind-r*j0OqHg}VWU7Cqseu1Bel0d39A($4 z9SW7oSd?>LIqX6fwCW=>;Ccv*;cmv%->FZbaBv0(8e4nzo00mv*(9@IJ%=ymtxf*m zD|>oboBe`RUnIYuP;ltVmTBVT>grn6OC~bmd3#CtT%i{U^jR;|A&edUu^U|?FF(-d zJ&hBrGYI!A(ycF1czNt|CRyaW z=B}^e?rzhDe$xH@UpPtKY^OVV2Y%W4XycsQzeWE6a!pGGsrvvQAk8Ih)rd5G0Em}E zch3Ia^HWo+se|ZJx>R)oPPSP7bl}HZXJK^Do!*_WyfE7QwZ94xCXwndKI6pWJX5_n zL0D@ZbF_PYd|OM|XDpV^RS|1_p=bel_8!l!GDm(c8*;paK8;Ip2`kv(rVjmoEdU#| z+pf_L=l9*~OTCcdb7PqFnxok0!TP zso9wpSlO3-C68-=k#w<7WmTdtZ515!&r2?XThp#H=_mg5m>k={f=*DRU7d{qyVYH8 z3oZ3B(8jdk$qi{!TmC3h@?Yd>{G)dfM#bx9dBK#%oMt(?RaCEIJTUr2jbkpP>i}p+ zeY$m8`sv90I7bJlt}7f6*VaN1&QuZ^>wFg4{-6_i<6xny@_Q=3@$F!Z`(mY6+aAWvGN?$!7>{m@KF~dGLf3O0x znKM~!Oya~(A)5ZdX`3lb^kfN>c)PX`LwkEw{B%e>JP8C9&I6=|v#l;&=YI*)O7(Jp z_sbEb%rCD=(4%P~z*Tn0Tr^mXa5$qG0#|9RSsiw=%oQQZF77;Kt?d!rcK0N!pY%BD zr>S(?ES22gzPIjlh4Vj4SBfy>_1s>6q|Jc*l9lT2F*?Y|hGfUF-L;$-&WE~z_h<<@ zdnD55h6Ozz=vl0mcb^o9ky_&3zy9Jxts#JVF|As4NmO5bC3s?dn_K^Cx8;OpvXp=L zFA%IkR@rFcJ#MQ(87=8qle_h{iMDSq>;S}_9&x6mTk~i5vp*ABT zRe=tPBwPv02U+O3>yeSsbnV*11@6=z*3{@}M?eV?_73Gj{}&>v#2{JcJ)whKHY-t# zxp+Z&v|BqtoQ!MPZA&7H6|#I5XTiEQFu+wC*d5J{=2>%JQaREi(fV2YrJsr0fRK*e zS~FhUTe9VWie_u)V79g*N7lF*kGoH++ZoI7EH~=lK*YD{J$PbjAjY+08z0$yDOr0 z3fN%obpqb7IU-yvp#H_c6Svy1GaggZ0Dd@NJ6;fCO8QHaKpqr$#MM9?`e#vG&W!S4 zC$(MbB4Gn+^+Dyq?PNgt7oRyT?Hgg9ez-tFOUhJ$MW}EgP_neq{u0PuTK^=k>GmLe?D*d&c9H^Ybd2gB|hh z$o(sw#WadS&AaSthPa;ES1V5X+{JjY`U~hU*Spq0xTvsAlREH!?5q9qBVb9i#pHi) zK)))-Dbz#fz{G{EZ_sC;2ZK+9IzD4PL0E63%3)5PGjyJe^IyIm7h(0JKGU+$*DOol zm)+`cpIv|~bJF(fs}yLl4T4Bl9CJkYvr88o^v3&1U{F@qbDUWRsI4)qi1oe1qcdYW z>eKf(q!QTW2A}YPU_IKwom=s&u-G+5eI-rSsJthE|7sHVQjM?KsWw4p&H1PvEa?`4~t`|J79G9=5`kPvs82Op4ytrx4{nVzc z<@#(1g|%uJr##5s;imY>5!J*jELm-W4H;P=Lb7qSr$}ATnzuPU6i+rv9kNjn3HReS z|6|V`T1yRG_)$B5IhyU$xn%N?7gFmIkYEtWIe&P5xP@_d@xSeqt@m%k) zuDde%zC~a5H1V0%pCOANCdYcyfu`VVujAZI#(LZ}!c7}dD1^?)KwRkBm}L zZ^Zv{k;KGV9>vSgs5`k?T4!4ZuB>-Yf?Wse-U+FF@!uf`GrO-&eZ)TIQ1s zjT~+xt@AfZa&L)f=Px6G>DHjm!L7MVIl8L@ayFC? zvFGExLg|Z3!h_D6cFl#Mu4?ndJCmZhA~_RBc5>-@WY2-%fws?2D!c$c|jO(cSIA9NY+)8itC$Q`Lm}$6Aaw#0(tY@ zbScW&V8@+7Zv}Dse7f%Qu_Eqhy2By-IMD9^_!$?9`eO!5CAPRGi_yHjc&YK%o4Ud$ zn(8Ac%^Q~cBbb+_2(5(SMUhwc3fK2`P>xi}-3cxyl|-W}R)YZ-Af3P{E7ErY*2pFk zzJ9fLDFFQrN87C<09FA3;FXAEy_>y7tf~vu>e=rDAi(ogvbQ<*o~YbCNF`J7(PjPC z-P}=D=7W3*(VM^3qD|}Kmh@VfQ{bm;L!d2P+|3I!;su;Qv$Zyb_-w$xW6Vp5%414v zb4#`~5j1A;x6&wJK>M=WrK&2iTx()r6>K-n8nK2bPo|X6VHS|3dti6L^s;Jr18 zQzd?Sd`K7K(oH_qLj#kd+$e%&7P*_yvJu#ZE09=H}S z>LEFu!|j;9J(lf4Q=q;hz-=$A?(D0nEPXFCc?}KP^|*|)TO=QXLC=FN-m;yvr62m4 z3;qK#Ufdulz%Xv}E^A5t&9Ru7FV5mlKi;UY1>Qaegq<%c590%Yt}>y@CsdF(JKjcc z`AxgG;7SLhK#gr1=wL%V#@pNS@b^;wSaCkX#yre(W6sX!VHLmoK!v7Dbf%_~IHh5$c6sF9uJDz+Z5)Cv zk|$SQfB-%fl>6&rY1$8QsH24dv9jLZGG7=YB=%L`$WPjLTPF9@v42(*IHi&5;|2S{ z6gV=u+XkxG$&2m4QraM^#2n3Lw+q%)!;V#NpULfu8xQUXsqOHgxSN9oXXB;CJ&Q~jCi5OB1zuc#s5%)V{Hu>R9*JB&(o zeG&)!_>B{!kQQDb)NYVfh|CQYBNN0v&$<7o+tiX|zUT7M81voNfVqei6%~io`&Ui+ zJev0`kE@zp^raZ%F-#SfK}C@%jd22yJ3}ge8f>2!LcbOlQROIc24KV29Cu<*E-k$^ zawUL?@mc8eq7yYk5%_6?qp};}rpY+La$qy4RHr8}K!=YjPlgK~D2qSp zLj#Fapr{Sa@z9UbD&afP+v zO8%+<^I?4gN5BCL?|sp%-Cg}Tqrrp-Kw@|EfT8ICNJ^5>SqDKi0^{k_4}uanF3_)r zdzdGAQps~QV{h5CiaMj4;DAHy7W+2N-!(SBEs#9eA_DykPvbw6xx}kg{a;{_WNCib zeeSw2=%+C-Fz?Y2F(PlWV%B}# zbfMe%C%85vU>ds|4_{-hTVnN@UK4WffR(b)?mTzpFBrKn(X%wxg4EM`GIjv~5@XOs zeaoYv(>@vhmL-z0u^m?WA8)=vxGZ#zOq3lGfvV z;mR(NBLqCIewaa^CY?{RGeeGtr&;D%yF&h#f&MPcy_rz$zd~Iv4L`&N^W=%zF9HlZ z1j-xY*9O5N4sbwnwo}a^UUo!=WhftmRL^O1HEYnf)#Q(0Gf?x-R$2b}Ex)i|o;aMr zH{g2`b(F8G88cBU%R^a=%OUytp5n(o;@O2uLk_%~fPdB7OZ`FGd19{zPk^m~R1JiF zXEfv6*<#H^s-Z0^!lo88FWVn92TkID4PY zW*GjsBFoL+j*rivVWnu?ycHzls!tzZLTqslk8328^djsc!0xI!Yr--AMq>N%|1tO0 zQB{6H|L6e}1OyB~8tDcp=@1m8ySux)Q3M3(?n8G-my`$yh;%ndcQ@R9jQ9PnyYBtt zcmKL9))|^Q6 z=&!h07_f50Dtz`C<}~k0XHhSlK=KU^J7%<+u!ePzN;5Q74UzwEC!B6?-_tx z^zVgaC8PHl@hei?8BM&5A&abB58j|gIp@V2)#CuT#`)l$_?g!IjEApyJomO4GXuCw1-VrR2cd`qwy zSp@FnP3fv2S*@SI4Ip zEVQF!Qt?YiAgq!6fiH84?()26%fOAtb2C5|@2LO>@cBg|WQo8bkqnHs?@EK3n;j(u zUuKh6n@ zSQH3IGe6z9MwTM^;)<=VTdWw1a7=!fQ*0c2^}vH&+8Sjro~_j`AK62di|)tDr{4UB zL^tS@6jXgi8?^%MaXz=W1*uvS0Uf6{Gs5;BNM&j6lmG!a^!@atMMT0seCOsut%N7g zJ_b<}Q~4#`fa0p2flE@?ON^roG0hr*Xx?U{I$QUX>uxh|Ln9|{pPPGHEp8~&ILWE_ z30hq#GTIW|LtN4JJVGB`D1j>Wn4E~trOJJ}Z+zX3S&r54L-T z;>o^3e^Dk=zKnl{nY4J!yANMr;*#Fa7uu5~|J*0NML_RSZxRkRO!ug=o<`4Q6`aq| z&f2BcWY9BU4P`CZa-#FrGbo>*-A9$6^7KdOZx-7MClVyaY1CHvE^~y$l(iZ>EXQ_n zL-MVhbnhj}DJU>4pdTF1ev%-Waj^V~O6d=|0+3_(HMLHjOzrbND zQHLV?FXZd?q11^L{&6un`r@yVIw-0~5a8@M)Q6x%^m^ZVrCd>9$My1R<}vy^GK6eJi^}1tf;s{4)bST`xr zbGyaV^;PCg#%jf|DyRXIds@g!agDiz6OEfLwEd=*fWE7(x-06jlv0A$qJf2uHrbU&G*o7QC*ybL0IGqfkeAN!!6PWKSeMfI4%*E1xhT_WRFW>Ts;^dVzcTN&U zaiNIv17w(Dlw=xxR+hO}?nGYeyb$(5w#k~nD|{*;t(;=J#yV;jH?#fe;!ZuP9On6P z{YeMT={p*fP!4Uu&pBZwAj`;{O_V(KSEj&Bf6n@iAGPuj!%Ugx9;@1$Sm+J2^ zQeK#UxajwilosIa_D_E6|X~8U9i~E`Bv4Gnl6AbNW9L z6@ix}Ih7}}U34nQJ~_}cmYN7%J|AQ-fo8qqn*Ewpu+07G(~?G0dQ5De9?>N4kEyYH ze8_~u&iM~ldD?Uu@?!#!2_~_A+p!(XHpQ8@Qw|eeX9n5Mj!RG_KPw#nmhhJ`+*96{k3`tiCU(O< zB%DOjaPemgK>9BAXv@W&E^SNpw&Q&*oI5vJMXWIwaIH=d8TQVzKTvH&TfGOP$=lq13x+MZkk?d&TPb3J zpl))m24g2yQqrr&N35au0C(m9NbE=4i_}2^Aj+411bm^nQV)BLU&TUKLKU(CB7V!% zBi8qYFRrroNUJ^vm0qRkyUt=4zeYsD7q#10id(YC|25d)&%4|+e(Sk+*yFdmEOS4P zsdQ;qqcm%$R>pR9jKj_X<;1E)^ZaUF7wW;ROxw3fXv6H2o-E$c+JjrCg@-mvGS+gz zG8$hB+jdzmg}Y|#>8Bc*{=?7csR=odR|P{{gHL(x-tM(q91+Hd#H6srb3y9@TDJ=b zD^Qt#JE7jNScLYTWO*}Lkc2`$dc&kn#wEbEl z9f=aITYKIxm$22|^tP2E23j8zc1Y{(b%qXsCkh3wTJCoQezrn*A2+?H&`+s-Htj~5 zCznU(Sf6a!dOW<(EEqfeIilN4HnVxX*`Uc$z5yKZB)6-NCg(_&@SR!qjyRTRm}pLC z6Nl0!xcMPoRAENLM+2X>Z!gFax+V1*^H{!ahii+i)c0~`-&1;EC;8iM_(6MiF#hc2 zAyasDWe!!l>{K@GI^}|#9M<>smwsl^ia+&VIr)aC$@StgR4Bmo!2^=l<EMDq36wIh7b#}<`i%YRclc%Qt zc!6__WX4eNdQ@>$>B6jVKZ9BqpE9vVJ3xEpdzj5!?^hoFkDH17XIHA5L0eyDqiviu zo*jJ7r?hQ7>YShIDBYWtF;{WXOWqvI_c?Q8n{kCp(z!%^z^nvY4qOU*-iNy{#_03j zh0&pWW&!e)P00Aua8QX1wgvq+!V%%AT3v2Oq#Z=1f4MDcYwh z?%AFWJ5WQrW@^F_d-I&(jpJ`z%bP=beU61^a)U|=K7n&w$IzLX) zkg*q~8XT_~Jo~P0UdCNi=VBP_ZXZ4gEm{*j<#AIW4jI0TM#6PHJh7YZRc6pX?JDb> zmvyQNr1_BW9C)0rNS`baJkJ8$imfC*m+~d*Bv#{6{#SR#io?UPL5`J()*bbt( z2&rRhK2kJUv;mwJ=WF7=+o*DH7No)OaRf$Ly4JlfPHQuoc9oU2$G!GzIyN005#`O# zLQczEuqmXhZi=1@9GAZ;Wj)&3?BJBK48@Y(Yr39&N$>7`N8h-2`&5}yWn#CeD1BvF zMZtM$$>60l$+vHBA>7^cyM9N2#tBU% z3GJWAi;U?KB>3=gV%zQaRSisj39)mpcn&3v8cVgLSEksC4#6>MZ zbdJc-!N%Ln!RuT5C{>*FMc1`%6u$FAlV^nD$zSFoTkXup07ndE@I3neNEJmtv6nm*n;0`kb zzmC-KYo&0{fSz@Xt!~#{*2EuG4?@GS+F$(Qs}39-7a@%l9Ihe_H{OgG?{;k{UFHnq zrS$krU$n2r7n?JDvA_S;#}@m2w(7(9t?xeWM4QcJb3D8+GrsMuPRr~vUSA>fwr4*n zcWF4UdNe)jm)N~XgPb1cy6-lNGu`-^1+madug3ZDmSSs8#szP_H&cxsC>b!=Vn!8d z?^C|_RSs-vz2@#`ehVUZo-ngj9kRTa_da&%c6)pKQ+Lg94$yTAgeL*XBE)lSK^hCS;&z54ZoMXY**INUG~YvX^d~{D zDUZpvRc#w*pW-b8rn;P=iWYm{_B`_A2p7@l@G#k40pBlsF3@!?Cnv|XY3N)p=8JUa zrw;w~2FCDiB5>Df(lTyn$YuAXmSq;)dSn2VwM+AcG^n|@cpSODx7YO|#IHGEsVV5I zi*7u2u0ZOYv?lO}FNc%5;sRt0+WCp)l-@X*nKC|8Pkgpl0omDd$uxGdM4}gMGvb;k z(7Y9B|Ar?$bfRH74rz^$)EsXW1DPQ@r|SYVh4|!GTq(FsKM-e4*&bYS2;?MDF8; zG_cwJ&S_ZQMbpH};(e(q`rVP0Vy={Zu9S}-l5cDui8NG8{+FC|S`>wYZ9HQ4=^MLv zf7EF@VIp-2iMKcxMwvNIuf!Gc$s#Fdr~L9NKJ0%H8PdA(*L93Bm;_b9#cEH&rb{n) z&rL={P(}PIw`}8yi0MkxW*_H~bN^5)YyLi@%H;k{;auaSqX=eog(Y9negM&s-}yQq ziI0sng5`Yhh!40IJ+f2eS<@-i8J`rExf{%e&Fj0@v1_5@t#&LIPhr3$@=vqp!|We% zB{E~zdPk^H060H62epB(22n>dFGwYwl&&&bU#+(Ea_F-K9LkMZFMw={?QD|FPDwSC zJZtiqzw}X7rm8pM=w@i_vT_j>x=_okG(VEq(Aa#i_=1`De{uoFF^#jaLHZR=0d+&p z5+hnx9R{z(u=v`d#GThzBP8>$-btGb=JB>VRO(nhE}TFh_B*j#5Mb|FC2nRt8m zw2WoH^Cf2Q&vAK-i=Y&?@F|y6XJ>Q z{gz!PTOP3{0^9QM_T~DkcK(7AnVV>Nz=!8nRPoE^@8SN;Dc|<=jy=5sNI==083%x3 z0WA84=;BupJyf(kkTGLxEj)5-U6lCaA`NO5Q26GQeuLz)x)}2%=uj z9dK)r2!KQ*ke|p`Gidi6trJzxG#9M)dx%`uMD0_DQkRdKdyj;fnzSZz>)5VCNADSj z>xl0aF&bnlIP|$DrOw|l07;78Arz7^vAf_)2o6pi7TZ}jT<@sOZ#tC3vuTcS^kCv? z@el~A)d(^HKM;Y zp%pV(j$hB&p~Z{HG)kZ|z1p1zU&hc%A(h5Cjp%bn{q zbZtHB-#B)KoEpK+>nwlIx*l;?(_8&HbJMmRd9F%|kVi}BQ~-kc!>1o-O5V zDmT;R7qzKcGENg-$DrcF)0A;RTkZC`9b?jHj5pIFCSWnvTW#V-XZ7f0N#r%&_~j?l zoiAxonx_thUTo5!4IeF_{<_Tk@a&~u;jROpF^g~myAOWhw7*rtdO7(Kzavda9<(zc zkQ>68mGi-Oje3k4OGpwI#FYN(?}Wq4C)`}aoohtIt~rjV4xH!!S9^qu%6$XsGgpb} zeC5nFV94!>NT!paU#_)z2!io0C0ol(DjWpY??r>?wy7!{(IaylI$v_5UkVn#kZ`Ob z^D=e;Hb-a+JXOmt{%OAN1D|a4zA5~24}^PbX(oJhH2|+oFZJrg?d{I4=pJ#hQ(-=B zVV9JyGlSBzvZbH3UB0m6z_J zU&J1E$zAjdAGQsfpU)->PlUDGjAQJZn2g9TB@3|1?@?x;wREOWmNXGa zteLZu*r=TK`_+j3E|s;-S(XirF1B5K#pHG>EEJu(M^&)YefFO5sIIX+$j_{33e2lr zxhpL|S^L4j<$R|0Ku+<$Bs7=cJ)fm*LiU<*9(JbgUO|w>`i|I%w~_6D&0i~S)qRc^ z)z#Q3&-9Feer2$)9i%UTe1)|vlQC=$RiqqK+IOpX@O|uxDGu^_jj^NMRcBGwI~g}? z;V-^eqXy^tu58~0E8f@fx(_n-F_qfJq&{2L)Vv8YIm%cAfg1|`pw}M~XnxHy{<9K# zG&J$kxwrMkb>mVt76=QD%v8}=COsjA)De?pkR6#s;3rm8xUI4`)Sn#V5zVIP(B2lQ zT-6yVv3s92pRnX1^sSLpr3VeXrv#xaL+(pE(f4&i-o=jSbkP*}GViRH(9icrRWjYX zHq*ERf;P|gFC(-joZG%u=+9u0ypELYml6199xp$`;Q;H; zbZH1gCHKc-md%REKc`0uO3c>nKSc_8jlzJr5EO#(9cg8)KOA#|=mAOatN++1Ur&1J z)FuhOmK0cS_3I|Q3}COhM|6Ma_IavY>bsck%qa+zw-MbaU=%{=v}MNbKir}^9cV_Z z+kMXVM2(-=#)`|B)IW6;!~J$f_aVp}^A|)^S}L>o*DXg;0(bcn-*%?jAdbG7S2MYw zjOH3h)PF-X_^n>Zd$WuyP|$$AKx=k_YuR^={i&I~m+*OV;pAt>H+on1Q4LS?{-7}b zPRh`v&&hWU*673njbYKr?@bF?#_ox|3s^<5=B*F5X)$3eGVc2_1@(}R@njf~6Y!{i zHl27|DQGe8#2s6tvQWf8Ro@h?x%VPW4-S1n*Tj*9@Fv^k?6GA*-UdSap>2;!-Sy`E zoHzK5k1{z8f7bp}eP$Hvqvz|m)nE2vXiKl5p^B<%Gf6_iN)b?RM`WeN#L<(R)D+g* z4{<2Ojfj=7WJQogw)Qi5mGwE6KNqwC9mpl$-5F{99LaGFiDU1pK}E%IR2j2`A*>^_ z+X18FzEp{`00zP4L}ja>FZ>@8%>GO1`@DG8N+kNfWZ7dk16Ys+&N69Hh`CDwd_42f ze4))Fy<84t!_AC^OGBpa^KTSWTT*VRw6nHWYM)1TJVRM1VI-^YBvJy)M?q3Ol2lo= zfA)PF99-o8Ik+Uk5H4-u36P|eY~$lGJ>Dt|-H0uce$CS1f>m$`8H~RSGa^sw#hr1d<^3A4!m>H+cL#+cy$YrJuxc#ua>R z9h)p&Kzn^{?VECt!%t4f!jcu4`M1hPB+XSKmbeFv<9If&~#!RPFAO~p?@ zZu@x$UDp}?0AGAdS(?BN&pa@2Q~vu()lPzBI9hf=jBbXaLc4+s@_h{a037jTu)tsT z1aG&n4~jdYr}h1JR|*`Xt71zgK{ z-e7iAV4;Nm#DuHu*|ul;WNvr?V9vxJ{}Jns zO6+%oxarooOq{QEvfg*xt2kt50U~R`h{RE>H60k8W0{CCLDHKC?UCgB2pee|9_)I zr);Jzw<-hN`eMV$@zmE1XxUDCMP5Jsz;4}7khUJMA-hXFKkxROeQdIsWgW4#geC@Q z_L#y^+cK2wLxS3Wb;IPKXGBf`N;3+wAjY^^F)=8!v%2 z(4IqW3+~PM`^;b1GyP;syqEM{J)y==qqhqWeE^r$wTVnk^;Vn6F?8$GigQ6ioG>Ym zSK}OD^N{~+QL5oj(g-4CL13Y{iA9RC@oCk44gq!o1c>q%HmSJ4`12~ycCulT9E~rt zdBa4b<)TkC%Os4H>uqL?9`?2Y3Y=HzKLqB;>;F!4N$ry$WlM~j0tJLmz7U?6*QuE7 zI(0Z(;_`hGgrrQwguZKwkVgJ;Vq_EqN2xgc_v<@FiONI7Ci2SDxowMKJX(QE=*z#~ zilFH->tt9tsgLpIpI5E-(TE;?k}U#5&BY)CC z6!q^IBYV_~<4>_K&Y7Uo%Mdo<5vOw4!gLz(LyfnZp|i9NL@As7boOzkhT<2A@5(~0 z$h2mFaqOma!FbA7PTwTBF>>l>`jkm>|7$%j3s*2Hb26L=P<8du71eLW@;mk}W`qjE?gOwdE-^myX{72C z;2Y@-dsjY3c=DJ@r=d7Vsq(P@DpsP$?C_gg!|c+|tH7U&^tlLFaL;=2gfyG$LMTq! z^k?sre8YT^1wX*ETbE@!Wk*n2znVlECi0JABE`?T_QO+7m0kyP$1T5cYwcjCQnKIM zx>2oZ*D5b9^x-`5t_ITfP`KQkAxa(av1vpX-cyxJw z@`pxzc*Hs$f+Bd9O&xgmDxr7fEoJo8O|sc)yf#h%b4KZ5fF7o`gp!G6c%hx;bZ12| zGGA#Ies6^>fhbWlA87a%-mOj06?yhko4%Jcz88zXGLLq;rrgRyC?1J&rJh4dL0j14 zvy}!>IA6$a?RrDlGA9z(*$f&y(~>ej*QjHIHR32 zuhy`(c&>P$5VXH9cm40Pf_=hc2Xwoj}!`}Rjg zc|i6con=wD>-iD|8c3S(wTkEq^YP*itL(orH{UxT^vb$wj$-%~>WwbNR?9Uf8F&*n zxMoe-5@~D+aVNjLyadYUIDM3h2_WdE%6LUurEL;|n9{AM4PW$dCTjR-ppU^lTvuNH#VxM1?6 zd>?2;wW+QE=&z&DL}Ni8r=#zk-C`rs((mr>K2Q~eWa`lp5as0;6B^QY_}#*iC3P$ilAj0}AYy`IEPC^V~W?X@=*xTuC>ZebDh`n09$E1MLo&U{Z#PkvDm&(idF zLzahVXa{%Gjc4l(o7{WLP_NxJa<2N9O@sC&n2OfQx&!i$HV2TXG5iZ+AAA%hOv$MZO_We{)^oku9hYrR+FE{;p)oV(3;&kXU*Ge3O++3Z}VWJ$&;bzv>s-U5vJ+*)2%Z;^ zBX@}*OMzOYalKZs2`0*YtWR&)*<7z0Vmoobz#&`PTw*AJ?NQl@tS0E_IJn_yX+*KT zMxZde)x=GPrrqb7`n>*?6NlG$kf1W9u`!Q8`I|H%#s1M(99Qnrhw3XNHVPY_1 z_};!YPY~?#LRlXp8q+v)2`7sE8<^F*F!3#mL0O+Zx*ltLdp) z8>qU523FAP8OAQwLcNxb8Y@sf-Un}+ZdvXrTt2f1sHe=ceG6)fsHtcS-1*RgJrIHQ9(H>8&N zGTj&Xg00g#{cA^|SGo$DchfQ>CLiYaOz`pEpN-feWPJqzge{{7HPMTRr)FwYfe$s8 zy0^BnhrGE4dWAA%-@vU4>UgeQRzx9*UaHCWZolj=>kneHRX;koOzls>8bXq>8abMd z5`PxzeUg{0Om8Z{C{QHp?0Dz1J6agu@C(PmRzO7kpxJr0!Zw%G;Gs4{uYSu4A(-^! z*GCBPh6QZ31?;1r=UHq~JSn=~&hf+ZB9dt-1X#$yK_C!8tHYd21lblNnxU`xEkUP2 zsCio#RyXl&7aI~+PB-<#n8z~P*+OMbhR2}lu&GIZhK1KptDyBT3J0fCOJggf7k1{P zkZO7f8Qy~r(?(!K2!!&TLH0l!viS|aM4PdVj&wR+Dr=**Ngt?mLx}5?D}H&#@ucCh zspM(JwrBUC*Im7efQMTPVkd)I+;KeW)JY;nnAZpuBm@ge3meY2Fsf%dc=eLX-BDle z;(f{z&met~59Ycr@!i?2-qWX{L)`P`$ym6K6{_X?+wjsawqRUZMBno zN+t+fDMUe3Mn^fr?}&;MO>)fTi|77GowQk~sfLTTjmz4}jE0yNi;ZVI{`Xjdo1=!N z%L`)k`%wPgA<=%D@w?mBhyDonppYSy^K`U>4-cPFfh1QZhnn@BsyQ`_0k)p|0)CNB80NQ9tUgMmPDUJXY0@^&OY@z z525V)c-H@@$<9W(Y+E|~qIxp3=cKEZZ`QRAc=@<)Xk0*yAv+OSXsncr6gy9_?B)5)+&=(#ycA-p7k;}ew zcI@NyuIZ)WR}i43O8fNuu57VXK@vDF){j&|?V z0fM;xDC^5g+=dMy5ifXKVt|l>uk^x+ra%$j&OBE5V^=pP7xk9ep`zC{#V-9H%|vBh zdAOspuuKhW444gPZuZ4h*VE-?TK&SIQLx7hKR@Xw=8`(fW8Hk}%kk(h0fR^5`5Q99PZ<$-_+*SK3XQjQR3(OU$_^t;Vkk(SNkkapQ3M77{?HSWmN|}E z=?veTP!HA$Le?b~xK^}(G+&JAIW$6z%C=<7ZHSm(2{w=3!J()yy6}wi$P?7fuhDoo;2DJn ze-wZc+2kaLE6>1>2LsC+J**mz;u^2J-_CnfI>dGYce z;UagrF?|t}ml>7iukc8{Z~7=I!OHTTDNr`wVqcXZbAO1eVp1EaLEuV#$&jhRm{xFl zna*<`p_RH0@efOx8)6Wk2$EUd148tMs;k=mfMB-LIo$aevr5lJ0pF*K4aBei)rCPLlGw0^=<}};g zp+>w$u6101Waz?S>tygKZ!2c(<8%&u>&Jg<&x+y1^nF>y(V*HrVlSkis-w*-dQp*8 z+ju0tYBd^o!(C31+3-kZ9AN=W6Gma*LcOzWax_{T^nA}yg1&dUL75hF8+^NLc4-cf?)x8wgCc{dOV0=^*`40cT|~Q z*b#K_`xFZnfc$S#zhFDmUJ?QrGz9H`e%YuHMc%cipr!C*#T)_|egEgR3vQjvv?s?% z>633IL(9{9vEU$u_y0W8del=8vR%Qjp$ox7uG4%BNmu_nBi^!vx82T{Ccgcz4T43l z8CC8<^0EI=8q!Zk5mk|TJDq4MDa9-T7T6i^?@b+mA{)eTNuiyXYnZN(R-C^C<}I5@ zCE&f!j~`md+(WYu@hvC$BU`T8cI!0zlJD<9I1&G6cuIL;>31ggs3E%B=RKD1Ii>GZ zBD)Rc+jMPbdTHW&qp}f@(7yv$rJ!UA*FcdTyV~c@8)i1@ms3yIs8I<|)G!!?R7@7b zOw4-CxMfaDDq&y|0(-9Cry2WGN3gaIZLDEPVnmA1*^MyHMMovJhmUplDE9L%3yaTQ_Tt_8a# zhIR79h8Rwnq_+aGec+&3dlN&EPEDGDx%0Zk`4R#l(ieOEN>TBPwng8-&b=E|DzfD! z)|uAJ{Y&md&<2ER)29C=8^M-A-8&~aw7sJ4Z_X?Pe3!QT&@$SZXz{DT*M!p`-v~EL zh?K(MQpP8|>wTJzPgk^&no>EM)XTAM+tG?W9yP=}^(MA$W^;>EM^be+Q{r9EXJ3qwqo&68?#0 z-!7p&+Q5Tx@O}b(cv;x|eDh)hwGh~P*kNz_@b68+GVl5W49tU>;V~gEod1fJ3_j<5 ze&V2>gDXr7*8l#Y-~R9o*F~mf7d3tmsGi;m)0%%(M5Q<%jaZab2+LqX<}0WW9J&!~ znd7iGLtK^XImpDoVV}h;;sX>N?!RZY=c)({3`1f<)v~RXJxyj@K+C?wQzHBQ_QyJ@aIiPTt&{E4w^R2U6rAaHosQEHm3r+vmP)mbfF*&|k%9g#(RyQr-1p|{=YU2#{ zjfN0GtiKP|F*ar?Oz-KG9It8x|1g!yr(hIg35z6?sF}}uZBRM2$zW8oH@d4+tmG)& znA9)OzS08+(e5ID3tJLoeCMJ=-DrL;&(>mD_ngKcyMlqN`}9o48?!i^hC5Gdk}!4Z zX5Z&~jOAG{B1G~2-)$}mM!Foi>M@?2{PJ~2%I}P);}$tQB(kUZwtd`pUj7A9G}c4v zMz69cn=d;e-4I_|p+9V7t7JYb9jl;rf9WL32yJdJ1|2b-n+=|AVatbiLN!mGwrB(j ztR{Onh|)hjUMMf4E?q$H<9g191g5cQJBYPNa?q4Wpfpk3pn^TPT(Ph zsL{`V@08{WDw5#^J#H7SbBh4B-0_Io)JUYl;zABTl87%}SEOg$b>x6yJSrrg1$JzK zuR2L1;~uzKnWXE+TsxtIg2XeTd?-e*`N|*I_MdejABv)w4Z8g~o+7 z_cGT9oBX67!bG;>>_j^Nh!2@NRNHdh^HHPjwK&0)%Es0-Wt66+c0T+*P$_`g;IZ~NiZh;uiWxrSp6%9Y2ljm68&?q`ikrluoK zDk-Ijs3!GVr2i`+U%DzV)8;bMCM&BzUBfnA*#qjp&p_M!W6OT=RgAv(BbX~yE9o@-DfQKLK`2 zl04jc9D|1Av{h|44y&tL>f{7+a-{yF(uHSK93C?Dc>O;7d@R z#Rg-}`WH-R+9j}zL%c3l;+5#JoxqQ+0DNm%dTgNLK~Dqqa(#dP{dX8|qtd)i)#B-X zbKl#ccama_?h-xmq2flO2QL7hElfxyLLA!z(4w*_B;rEO&sXAg7{%OgPR6N9C}D4G zwG|n%sX5*_y0a;=z8*|=w{wy9h@!CCqgfx*u^w%)=1kAD3Tq&MKoBJp%ld1qXKBUE zZEOUVj)XD>3}X;rW4H!NwvB1sm1|hk9-F(!$ki~@#)J}xR)h{FNi|(6m?*bQ&J>j~ za>?zS{6N8ga5jL;wsQ{se4?J$2VKPR+| z_j!}dyTqeNrGmcWt9MfoUm+pi{gTuKq_Wizl^ za7vG5zWF5LWes+##&VKn$$($yZuB02s0`JV-<-T10=N~eI_x+Gwg^DW>Hvfm(`&>P z)(*p$ngArGRr-xbJm<+?sta{|Z_nCM+MOo@CJKx3b>3;LcnF;=bQ2 z{%mxX&hI!1gYG5l2t0ko(V%i}1v$;5gdt*!cCh3NPyU){5`wOR;C>ZgzsZHh8Fg0_ z2j87`=to+u6ZWjIY#BW0vIFbIdT_53(^?YCk}A+3^`Xghjpg*|HFv?W7vDfH{JU1U zv%#LQ!4|6?bDN4{1$AMR%c~YeJ4=&&u2(JW=SIC^40=t2iQ{{7KP@h}_^Uf|=S(7u z)V8nC<>;~L_=(Ec5umKv^Jl5_+qEIZc<#r75cTdF&8N_~P8d9g-kVDAx)SD6iWo_%@? zHW_Tcxs}xlnj1hiH#auqG&GW7hPaDMt$n@bn`!luZbKH9&X7xr4#g^yej@*Ny*VCX z0K6BKmk%Bxq1rT^D8Jz$L1@v*fj&-@6ah-e+|sfb7_El$&0e0T=%DXhOrP=S%uKN@ z=e9FfTAMSArj8CYxPx@d@FP$n;5(PnCS3E!ihWe4Pb3UDrpC3mzUTAU6fok+ z8)zBs-@Y$5QgiEmyO{1Xk%G2^CQ^`@Q!7uBYPa;g%d8rhz};&{1*N4wVKz6kpAIiH z%>4&H766qCa&r7F7t`(Qi!EOkx$>5((yxL^$e~>^)L2Q#8+E;XsuVJfsN5;L$E(zi zlQmkTvh@y$D1sbNSF$&r$)p_#Cc4jdBr#)XxC=4Rh-2i5Sf)K%1+L2jKI+USRyb2~ zuHZs!4cQ<2s>kI}rMWJB>}T#=2PG&+lh`fTd~Q8UH0$L-arJ0LlHXc@?V^IL3+Mh# zyJ+&u*Vo(*?y5Nza>AD9--)69Q3fIQ6rvCaftb|2bb|xXIME!`vE&8?1D(1EU2HSF zVI%B+TvZh$X_2`&+<(EkP>G3gwQ`T}&DVCBWrmngA#bSq<`=IWZiw$yt|ZF&dRDl2 zlr?A|1@J-Gvk?Glq9Hmda`|4oCpsKWLql}1#m8EojSE@$p8M^A>~u}F-Li-nxD#`G zK*sN~_|?DRWK4r9iyrp0Z#M2h1on@D@zS*S+zM~{J_d%JUmKPd12C|_N-mW(Imj0R z5q(J!Aar_if;LxUb(Mbydkzx4m5XY!9#fOgtw2Fhks}99g$qd&aD z(r0Xl>^mA}_^O zR(iRs84AOjTeRYTSUCPZrW2n0wLz}1`)!mR=+ixXYE?8E?5CiNG|^1G%p&EVvj73} zWWvFu@+`U&8LVMu&J%F5!M^%cU(~)5s4LfQnI0;Ncgd|Tsg%j7D2dMH*qGruX>inz zUV3~t`0O5}_0``eWRNcy7}Dm8JC2e^N3rAz6o-n{DrXo`A+kAj>TJIUh4?1D`D5Ne zAnC?`y=;IxuGhHo zw*cb;2N8r*3Qci=au=tJ2H_SghP=4!VKX4&u%OLEO^G6HjwT~j%lzJ7xz3Q4WsFzI zkhKL~Bsf`s`?$Hi?bsMYmXyD9UQ#<(n15zmIoZ~ae@ut{326H^-2s@uCQ8!cJOtiu zFYG_beT9vU$(D=HL91>_%Ghp0*S&`@aqUb9j(-K=ekYU>@g(R2I1B3H^+F<-In(CP zDU-nu40_7pR_CGN;bpK`=KXhX9R$ABSOG;o*8Qk6p-_!Dc01-iJRCq3b|%WRGVvw? z(APN8b!Z>9dG~$?p0oiEmnQp8t>WQIMgN)tHRe#MRwHd;n;n5z;W}s0nBwqDHZ>4h zHBtl4HfI=r3ec9IPYDlhruwM{EYhM=r(sO0uPB)i7KYw**h8oO#g&=N`bFWmj*k`+ zI>7)%yylWK&Hm^4n_U;!5w2#Ey5dZeFE7J)5(D}{K1{Xmp|OsK4+lDU@Tgy)%pdic zGOsyqwFPL5Eaogui^@qS{RD!)Yuu;Kql7Bj*%2$_Df5TRe5FG-n|n@gz{x8lsTpAYmY z(5kMyyRcP(V4dLebeM7lQv?hH&;-CRu=M~Y5YLe}H#L=g{>ZkGz*UhSssg@$hZNJr zjVje9Yf1tF5Njpg1p>yR!FgD*_eqW`EDHcH-~gw?dDx(ZPWjhUg$YLoaK!(7{hzEy zxpfDApe!#>G@S1=!TauN9@rNab6?!RE|oJjpX*NM4_ud3%;iFrB8sD6&)NZfAZ|{GH5j@R+{uXH}WdNT|N%Ox_OY5L6sqYOiqA$ z`B+3);61roC(g3-V})7J>HRo|$xDpvhGw-NS_ZRE-a*vZ(aWtgi0{t3fVp)HdJPOL zkcdrH7<~eYy5_Nf1o;N&NjVO-n5v#u@#+853%)|&W#fS@FbgIl->5Zp* z5=0&OcAfa{fEcF68PqCXLvOZCW*M;g1wK_an$xj@-PC zvxt?-RYyWO=JInS;%V_h!Jhs0B+eHDDZ~UWx@AD$tY7xk`=pnTJA=JH{9S9v{hJ4( z!UA7qQ#ckXoVLbjV#PPEkNU@TZbo%z@Irek=&NgLHp6&!fkoqfxsey!XAGOj)mUwF z4i=rV=}J$mUmqdP{$Vdukt+Qr_%V*gF$0*0vbO^BQ%9A42a4AM0&xU6-_>>{qY6q{ zCb3@ex+o`}`xDwXGGA2(!fn}($sWFeY*y&pY^p?M0|F4As**n$eDh3;T+AIL4^UP! zLPm}LUt9#mXP1wCgM?&+a@NHll<+qXgzW|~pWzySCJ@GALo@XbqMkn!P0|Y1pg!6_ z6Arz-uBSc~tPz+c_Awa& z8Xt0OI@O;^Up@{Xg*eG^r^bpu|D`Ds7%i#iy zVhx~aJY^PvA}*l#C+`oD1JSa`?oT@XVE+t%feDxY2}n9Q;emc*xvFFoP?S_Tl#uEU zJAxARYLI|wDGL}Cn?e1Tv)KM~u*z;h7`>t)1UAQ61woLJH=Q_QH}lp+QqNnVD6Qp_ z&0dYW%~#etGxZ8oDYoxnZAgHXT-*B|X)ql25P1j|A9Cx#Yk{PObsWauk@x22W;rP9 zi%LBUi>>UDd+C=HPmn=-884XoxpH*jc+|(S1?-o&{;n@BIJh?tS`UO|zLsZF!Eq9; zi#~@q4Yn5G`wPA5(6{@By0;5XpC~qypDAJ`Xo4rqou)89cHtcoxflqg4=t9D;8&pAO%4DyXBknI-h0D__)S#60)U4@PMjt|3r!j^_v1lP3=ew1%NJ`< z6;6V&ZYn76WDZIgO9WAWuPk6!F1mh~&LLTRdqLuaygw z;r#7stvhf6m0;lY;9Qf($qJK?TGVlYjF-9OGdQFdPG|(rXPl?4G`kR&g#_SV$gPXz zV*)b2PAAr*?tLg(i8O9GRV7wC?|t<#oI$frwszJznZ7saSK)#aaJXa1`9PbJ;Mb&# zDhM1viCUC3DGv>rNNUyDW>`0!jCE6^Dt+|+Z~z<4{Rt%sA95Fv-HdfnSE^FDO}IR$ zcLR~<{wvrZ?u-77t~l0AJmI_5Gdf^JP-tel0bb- z4v9@CUQES-`yE$-88mi}e`5qdEwg|6gJ=SGzwd7h6+}`h|Hg?RkP-SnXwUzTKB}Y# zuy){<-Fd*^5*X-iV337PubK|)mFd1yJsx&>*_X_*;af0r3S;nPd-4kmw!m-@%8y1N%+}9f zhcZF;c=IW{*HQ93?~;Rc-6A4Pc=_k|_s&C^FHdV*N?LBFTL=%Ffb-zKo)PFcs-z+o z71f=MhldxyXRF~{njg4)+w&kV-oK9cLZ^gmr3FN) zHr{gU1Y{H(t?~ugR?{^bxyja1ht#v9tsCm9Y1x^&baC`&D(@B%9aG&ce7`b$=m!A2B?@ZUq zfXt&9a<8+-`BBiNw4+_S#h?p4)p1D7@6KoK!2n%polrmTQ3!yvN2r>JaL<$5yyt_pfB(CI2FyR@`a zFZ^adP#|W+C-_q5?nEd2{PL*`ubj^1P`rreHt?ZGK*LiqvCD&SA5YbD8Zi(unZLU| zqY(2r-5v};!w);P06VGsxo2zQzb%X7a z0&Ne82y(b$Kmt;YRWdoDlYJ)F|JB^}KP7p`@w;xbt8Lx2)j78&JEhxpt>n_JrbF+# zW-&`U(`IKv&6&2H^9ve;17=>)otAe`H)$=x0&^1iP9LaXA0oWmI zI8j#u(k_MJYPc$G9SOjhGf+I5z)MQQZZVqEmXo}&e4NIe2%pt2P|ocvXuCqRW0Z7$hlZ^h#aJ}Ec>57LUd%AT!c_Vc!&1c)rZkvzRi zL1=s;^1OF%Ir+|-`14Z4Xg1eO@SBQGK@*Fd&pMfe2m@ka%rgE$!cT_~%#e|AQT-WQ zf%_uadckw5w+B7Bc%^t zdA3&ERiclhFW-Nq&g4D-&~Xi{t+uy_FTK{uJUv+iJfxV)f3l4gqb4AI*lM*_ZrNu# z#vYjvd;mrtSiiaz;~;$sX70S1C2(Jc<3)rDqjE|X%7hH@um>c?fPiHnr=3&u1zxiN zWr5P$*(ngH2T(hpegSp{0n+usV-19ZB+k+?`pQ#TJRX9%GZyX^BXUtJZ@(1BTGeIK zsWEUyL?*I;PRQg~DnwL!aa!C#WkH(*o#QCs4FvbnW2vlvzidhY+mVj| zfwcKzx+r{YIyARS<7n?lf8&(H6Ts>yVCWBkm#;bGxzaD5@y>#dz9mhDj_$L}%%+1{ zyYh%4?*=p&F@@N}+k#wB3601Py)7q*9$S4vtjBGFls;G=4V^|i**O1tJ+XW!q!Z%o z{*YS>@Jt3NhANQWwqKTpMUl3N;XtFF0`xkR`8`8- zN*UR}s6)BYN|YRJIUjrGM#dnPI8WY%JM7-DI<4~FB2*|wLrX@Z{~8AkT6s%%=Lx!x zkxRH@H@Ps)b6yNyuhE{%Tj+Z5qae&{$$m#tesA51CoRG*5Qe>)g>LPvr=oHbB<}71 lN!

-

brokenstick 2.5.0

+

brokenstick 2.5.0

CRAN release: 2023-03-22

  • Updates the manual vignette to conform to the accepted JSS manuscript (March 2023)
  • Updates the documentation for CRAN release
  • Adds the doi:10.18637/jss.v106.i07 for the forthcoming JSS paper to DESCRIPTION and documentation
  • diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index a7ff5e3..2bca6bc 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -7,7 +7,7 @@ articles: manual: manual/manual.html oldfriends: oldfriends.html perfectmodel: perfectmodel.html -last_built: 2023-03-22T19:48Z +last_built: 2023-03-23T08:31Z urls: reference: https://growthcharts.org/brokenstick/reference article: https://growthcharts.org/brokenstick/articles diff --git a/docs/search.json b/docs/search.json index ffe2576..3df4570 100644 --- a/docs/search.json +++ b/docs/search.json @@ -1 +1 @@ -[{"path":"https://growthcharts.org/brokenstick/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2023 brokenstick Stef van Buuren Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"what-is-the-broken-stick-model","dir":"Articles","previous_headings":"","what":"What is the broken stick model?","title":"Getting started","text":"broken stick model describes set individual curves linear mixed model using second-order linear B-splines. model can used smooth growth curves series connected straight lines; align irregularly observed curves common age grid; create synthetic curves user-specified set break ages; estimate time--time correlation matrix; predict future observations. user specifies set break ages straight lines connect. individual obtains estimate break age, set estimates individual form smoothed version observed trajectory.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"what-are-the-main-model-assumptions","dir":"Articles","previous_headings":"","what":"What are the main model assumptions?","title":"Getting started","text":"main assumptions broken stick model : development break ages follows straight line; Broken stick estimates follow common multivariate normal distribution; order conform assumption multivariate normality, user may fit broken stick model suitably transformed data yield standard normal (\\(Z\\)) scale.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"why-should-i-want-to-use-the-broken-stick-model","dir":"Articles","previous_headings":"","what":"Why should I want to use the broken stick model?","title":"Getting started","text":"Three unique features broken stick model : Modular: Issues related nonlinearities growth curves observed scale can treated separately, .e., outside broken stick model; Local: given data point contribute estimates corresponding closest break ages; Exportable: broken stick model can exported reused prediction new data alternative computing environments.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"what-is-in-the-package","dir":"Articles","previous_headings":"","what":"What is in the package?","title":"Getting started","text":"brokenstick package contains functions fit, predict plot data. See reference page overview.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"acknowledgment","dir":"Articles","previous_headings":"What is in the package?","what":"Acknowledgment","title":"Getting started","text":"work supported Bill & Melinda Gates Foundation. contents sole responsibility authors may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"objective","dir":"Articles","previous_headings":"","what":"Objective","title":"Overview of main functions","text":"vignette demonstrates three major functions brokenstick package: brokenstick(), predict() plot(). also need dplyr ggplot2. elaborate documentation, see manual.","code":"require(\"brokenstick\") require(\"dplyr\") require(\"ggplot2\")"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"plot-trajectories","dir":"Articles","previous_headings":"","what":"Plot trajectories","title":"Overview of main functions","text":"smocc_200 data brokenstick package contain heights 200 Dutch children measured 10 visits ages 0-2 years. Figure 1 dispays data first 500 rows set growth curves Dutch children. Curves steeper first months, child growth faster young infants. Note also cross-overs first half year, whereas fewer occur later. means relative positions settled age 2 years, - put differently - correlation time points ages high. Figure 2 dispays data, vertical axis changed Standard Deviation Scores (SDS), \\(Z\\)-score. \\(Z\\)-score height corrected age relative Dutch height reference Fourth Dutch Growth Study. \\(Z\\)-score transformation takes away major time trend, curves less flat. allows us see detailed assessment individual growth. plots also show measurements clustered around ten ages: birth, 1, 2, 3, 6, 9, 12, 15, 18 24 months. design followed rigorously study, variation timing inevitable weekends, holidays, sickness, events. timing variation poses problem directly compare measurement different children (especially figure 1). Also, easily construct “broad” matrix 10 time point per child. course, can divide time axis ten age groups, treat point within age group measured point. probably good strategy nicely looking data - -, approach problematic data irregular time intervals, multiple measurement per age group, measurement schedules vary child, data combined studies employed different designs. brokenstick package contains tools approximate observed data series connecting straight lines. lines closely follow data, may replace trajectory values breakpoints. statistical analysis can done regularised trajectories, easier working observed data.","code":"data <- brokenstick::smocc_200 head(data, 3) ## # A tibble: 3 × 7 ## id age sex ga bw hgt hgt_z ## ## 1 10001 0 female 40 3960 52 0.575 ## 2 10001 0.0821 female 40 3960 55.6 0.888 ## 3 10001 0.159 female 40 3960 58.2 0.797 ggplot(data[1:500, ], aes(x = age, y = hgt_z, group = id, color = as.factor(id))) + geom_line(size = 0.1) + geom_point(size = 0.7) + scale_colour_viridis_d(option = \"cividis\") + xlab(\"Age (years)\") + ylab(\"Length SDS\") + theme_light() + theme(legend.position = \"none\")"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"fit-broken-stick-model-with-one-line","dir":"Articles","previous_headings":"","what":"Fit broken stick model with one line","title":"Overview of main functions","text":"fit trivial broken stick model just one line ages birth two years, plot trajectories three selected children follows: following plot displays data, standardised units increase analytic resolution: Note approximations describe individual trend data, address systematic deviations trend.","code":"set.seed(123) fit <- brokenstick(hgt ~ age | id, data, knots = c(0, 2)) ids <- c(10001, 10005, 10022) plot(fit, group = ids, xlab = \"Age (years)\", ylab = \"Length (cm)\") fit0 <- brokenstick(hgt_z ~ age | id, data, knots = c(0, 2)) plot(fit0, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\")"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"fit-broken-stick-model-with-two-lines","dir":"Articles","previous_headings":"","what":"Fit broken stick model with two lines","title":"Overview of main functions","text":"broken stick model describes trajectory series connected straight lines. first calculate model two connected lines. first line starts birth end age exactly 1 years. second line spans period 1 2 years. addition, lines must connect age 1 year. estimate plot model follows: plot shows two-line model still fairly crude. fit2 object holds parameter estimates model: console output lists knots model, including left right boundary knots 0 2.6776. row means correspond fixed effect estimates linear mixed model. may interpret global means. Next, output lists variance-covariance matrix random effects. model contains 16 parameters total: four fixed effects (means), four random effects (diagonal elements), 6 covariance (-diagonal elements) 2 error variances (one residual error variance, one variability error per cluster). parameters enough reconstruct broken stick model, apply new data.","code":"fit2 <- brokenstick(hgt_z ~ age | id, data = data, knots = c(0, 1, 2)) plot(fit2, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\") summary(fit2) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 16 (total), 4 (fixed), 4 (variance), 6 (covariance), 2 (error) ## Knots 0 1 2 ## Means -0.0394 0.0278 0.0646 ## Residuals 0.113 0.146 0.168 0.195 0.383 (min, P25, P50, P75, max) ## Mean resid 0.179 ## R-squared 0.867 ## ## Variance-covariance matrix ## age_0 age_1 age_2 ## age_0 1.218 ## age_1 0.481 0.823 ## age_2 0.485 0.782 0.884"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"extend-to-nine-lines","dir":"Articles","previous_headings":"","what":"Extend to nine lines","title":"Overview of main functions","text":"refine model first two years adding knot age visit scheduled. model can run optimization problem difficult, takes slightly longer run. results nine-line model summarises data 79 parameters. model fits substantially better. model residuals substantially smaller (0.075 instead 0.179) proportions explained variance much higher (0.983 instead 0.867). figure shows nine-line broken stick model fits observed data well.","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit9 <- brokenstick(hgt_z ~ age | id, data = data, knots = knots) summary(fit9) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 79 (total), 11 (fixed), 11 (variance), 55 (covariance), 2 (error) ## Knots 0.0000 0.0833 0.1667 0.2500 0.5000 0.7500 1.0000 1.2500 1.5000 2.0000 ## Means -0.18618 0.02163 0.00262 0.06602 0.06346 -0.01955 0.00781 0.03233 -0.02665 0.11470 ## Residuals 0.0176 0.0268 0.0329 0.0494 4.5190 (min, P25, P50, P75, max) ## Mean resid 0.0752 ## R-squared 0.983 ## ## Variance-covariance matrix ## age_0 age_0.0833 age_0.1667 age_0.25 age_0.5 age_0.75 age_1 age_1.25 ## age_0 1.740 ## age_0.0833 1.118 1.337 ## age_0.1667 1.077 1.095 1.246 ## age_0.25 0.900 1.005 0.999 1.052 ## age_0.5 0.627 0.821 0.822 0.815 0.943 ## age_0.75 0.597 0.696 0.693 0.718 0.867 0.938 ## age_1 0.495 0.611 0.579 0.606 0.786 0.819 0.869 ## age_1.25 0.432 0.614 0.575 0.601 0.757 0.807 0.834 0.953 ## age_1.5 0.455 0.614 0.624 0.604 0.808 0.824 0.836 0.914 ## age_2 0.361 0.483 0.517 0.539 0.720 0.753 0.783 0.883 ## age_1.5 age_2 ## age_0 ## age_0.0833 ## age_0.1667 ## age_0.25 ## age_0.5 ## age_0.75 ## age_1 ## age_1.25 ## age_1.5 1.039 ## age_2 0.919 1.06"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"obtain-predicted-values","dir":"Articles","previous_headings":"","what":"Obtain predicted values","title":"Overview of main functions","text":"predict() function allows us obtain various types predictions broken stick model. simplest call produces tibble one column called .pred row data. can bind column .pred data processing. Sometimes, also want prediction knot values, example, create graphs contain observed modelled trajectories. obtain predictions knots special x = \"knots\" argument, e.g. use include_data = FALSE argument remove predictions observed data. output verbose includes grid knots child (id, age). column .source equal added rows non-observed data. Note also knots ages 0.00 2.68 years. boundary knots, added brokenstick() function. boundary knots effectively filter observations enter calculations. default, boundary knots span age range data. technical reasons, broken stick model also defines estimates parameters knots, may general ignored, especially data near boundary knots sparse. wish obtain estimates knots observed data use: return 1942 rows data 800 rows knots.","code":"p1 <- predict(fit2) head(p1) ## .pred ## 1 0.720 ## 2 0.660 ## 3 0.604 ## 4 0.534 ## 5 0.352 ## 6 0.171 identical(nrow(data), nrow(p1)) ## [1] TRUE p2 <- predict(fit2, x = \"knots\", include_data = FALSE) head(p2) ## .source id age sex ga bw hgt hgt_z .pred ## 1 added 10001 0 NA NA NA NA 0.71989 ## 2 added 10001 1 NA NA NA NA -0.00939 ## 3 added 10001 2 NA NA NA NA 0.05785 ## 4 added 10002 0 NA NA NA NA -0.23264 ## 5 added 10002 1 NA NA NA NA -0.37772 ## 6 added 10002 2 NA NA NA NA -0.50233 nrow(p2) ## [1] 600 p3 <- predict(fit2, x = \"knots\", hide = \"none\") table(p3$.source) ## ## added data ## 800 1942"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"explained-variance","dir":"Articles","previous_headings":"","what":"Explained variance","title":"Overview of main functions","text":"proportion variance outcome explained two-line model second model get nine-line broken stick model explains 98 percent variance height SDS.","code":"get_r2(fit2) ## [1] 0.867 get_r2(fit9) ## [1] 0.983"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"subject-level-analysis","dir":"Articles","previous_headings":"","what":"Subject level analysis","title":"Overview of main functions","text":"Suppose interest knowing effect sex, gestational age birth weight height SDS age 2 years. analysis subject level. Let us first extract subject-level data variables vary subjects . also need outcome variable. take broken stick estimates nine line solution append subject level data. names columns bs correspond knot values. effect subject’s sex, gestational age birth weight height SDS age 2 years (denoted variable named 2) can estimated Note analysis shows substantial effect birth weight. course, might birth weight directly related height age 2 years. Alternatively, relation mediated birth length. following model adds birth length (variable named 0) model: effect birth length length age 2 strong. separate effect birth weight anymore, analysis suggests relation birth weight length age 2 can explained mutual associations birth length.","code":"subj <- data %>% select(id, sex, ga, bw) %>% group_by(id) %>% slice(1) head(subj, 3) ## # A tibble: 3 × 4 ## # Groups: id [3] ## id sex ga bw ## ## 1 10001 female 40 3960 ## 2 10002 male 38 3210 ## 3 10003 female 40 4170 bs <- predict(fit9, x = \"knots\", shape = \"wide\", include_data = FALSE) data <- bind_cols(subj, select(bs, -id)) head(data, 3) ## # A tibble: 3 × 14 ## # Groups: id [3] ## id sex ga bw `0` `0.0833` `0.1667` `0.25` `0.5` `0.75` `1` ## ## 1 10001 female 40 3960 0.569 0.865 0.735 0.657 0.232 -0.172 0.118 ## 2 10002 male 38 3210 -0.184 -0.329 -0.252 -0.319 -0.218 -0.281 -0.344 ## 3 10003 female 40 4170 1.17 2.11 1.97 2.04 2.03 1.81 1.32 ## # … with 3 more variables: `1.25` , `1.5` , `2` fit1_lm <- lm(`2` ~ sex + ga + I(bw / 1000), data = data) summary(fit1_lm) ## ## Call: ## lm(formula = `2` ~ sex + ga + I(bw/1000), data = data) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.8965 -0.4525 0.0817 0.6424 2.0369 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 1.0361 1.4705 0.70 0.48187 ## sexmale 0.0109 0.1285 0.08 0.93249 ## ga -0.0700 0.0433 -1.62 0.10752 ## I(bw/1000) 0.5343 0.1420 3.76 0.00022 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.879 on 196 degrees of freedom ## Multiple R-squared: 0.0757, Adjusted R-squared: 0.0616 ## F-statistic: 5.35 on 3 and 196 DF, p-value: 0.00145 fit2_lm <- lm(`2` ~ sex + ga + I(bw / 1000) + `0`, data = data) summary(fit2_lm) ## ## Call: ## lm(formula = `2` ~ sex + ga + I(bw/1000) + `0`, data = data) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.9375 -0.5326 0.0426 0.6292 1.8792 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 3.226719 1.662005 1.94 0.0536 . ## sexmale -0.000703 0.126542 -0.01 0.9956 ## ga -0.089472 0.043247 -2.07 0.0399 * ## I(bw/1000) 0.143924 0.201777 0.71 0.4765 ## `0` 0.245522 0.091492 2.68 0.0079 ** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.865 on 195 degrees of freedom ## Multiple R-squared: 0.109, Adjusted R-squared: 0.0904 ## F-statistic: 5.94 on 4 and 195 DF, p-value: 0.000156"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"conclusion","dir":"Articles","previous_headings":"","what":"Conclusion","title":"Overview of main functions","text":"vignette illustrated use brokenstick(), plot() predict() functions. vignettes highlight various capabilities package.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"abstract","dir":"Articles > Manual","previous_headings":"","what":"Abstract","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Many longitudinal studies collect data irregular observation times, often requiring application linear mixed models time-varying outcomes. paper presents alternative splits quantitative analysis two steps. first step converts irregularly observed data set repeated measures broken stick model. second step estimates parameters scientific interest repeated measurements subject level. broken stick model approximates subject’s trajectory series connected straight lines. breakpoints, specified user, divide time axis consecutive intervals common subjects. Specification model requires just three variables: time, measurement subject. model special case linear mixed model, time linear \\(B\\)-spline subject grouping factor. main assumptions : subjects exchangeable, trajectories consecutive breakpoints straight, random effects follow multivariate normal distribution, unobserved data missing random. R package brokenstick v2.4.0 offers tools calculate, predict, impute visualise broken stick estimates. package supports two optimisation methods, including options constrain variance-covariance matrix random effects. demonstrate six applications model: detection critical periods, estimation time--time correlations, profile analysis, curve interpolation, multiple imputation personalised prediction future outcomes curve matching.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"introduction","dir":"Articles > Manual","previous_headings":"","what":"Introduction","title":"Broken Stick Model for Irregular Longitudinal Data","text":"longitudinal studies plan data collection occur fixed set time points. practice, realized times can differ — sometimes substantially — scheduled times. may many reasons differences. example, planned visit weekend holiday, subject show , measurement device order, investigator fell ill. Varying observation times may also result combining data multiple studies, collected according design. Timing variation can substantial observational studies, especially survey lacks pre-specified schedule. Longitudinal data timing differences subjects said irregular. Irregular observation times present significant challenges quantitative analysis. example, easy calculate time--time correlation matrix data spread thinly time. might also complex predict future past data subject times differ. Observation times may also relate process interest. example, severely ill patients get measured frequently; unmotivated cohort members respond rarely, . Conventional methods like MANOVA, regression cluster analysis break observation times differ drop-selective. irregular observation times occur science, universal principled approach resolve problem. One straightforward fix take dates data available (e.g., dates stocks traded), thus ignoring times markets closed. One may also create bins time intervals around planned times, thereby ignoring within-period differences. Another ad-hoc method predicts value scheduled time neighboring data, e.g., linear interpolation smoothing, typically reducing variability data. quick fixes create data sets timing problem seems “gone away”, may tempt analyzingt ignore potential effects data patch-substantive conclusions. convenient straightforward, thoughtless application fixes introduces significant spurious relations time, especially spacing observations highly irregular (Rehfeld et al. 2011). Binning can lead “surprisingly large” biases (Towers 2014). timing variation related outcome interest, methods may result biased estimates exaggerated claims (Pullenayegum Lim 2016). linear mixed model longitudinal data (Laird Ware 1982; Fitzmaurice, Laird, Ware 2011) standard analyzing irregular data. model represents subject’s observed curve parametric function time. parameter estimates function specific subject modeled random effects. linear mixed model beneficial irregular data. borrows strength across different realizations process, summarizing trajectory small number parameters vary subjects. analyst can break distribution random effects function individual characteristics. linear mixed model attractive number measurements differs individuals measurements taken different times. paper explores use broken stick model transform irregularly observed data repeated measures. broken stick model describes curve series connected straight lines. model long history known many names, among others, segmented straight lines (Bellman Roth 1969), piece-wise regression (Toms Lesperance 2003), structural change models (Bai Perron 2003), broken line smoothing (Koutsoyiannis 2000) segmented regression (Lerman 1980). term broken stick goes back least MacArthur (1957), used analogy indicate abundance species. literature broken stick model concentrates problem finding optimal times lines connect. Instead, present paper focus problem summarizing irregular individual trajectories estimates made pre-specified time grid. time grid identical individuals, need equidistant. model formulation special case linear mixed model, time modeled set random effects coded linear \\(B\\)-spline subjects grouping factor. output transformation set repeated measures, every subject obtains score every time point. Many R packages offer tools interpolation. splines package ( Core Team 2020) akima package (Akima et al. 2021) contains classic interpolation methods one- two-dimensional smoothing. contributed packages concentrate time series spatial interpolation. See Li Heap (2014) Lepot, Aubin, Clemens (2017) overviews different concepts methodologies. interpolation techniques rely neighboring information, time, space . broken stick model addresses problem many independent replications provide short irregular multivariate time series, say 5-30 time points. scientific interest dynamically predict update future observations. model applies linear mixed model increase stability series borrowing information across replicates. satisfactory solutions problem, brokenstick package intends fill gap. Package brokenstick available Comprehensive R Archive Network https://CRAN.R-project.org/package=brokenstick. Substantive researchers often favor repeated measures use linear mixed models simplicity. example, can easily fit subject-level model predict future outcomes conditional earlier data repeated measures data. simple regression models may less efficient modelling complete data (Diggle et al. 2002, sec. 6.1), increased insight may valuable increased precision. broken stick model requires specification sensible set time points measurements ideally taken. subject, model predicts imputes hypothetical observations times, substantive analysis applies repeated measures instead irregular data. strategy akin Diggle’s multi-stage model-fitting approach (Diggle 1988). envisioned two-step analytic process aims provide best worlds. applications broken stick model : approximate individual trajectories series connected straight lines; align irregularly observed curves joint age grid; impute realizations individual trajectories; estimate time--time correlation matrix; predict future observations. original motivation developing broken stick model facilitate statistical analysis testing critical ages onset childhood obesity (de Kroon et al. 2010), extensions multiple imputation (van Buuren 2018b). good support R fitting child growth data. mention related approaches. Methods estimating growth references parametric models gamlss() gamlss (Stasinopoulos Rigby 2007) Bayesian incarnation bamlss() bamlss (Umlauf et al. 2021). Nonparametric alternatives estimate quantiles directly rq() quantreg (Koenker et al. 2018) expectreg.ls() expectreg (Otto-Sobotka et al. 2021). Methods modelling smoothing growth curves fit trajectories per child include smooth.basisPar() fda (Ramsay, Graves, Hooker 2021), gam() mgcv (Wood 2011), loess() smooth.spline() base stats ( Core Team 2020). Models smooth borrowing strength across children face.sparse() face (Xiao et al. 2021), lmer() lme4 (Bates et al. 2015), sitar() sitar (Cole 2022). broken stick model fits latter tradition, features intuitive parametrization individual growth curve series connected straight lines. See Anderson et al. (2019) overview comparison methods. present paper highlights various computational tools brokenstick v2.4.0 package. package contains tools fit broken stick model data, export fitted model’s parameters, create imputed values model, predict broken stick estimates new data. Also, text illustrates tool helps solve various analytic problems.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"illustration-of-broken-stick-model","dir":"Articles > Manual","previous_headings":"","what":"Illustration of broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"first step, let us study variation age measurement 200 children SMOCC study (Herngreen et al. 1994). Lokku et al. (2020) suggest abacus plot visualize variation. Figure 1: Abacus plot observation times first 20 children SMOCC data. Data collection done 10 waves. dot represents age observation made. variability timing children rises age. blue points Figure 1 indicate observation times. Generally, blue points close scheduled ages (indicated vertical lines), especially first half-year. Observation times vary older children. Several children one missing visits (e.g., 10002, 10008, 10024). children (10012, 10015) fairly close visits. Child 10028 dropped month 9. Let us fit two models, two nine lines, respectively, body length’s standard deviation score (SDS). Figure 2: Data fitted curves three children (blue = observed data, red = fitted curves). broken stick model two lines (top) gives crude approximation data. model nine lines (bottom) follows data quite closely. Knot values rounded simplify presentation. Figure 2 shows individual trajectories three children. blue points coincide observed data, whereas red curves calculated according broken stick model. two fitted models. simpler model (top) uses just two line segments. first line starts birth ends age exactly 1 year. second line spans period 1 2 years. Note two lines connect breakpoint, age 1 year. red curves two-line model crude approximation data. can create better model setting breakpoints equal scheduled ages. Since 10 scheduled ages, construct nine straight lines. contrast two-line model, nine-line broken stick model sensitive small bumps observed trajectory closely fits empirical data. residual variance nine-line model low (0.059), proportion explained variance SDS high (0.98). observation times data differ children, broken stick curves use identical time points across subjects. idea now can add broken stick estimates child-level data long--wide conversion analyze supplemented columns repeated measures. repeated measures analysis usually simpler equivalent temporally misaligned data. example, easy calculate mean profiles arbitrary groups, estimate time--time covariance matrix, build predictive models child level. See Hand Taylor (1987) lucid overview linear techniques repeated measures.","code":"fit2 <- brokenstick(hgt_z ~ age | id, smocc_200, seed = 1, knots = 0:2) fit9 <- brokenstick(hgt_z ~ age | id, smocc_200, seed = 1, knots = round(c(0:3, 6, 9, 12, 15, 18, 24)/12, 4))"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"notation","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Notation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"adopt notation Fitzmaurice, Laird, Ware (2011). Let \\(Y_{ij}\\) denote response variable \\(^{\\rm th}\\) subject \\(j^{\\rm th}\\) measurement occasion time \\(t_{ij}\\). Data collected sample \\(N\\) persons \\(=1,\\dots,N\\). Let repeated measurements \\(^{\\rm th}\\) subject grouped \\[ Y_i = \\left( \\begin{array} {l} Y_{i1} \\\\ Y_{i2} \\\\ \\vdots \\\\ Y_{in_i} \\end{array} \\right), \\quad = 1, \\dots, N. \\] measures observed common set occasions, drop index \\(\\) \\(t_{ij}\\) since \\(t_{ij} = t_j\\) \\(= 1, \\dots, N\\). focus case \\(t_{ij}\\) varies \\(\\). addition, let use define \\(n_i \\times p\\) matrices \\[ X_i = \\left( \\begin{array} {llll} X_{i11} & X_{i12} & \\cdots & X_{i1p} \\\\ X_{i21} & X_{i22} & \\cdots & X_{i2p} \\\\ \\vdots & \\vdots & \\ddots & \\vdots \\\\ X_{in_i1} & X_{in_i2} & \\cdots & X_{in_ip} \\end{array} \\right), \\quad = 1, \\dots, N, \\] rows \\(X_i\\) contain \\(p\\) covariates associated responses \\(n_i\\) measurement occasions. columns may time-varying covariates. certain covariate fixed time (e.g., sex, treatment, education), values within corresponding column \\(X_i\\) identical.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"broken-stick-model","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model avoids modeling observation times \\(t_{ij}\\) directly representing \\(t_{ij}\\) relative position within time interval. example, suppose \\(t_{ij} = 0.6\\) years time interval given 0.5-1.0 years. position relative left break age \\(x_{\\rm left} = (1.0-0.6)/(1.0-0.5) = 0.8\\), whereas relative right break age \\(x_{\\rm right} = (0.6-0.5)/(1.0-0.5) = 0.2\\). order fit broken stick model, need replace time point \\(t_{ij} = 0.6\\) two values: 0.8 (break age 0.5), 0.2 (break age 1.0). Note values add 1. Coding time way simplifies modeling continuous time set discrete break ages. specifically, let \\(t_{ij}\\) coded second-order (linear) \\(B\\)-spline using \\(k\\) internal knots \\(\\kappa\\) placed \\(k+1\\) ordered ages \\[ \\kappa_0 = \\kappa_1 < \\dots < \\kappa_k < \\kappa_{k+1} \\] internal knots \\(\\kappa_1, \\dots, \\kappa_k\\) correspond set ages obtain broken stick estimates, specified user. left boundary knot \\(\\kappa_0 = \\kappa_1\\) left-anchored minimum time \\(\\min(t_{ij})\\) data. point defines starting event participant, birth study enrollment. right hand boundary knot \\(\\kappa_{k+1} \\geq \\max(t_{ij})\\). second-order \\(B\\)-spline (de Boor 1978, 32), \\[ H_s(t) = \\left\\{ \\begin{array} {l@{\\quad,\\quad}l} (t-\\kappa_{s-1})/(\\kappa_s - \\kappa_{s-1}) & \\kappa_{s-1} < t \\leq \\kappa_s,\\\\ (\\kappa_{s+1}-t)/(\\kappa_{s+1} - \\kappa_s) & \\kappa_s \\leq t < \\kappa_{s+1},\\\\ 0 & {\\rm otherwise.} \\end{array} \\right. \\] applied \\(t_{ij}\\) obtain \\((k+1)\\) transformed variables \\(x_{} = t_{ij}\\) \\(s = 1,\\dots,k+1\\). variables can conveniently grouped \\(n_i \\times (k+1)\\) matrix covariates \\(X_i = (x_{i1}, \\dots, x_{ik}, x_{(k+1)})\\). row \\(X_i\\) one two non-zero elements, sum 1. Using \\(X_i\\), broken stick model special case (\\(Z_i = X_i\\)) two-stage random-effects model (Laird Ware 1982) \\[ Y_i = X_i\\beta + X_ib_i + \\epsilon_i \\] \\(k+1\\) column vector \\(\\beta\\) contains \\(k+1\\) fixed effect coefficients common persons, \\(k+1\\) column vector \\(b_i\\) accommodates \\(k+1\\) subject-specific random parameters, \\(n_i\\) column vector \\(\\epsilon_i\\) holds subject-specific residuals. order complete model specification, assume residuals identically independently distributed \\(\\epsilon_i \\sim N(0,\\sigma^2 (n_i))\\), \\(\\sigma^2\\) common variance parameter, \\((n_i)\\) identity matrix order \\(n_i\\). Thus, equation represents population parameters (fixed effects), individual effects (random effects), amount within-person dispersion persons. Section 4.2 also considers heterogeneous model allows \\(\\sigma_i^2\\) vary subjects. summary, given knot specification choice response scale, parameters broken stick model : \\(\\beta\\), vector \\(k + 1\\) fixed parameters; \\(\\Omega\\), \\((k+1) \\times (k+1)\\) covariance matrix random effects; \\(\\sigma^2\\), within-person error variance. total number parameters solution \\(k\\) internal knots thus equal \\((k^2 + 5k + 6)/2\\). example, model \\(k = 3\\) knots (.e., two connected lines) 15 parameters, model \\(k = 4\\) 21 parameters, model \\(k = 10\\) break ages 78 parameters. heterogeneous model one additional parameter measures variation \\(\\sigma_i^2\\).","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"model-assumptions","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Model assumptions","title":"Broken Stick Model for Irregular Longitudinal Data","text":"person level, assume \\(b_i \\sim N(0, \\Omega)\\), .e., random coefficients subjects multivariate normal distribution zero mean \\((k+1) \\times (k+1)\\) covariance matrix \\(\\Omega\\). base model allows elements \\(\\Omega\\) vary freely. time-dependent data, constrained versions \\(\\Omega\\) also interest (Fitzmaurice, Laird, Ware 2011, Ch. 7). Section 4.2 highlights two extensions. also assume covariance \\(b_i\\) \\(\\epsilon_i\\) zero. simplicity, paper restricted case \\(X_i\\) includes time, covariates. broken stick model builds upon three main modeling assumptions: trajectory break ages follows straight line. assumption may fail processes convex concave time. example, human height growth centimeters concave time, setting breakpoints far apart introduces systematic negative bias. Modeling height SDS instead raw height prevent bias. broken stick estimates follow joint multivariate normal distribution. assumption may fail skewed measurements, beneficial transform outcomes distribution closer normal. data missing random (MAR) given outcomes subjects observation times. assumption restrictive sense missingness may depend observed outcomes, covariates time. time, assumption liberal sense missingness may depend future outcomes. MAR-future assumption unusual literature drop-observation time models, sensible strategy creating imputations preserve relations time, especially intermittent missing data. course, subsequent substantive analysis imputed data needs aware causal direction time.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpretation","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Interpretation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Given model estimates person data, can calculate random effect \\(b_i\\). broken stick parameter \\(\\gamma_{} = \\beta_s + b_{}\\) subject-specific mean \\(Y_i\\) time \\(\\kappa_s\\), \\(s = 1,\\dots, k + 1\\). set \\(\\gamma_{}\\) parameters describes mean response profile subject \\(\\) \\(k\\) lines connect \\(k + 1\\) coordinates \\((\\kappa_s, \\gamma_{})\\). broken stick parameter likely value outcome \\(Y_i\\) subject \\(\\) time \\(\\kappa_s\\) given person’s observed data given fitted model (represents evolution trajectories training data). parameter center posterior predictive distribution normal \\(Y_i\\). two-sided \\(100(1-\\alpha)\\%\\) prediction interval true, though often unobserved, value \\(Y_{,\\kappa_s}\\) equal \\[ [Y_{,\\kappa_s}^{\\rm lo}, Y_{,\\kappa_s}^{\\rm hi}] = \\gamma_{} \\pm t_{(1-\\alpha/2;N-1)}\\sigma, \\] \\(t_{(1-\\alpha/2;N-1)}\\) \\(100(1-\\alpha/2)\\) percentile Student’s \\(t\\)-distribution \\(N - 1\\) degrees freedom. example, 50% prediction interval \\(\\gamma_{} \\pm 0.68\\sigma\\) contain 50% true values. normal \\(Y_i\\), length 50% prediction interval equivalent interquartile range (IQR). residual variation \\(\\sigma^2\\) small (say \\(\\sigma^2 < 0.1\\)), IQR 0.22, half true values within 0.22 SD \\(\\gamma_{}\\), small difference. large \\(\\sigma^2\\) (e.g., \\(\\sigma^2 > 0.2\\)), \\(\\gamma_{}\\) vector smoothed representation \\(Y_{}\\). smoothness amplifies low-frequency features trajectories, also introduce biases subsequent analysis suppressing high-frequency variation. case, analyst needs check whether reduction variation affect parameters substantive interest. may restore high-frequency variation adding random draws residual distribution \\(N(0, \\sigma^2)\\). , small step multiple imputation, well-developed methodology drawing valid inferences incomplete data (Rubin 1987; van Buuren 2018b). \\(n_i \\gg k\\) broken stick model provides parsimonious representation measurements. Reversely, \\(n_i \\ll k\\) model infers plausible values subject \\(\\) building strength across persons. broken stick model converts \\(n_i\\) irregularly observed measurements new set \\(k\\) values \\(\\gamma_{}\\) common ages \\(\\kappa_1, ..., \\kappa_k\\), \\(s = 1,\\dots, k\\). Since row \\(X_i\\) sums unity, broken stick model global intercept. linear \\(B\\)-spline coding effectively replaces global random intercept term \\(k + 1\\) local intercepts, one break age. local intercept summarizes information available adjacent left right age intervals ignores information beyond two adjacent knots. broken stick estimates thus primarily local. Outcome data observed outside two adjacent age intervals influence broken stick estimates subject-level part model, particular \\(\\Omega\\).","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"main-function","dir":"Articles > Manual","previous_headings":"4 Estimation","what":"Main function","title":"Broken Stick Model for Irregular Longitudinal Data","text":"brokenstick() function estimates parameters broken stick model. user needs specify outcome, predictor grouping variable, well location knots predictor variable. call produces object class \"brokenstick\": object contains model setting, data results. column names \\(X\\) consist name time variable knot values appended. Thus, age_0 birth length age_1 length age 1y. find estimates fixed effects \\(\\beta\\) means, residual variance \\(\\sigma^2\\) mean resid variance-covariance matrix random effects \\(\\Omega\\) get_omega(fit). calculate broken stick estimates knot locations wide matrix predict() function follows: specification x = \"knots\" uses special keyword \"knots\" set predictor values equal knot locations used fit model. argument shape = \"wide\" returns predicted values wide matrix (one row per group, one column per predictor value). result now individual trajectory summarized six estimates.","code":"fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = c( 0, 0.5, 1, 2), seed = 12321) summary(fit) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 22 (total), 5 (fixed), 5 (variance), 10 (covariance), 2 (error) ## Knots 0.0 0.5 1.0 2.0 ## Means -0.0939 0.0926 -0.0137 0.0842 ## Residuals 0.106 0.129 0.146 0.169 0.361 (min, P25, P50, P75, max) ## Mean resid 0.156 ## R-squared 0.893 ## ## Variance-covariance matrix ## age_0 age_0.5 age_1 age_2 ## age_0 1.409 ## age_0.5 0.718 0.905 ## age_1 0.521 0.755 0.765 ## age_2 0.395 0.721 0.783 0.941 bse <- predict(fit, x = \"knots\", shape = \"wide\") dim(bse) ## [1] 200 5 head(bse, 3) ## # A tibble: 3 × 5 ## id `0` `0.5` `1` `2` ## ## 1 10001 0.789 0.247 0.0256 0.0341 ## 2 10002 -0.267 -0.228 -0.421 -0.514 ## 3 10003 1.67 2.00 1.28 1.10"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"estimation-steps-explained","dir":"Articles > Manual","previous_headings":"4 Estimation","what":"Estimation steps explained","title":"Broken Stick Model for Irregular Longitudinal Data","text":"may break estimation process two main steps. first step calculates matrix \\(B\\)-splines time variable age core splines::bs() ( Core Team 2020) function: numerical example shows bs() function transforms age variable five columns, \\(B\\)-spline basis, names like age_0 age_0.5. age coincides one (e.g., top row), corresponding column receives 1. cases, age distributes two adjacent columns. Setting degree = 1 specifies \\(B\\)-spline gives broken stick model name characteristic shape. Although strictly needed, applications paper assume left boundary knot marks start time, e.g., birth day enrollment. subtleties using splines::bs() create linear \\(B\\)-spline basis. Matrix X values range \\([0, 1]\\) maximum two non-zero values per row sum \\(1\\). conditions require Boundary.knots span least range data. requirement easy achieve setting Boundary.knots = range(data$age), done default. Also, need ensure range knots outside Boundary.knots. may achieve setting Boundary.knots include least range(knots). practice, user need worry boundaries since brokenstick() function takes care conditions expanding boundary range needed. primary reason setting explicit boundaries make independent data. second step specify model estimate parameters. two methods : \"kr\" \"lmer\". Method \"lmer\" relies popular function lme4::lmer() (Bates et al. 2015) fit linear mixed normal model. formula removes intercept specifies knot random effect child id grouping factor. control argument suppresses warning Model failed converge max|grad| = 0.0360913. warnings occur often model many random effects. warnings may also thrown child data outliers (example pre-terms). found broken estimates generally look sound reasonable despite warnings. Note however experience derives primarily child growth data, guarantee apparent robustness hold types data. Warnings lmer() become frequent higher number knots, smaller samples data observations made irregular time points. Object mod_lmer class \"lmerMod\" may use standard plot(), predict() summary methods offered lme4 package. Converting result broken stick estimates requires summing fixed random effects. calculation time lme4::lmer() rapidly increases number random effects. ten random effects (knots) takes significant time, beyond 15 knots generally impossible fit. example, using dataset 33,000 records 2,600 individuals, M1 Max processor takes 8 seconds (5 knots), 107 seconds (9 knots), 403 seconds (12 knots) 1172 seconds (15 knots). brokenstick package provides another alternative, Kasim-Raudenbush (KR) sampler (Kasim Raudenbush 1998). method simulates draws posterior distributions parameters two-level normal model heterogeneous within-subject variances. speed Kasim-Raudenbush sampler almost insensitive number random effects depends primarily total number iterations somewhat sample size. Execution KR method problem takes 15 seconds (5 knots), 17 seconds (9 knots), 19 seconds (12 knots) 20 seconds (15 knots). method available function kr() brokenstick package default since version 2.0.0. control_kr() function tweaks estimation options: call control_kr() produces list settings sampler according conventions coda package (Plummer et al. 2006). defaults control_kr() reasonable across wide range cases. list component mod_kr$mod contains various objects class \"mcmc\" sampling history detailed results. example, inspect fixed effect estimates Also, may obtain trace plots densities. example try plot(mod_kr$mod$beta). obtain results method \"lmer\" argument shape = \"wide\" specifies form return value. broken stick estimates kr lmer methods similar, identical. fact, substantial discrepancies may occur areas data sparse, example, right boundary knot. Apart faster complex models, KR-sampler opens interesting analytic options: relatively easy constrain fitted covariance random effects, \\(\\Omega\\), matrix simple structure. Informing sampler time-dependent structure random effect leads stabler estimates \\(\\Omega\\). package currently implements two correlations models. models express correlation \\(\\rho(t_1, t_2)\\) two Z -scores \\(Z_1\\) \\(Z_2\\) successive ages \\(t_1\\) \\(t_2\\) function ages. Argyle model (Argyle, Seheult, Wooff 2008) \\(\\rho(t_1, t_2) = \\exp(-\\lambda|T_1-T_2|)\\), \\(T_i = \\log(\\tau+t_i)\\) logarithmic rescaling time axis \\(\\rho=exp(-\\lambda)\\). Cole correlation model (Cole 1995) describes Fisher-transformed correlation function average \\((t_1+t_2)/2\\) difference \\((t_2-t_1)\\), including two multiplicative terms. Note models proposed context child growth, may fit less well types time-dependent data. Kasim-Raudenbush sampler fits slightly general linear-mixed model heterogeneous within-subject variances, .e., residual variance \\(\\sigma_i^2\\) per subject \\(\\) instead global residual \\(\\sigma^2\\). makes easier identify, study weight subjects based well fit model. third option simulate imputations extra step sampler. subjects large \\(\\sigma_i^2\\), random effect estimates smooth representation data, leading inappropriate variance estimates estimates analyzed “just data”. Section 11.3 van Buuren (2018b) pioneered solution constructs multiple trajectories adding proper amount residual noise random effect estimates. variance estimation proceeds according principles multiple imputation (Rubin 1987).","code":"library(\"splines\") data <- brokenstick::smocc_200 internal <- c(0, 0.5, 1, 2) X <- bs(data$age, knots = internal, Boundary.knots = c(0, 2.68), degree = 1) colnames(X) <- paste(\"age\", c(internal, 2.68), sep = \"_\") head(X) ## age_0 age_0.5 age_1 age_2 age_2.68 ## [1,] 1.000 0.000 0.0000 0 0 ## [2,] 0.836 0.164 0.0000 0 0 ## [3,] 0.682 0.318 0.0000 0 0 ## [4,] 0.491 0.509 0.0000 0 0 ## [5,] 0.000 0.992 0.0076 0 0 ## [6,] 0.000 0.494 0.5058 0 0 data <- cbind(brokenstick::smocc_200[, c(\"id\", \"age\", \"hgt_z\")], X) ctl_lmer <- lme4::lmerControl( check.conv.grad = lme4::.makeCC(\"warning\", tol = 0.04)) f <- hgt_z ~ 0 + age_0 + age_0.5 + age_1 + age_2 + age_2.68 + (0 + age_0 + age_0.5 + age_1 + age_2 + age_2.68 | id) mod_lmer <- lme4::lmer(f, data, control = ctl_lmer) class(mod_lmer) ## [1] \"lmerMod\" ## attr(,\"package\") ## [1] \"lme4\" bse_lmer <- t(t(lme4::ranef(mod_lmer)$id) + lme4::fixef(mod_lmer)) head(round(bse_lmer, 3), 3) ## age_0 age_0.5 age_1 age_2 age_2.68 ## 10001 0.778 0.272 -0.01 0.076 0.095 ## 10002 -0.278 -0.206 -0.46 -0.477 -0.223 ## 10003 1.681 1.969 1.28 1.115 -0.256 ctl_kr <- control_kr() mod_kr <- kr(y = data$hgt_z, x = X, g = data$id, control = ctl_kr) library(\"coda\") summary(mod_kr$mod$beta) ## ## Iterations = 101:300 ## Thinning interval = 1 ## Number of chains = 1 ## Sample size per chain = 200 ## ## 1. Empirical mean and standard deviation for each variable, ## plus standard error of the mean: ## ## Mean SD Naive SE Time-series SE ## age_0 -0.0966 0.0875 0.00619 0.01001 ## age_0.5 0.0897 0.0625 0.00442 0.00442 ## age_1 -0.0196 0.0626 0.00443 0.00526 ## age_2 0.0768 0.0749 0.00530 0.00715 ## age_2.68 0.2087 0.4594 0.03249 0.15269 ## ## 2. Quantiles for each variable: ## ## 2.5% 25% 50% 75% 97.5% ## age_0 -0.2623 -0.1582 -0.0897 -0.0354 0.0600 ## age_0.5 -0.0188 0.0454 0.0943 0.1320 0.2139 ## age_1 -0.1502 -0.0633 -0.0183 0.0223 0.0922 ## age_2 -0.0623 0.0257 0.0806 0.1263 0.2168 ## age_2.68 -0.6762 -0.0168 0.1983 0.4737 1.2039 fit_lmer <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = c( 0, 0.5, 1, 2), method = \"lmer\", control = ctl_lmer) head(predict(fit_lmer, x = \"knots\", shape = \"wide\"), 3) ## # A tibble: 3 × 5 ## id `0` `0.5` `1` `2` ## ## 1 10001 0.778 0.272 -0.0101 0.0763 ## 2 10002 -0.278 -0.206 -0.460 -0.477 ## 3 10003 1.68 1.97 1.28 1.12"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"overview","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Overview","title":"Broken Stick Model for Irregular Longitudinal Data","text":"brokenstick package contains functions fit, predict plot data. Main functions, user-oriented helpers, internal functions computation used brokenstick package summarized Table 1. Table 1: Main functions, user-oriented helpers, internal functions computation used brokenstick package. package exports S3 methods class \"brokenstick\" following generic functions coef(), fitted(), model.frame(), model.matrix(), plot(), predict(), print(), residuals() summary(). object class \"brokenstick\" stores training data default. desired, specify brokenstick(..., light = TRUE) create small object just parameter estimates. course, extract original data light object. However, can still use calculate brokenstick estimates new cases using predict(object, newdata = ...).","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"data-preparation","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Data preparation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"can fit model, data need shape. brokenstick() function takes tidy data long-form. Every row data corresponds one visit. Two columns identify visit: subject variable time variable. Thus, subject one three visits subject two five visits, combined data eight records. section uses built-smocc_200 data, containing heights 200 children measured ten visits two years (Herngreen et al. 1994). subject variable id time variable age.","code":"library(\"brokenstick\") head(smocc_200, 3) ## # A tibble: 3 × 7 ## id age sex ga bw hgt hgt_z ## ## 1 10001 0 female 40 3960 52 0.575 ## 2 10001 0.0821 female 40 3960 55.6 0.888 ## 3 10001 0.159 female 40 3960 58.2 0.797"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"transformation-to-standard-deviation-scores-sds","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Transformation to Standard Deviation Scores (SDS)","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model can fit observations either raw scale \\(Y\\) (cm, kg, ) \\(Z\\)-score. normal distribution mean \\(\\mu\\) standard deviation \\(\\sigma\\) \\(Z\\)-score data value \\(Y\\) defined \\(Z = (Y - \\mu)/\\sigma\\). statistics, customary estimate \\(\\mu\\) \\(\\sigma\\) data, can also take values external reference table. example, heights boys age \\(t\\) follow approximate normal distribution age-specific mean \\(\\mu_t\\) age-specific standard deviation \\(\\sigma_t\\). reference table consists estimates \\(\\mu_t\\) \\(\\sigma_t\\) different ages \\(t\\). calculate standard deviation score (SDS) boy height \\(Y\\) age \\(t\\) \\(Z = (Y - \\mu_t)/\\sigma_t\\), \\(\\mu_t\\) \\(\\sigma_t\\) taken reference table. can compare \\(Z\\)-score directly reference population, compare two measurements taken different ages age effect removed. SDS calculation standard methodology child growth, available many distributions. See Stasinopoulos Rigby (2007) details. Analysis \\(Z\\)-scores preferable raw scale several reasons: growth curve follows centile reference distribution translates horizontal line \\(Z\\)-score scale, simplifies modeling; Observations \\(Z\\)-score scale closer multivariate normality; Analysis \\(Z\\)-scores removes overpowering impact age sex growth, becomes easier highlight interesting variation within children; Fitting \\(Z\\)-score data leads fewer convergence issues. area child growth, easy convert raw measurements \\(Z\\)-score scale, fit model, convert back raw scale afterwards, desired. several R packages assist calculations: AGD (van Buuren 2018a), anthro (Schumacher, Borghi, Polonsky 2020), childsds (Vogel 2020), growthstandards (Hafen 2021), nlreferences (van Buuren 2021b), sitar (Cole 2022) zscorer (Myatt Guevarra 2019). smocc_200 data contains height measurement original scale cm (hgt) \\(Z\\)-score scale (hgt_z) relative height references Fourth Dutch Growth study (Fredriks et al. 2000). illustration, let us calculate check height SDS using AGD package. Figure 3: Distribution height SDS 200 SMOCC children aged 0-2 years relative Dutch 1997 length references. distribution closely follows normal distribution. outliers left tail genuine observations children born pre-term. Figure 3 shows , expected, empirical Z-score distribution close standard normal. extremely low heights correspond pre-term born infants. Section 5.4 concentrates modelling hgt_z. Function z2y() applies inverse transformation \\(Z\\)-scores original scale. following snippet converts hgt_z cm scale. used Dutch 1997 height references , similar transforms made using references. Many age- sex-conditional references exist field child growth. fields, references may rare uncommon. case, may achieve benefits \\(Z\\)-scale analysis applying broken stick model standardized residuals preliminary non-linear regression outcome time.","code":"library(\"AGD\") z <- with(smocc_200, y2z(y = hgt, x = age, sex = ifelse( sex == \"male\", \"M\", \"F\"), ref = nl4.hgt)) identical(z, smocc_200$hgt_z) ## [1] TRUE y <- with(smocc_200, AGD::z2y(z = hgt_z, x = age, sex = ifelse( sex == \"male\", \"M\", \"F\"), ref = nl4.hgt)) all.equal(y, smocc_200$hgt, tol = 0.0001) ## [1] TRUE"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"model-fitting","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Model fitting","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 4: Detrended growth chart. Length growth 52 infants 0-2 years expressed Z-score scale. trajectory represents child. Trajectories almost flat representation. centile crossings occur near start trajectory. Figure 4 displays growth curves subset 52 children. \\(Z\\)-score transformation takes away major time trend, trajectories less flat. display allows us see extremely detailed assessment individual growth. Note measurements cluster around ten ages: Birth, 1, 2, 3, 6, 9, 12, 15, 18 24 months. data collectors rigorously followed study design, variation timing inevitable weekends, holidays, sickness, events.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"fit-one-line","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.4 Model fitting","what":"Fit one line","title":"Broken Stick Model for Irregular Longitudinal Data","text":"start, let us fit simple straight line model age range 0y-2y. argument knots = c(0, 2) specifies wish model data age range 0y-2y straight line. Closer inspection get_knots(fit1, hide = \"none\") reveals actually another knot right boundary age 2.68 years. knot needs ensure data taken account, direct interest. can plot individual trajectories : Figure 5: Observed data (blue) fitted broken stick model (red) straight line birth two years. model picks overall trend, ignores systematic patterns around line. Figure 5 shows observed (blue) fitted (red) trajectories three selected children. side note, can actually plot model full age range data adding argument hide = \"none\" plot() function (shown). Observe model captures overall age trend, fit data moderate.","code":"fit1 <- brokenstick(hgt_z ~ age | id, smocc_200, knots = c(0, 2)) get_knots(fit1, hide = \"none\") ## [1] 0.00 2.00 2.68 ids <- c(10001, 10005, 10022) plot(fit1, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\")"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"fit-two-lines","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.4 Model fitting","what":"Fit two lines","title":"Broken Stick Model for Irregular Longitudinal Data","text":"now extend two connected lines. first line start birth end age one year. second line spans period one two years. lines must connect age one year. estimate plot model follows: resulting plot already shown Figure 2 (top line). fit2 object holds parameter estimates model: printed output lists knots model 0, 1 2 years. left right boundaries located 0 2.68, respectively, corresponding lowest highest ages data. data right boundary suppressed since brokenstick() function sets fit2$hide = \"right\" default. means entry lists fixed effect estimates, interpret average SDS per time point. time--time variance-covariance matrix covers four random effects (3 visits + 1 end knot). two error parameters measure variability discrepancies model observed data. three parameters (fixed, random, residual variance) well interpretable fully record fitted broken stick model.","code":"fit2 <- brokenstick(hgt_z ~ age | id, smocc_200, knots = 0:2) plot(fit2, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\") summary(fit2) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 16 (total), 4 (fixed), 4 (variance), 6 (covariance), 2 (error) ## Knots 0 1 2 ## Means -0.0450 0.0179 0.0611 ## Residuals 0.125 0.150 0.170 0.200 0.379 (min, P25, P50, P75, max) ## Mean resid 0.182 ## R-squared 0.866 ## ## Variance-covariance matrix ## age_0 age_1 age_2 ## age_0 1.226 ## age_1 0.494 0.841 ## age_2 0.454 0.794 0.874"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"fit-nine-lines","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.4 Model fitting","what":"Fit nine lines","title":"Broken Stick Model for Irregular Longitudinal Data","text":"two-line model fit well. substantially refine model adding knot scheduled visit. code run model small residual variance 0.077, nine-line broken stick model fits observed data well. Figure 2 (bottom line) illustrates nine-line model follows data much better. training set includes subjects. Depending study goals, may wish improve model fit removing children data. example, might children observations available, children diseases, children trajectories unusual faulty. distribution subject-specific residuals, plotted hist(fit9$sigma2j), shows one severe outlier. can locate plot outlier plot(fit9, group = unique(fit9$data$id)[(fit9$sigma2j > 4)]). remove increase model fit, course, removals may affect external generalizability.","code":"fit9 <- brokenstick(hgt_z ~ age | id, smocc_200, seed = 1, knots = round(c(0:3, 6, 9, 12, 15, 18, 24)/12, 4))"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"prediction","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Prediction","title":"Broken Stick Model for Irregular Longitudinal Data","text":"fitted model, may obtain predictions. subject(s) part training sample, also consist new children.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"all-subjects","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.5 Prediction","what":"All subjects","title":"Broken Stick Model for Irregular Longitudinal Data","text":"predict() function obtains predictions broken stick model. function flexible, allows prediction new subjects arbitrary ages variety output formats. simplest call produces vector containing 1942 predictions observed ages. values represent compromise person’s measurement global mean. general, fewer less extreme data points person , closer compromise toward global mean. compromise called conditional mean posterior distribution, sum fixed random effects. can obtain predictions knot every person specifying x = \"knots\" argument, e.g., result p2 table 200 rows values 10 knots. values represent regularized version observed curve, .e., predicted value knot location. Add argument hide = \"none\" predict() calculate values right boundary knot. may request combination types predictions one call result long matrix 3942 rows. two special columns. Column .pred contains predicted values. Column .source identifies whether row comes training data (value data) corresponds one knots (value added). number records training data knots : dataset perfectly suited plot summarizes data model predictions. Now suppose desire predict height SDS ages, e.g., 0.42, 1.33 4 years. can include_data = FALSE argument removes observed data result prevent conversion overly large inefficient wide matrix. Thus, considerable flexibility work times breakpoints. Remember though underlying model change. example, magically predict outside model age 4, values get NA.","code":"p1 <- predict(fit9, shape = \"vector\") head(p1) ## [1] 0.574 0.852 0.750 0.643 0.231 -0.168 p2 <- predict(fit9, x = \"knots\", shape = \"wide\") head(p2, 3) ## # A tibble: 3 × 11 ## id `0` 0.083…¹ 0.166…² `0.25` `0.5` `0.75` `1` `1.25` `1.5` ## ## 1 10001 0.574 0.856 0.739 0.650 0.237 -0.172 0.121 0.163 -0.193 ## 2 10002 -0.189 -0.311 -0.260 -0.315 -0.229 -0.282 -0.336 -0.494 -0.490 ## 3 10003 1.17 2.10 1.98 2.02 2.04 1.81 1.31 1.14 0.880 ## # … with 1 more variable: `2` , and abbreviated variable names ## # ¹​`0.0833`, ²​`0.1667` p3 <- predict(fit9, x = \"knots\") head(p3, 3) ## .source id age sex ga bw hgt hgt_z .pred ## 1 data 10001 0.0000 female 40 3960 52.0 0.575 0.574 ## 2 data 10001 0.0821 female 40 3960 55.6 0.888 0.852 ## 3 data 10001 0.1588 female 40 3960 58.2 0.797 0.750 table(p3$.source) ## ## added data ## 2000 1942 head(predict(fit9, x = c(0.42, 1.33, 4), shape = \"wide\", include_data = FALSE), 3) ## # A tibble: 3 × 4 ## id `0.42` `1.33` `4` ## ## 1 10001 0.369 0.0492 NA ## 2 10002 -0.257 -0.493 NA ## 3 10003 2.03 1.05 NA"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"single-subject","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.5 Prediction","what":"Single subject","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Obtaining predicted values selected subjects requires group argument (case 3 predict()). example returns vector predictions child 10001. Appending child’s data conveniently done removing shape argument. Also, can predict times using x argument, e.g. ages 0.42 1.33 (case 4 predict()). Now suppose subject 10001 additional height data ages 0.42 1.33 years, say -0.5 SDS -1 SDS, respectively. Can predict child’s trajectory new points included? answer yes: command (case 5 predict()) appends two new records data child 10001, recalculates trajectory using data child 10001. Note last two rows contain specified values columns age hgt_z, well predicted value .pred. predicted values different calculated case 4 two additional observations. desired user also fill values columns sex, ga, .","code":"predict(fit9, group = 10001, shape = \"vector\") ## [1] 0.574 0.852 0.750 0.643 0.231 -0.168 0.121 0.151 -0.150 ## [10] 0.142 predict(fit9, x = c(0.42, 1.33), group = 10001, shape = \"vector\") ## [1] 0.5744 0.8519 0.7503 0.6428 0.2308 -0.1682 0.1214 0.1505 ## [9] -0.1500 0.1424 0.3693 0.0492 predict(fit9, x = c(0.42, 1.33), y = c(-0.5, -1), group = c(10001, 10001)) ## .source id age sex ga bw hgt hgt_z .pred ## 1 data 10001 0.0000 female 40 3960 52.0 0.575 0.61363 ## 2 data 10001 0.0821 female 40 3960 55.6 0.888 0.78191 ## 3 data 10001 0.1588 female 40 3960 58.2 0.797 0.67251 ## 4 data 10001 0.2546 female 40 3960 61.2 0.661 0.46165 ## 5 data 10001 0.5038 female 40 3960 67.2 0.290 0.00908 ## 6 data 10001 0.7529 female 40 3960 70.2 -0.398 -0.28561 ## 7 data 10001 1.0021 female 40 3960 75.7 0.202 -0.01344 ## 8 data 10001 1.1745 female 40 3960 78.5 0.268 -0.13440 ## 9 data 10001 1.5661 female 40 3960 81.8 -0.332 -0.39919 ## 10 data 10001 2.0096 female 40 3960 88.3 0.227 0.05064 ## 11 added 10001 0.4200 NA NA NA -0.500 0.15972 ## 12 added 10001 1.3300 NA NA NA -1.000 -0.27760"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"new-subject","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.5 Prediction","what":"New subject","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Suppose measured two new children, Fred Alice. wish obtain predictions using model fit9. following snippet calculates predictions observed ages knot locations: can plot trajectories data Figure 6: Broken stick model prediction sparse data. Alice Fred observations (blue points). broken stick model borrows information children calculate fitted trajectories full age range (red points). Alice contributes two data points first half-year. model expects height SDS around $-$1 SD age two years. Using data 1.1 years, model predicts Fred’s growth curve remains around -2.0 SD Fred 1.5 years, increases around -1.8 SD. predicted trajectories extreme extrapolations, example illustrates possible make informed predictions using just handful data points. brokenstick:::EB() function implements empirical Bayes (EB) estimate (Skrondal Rabe‐Hesketh (2009), p. 683). procedure workhorse underlying predict() method.","code":"data <- data.frame(age = c(0, 0.12, 0.32, 0.62, 1.1, 0.25, 0.46), hgt_z = c(-1.2, -1.8, -1.7, -1.9, -2.1, -1.9, -1.5), id = c( rep(\"Fred\", 5), rep(\"Alice\", 2))) p <- predict(fit9, newdata = data, x = \"knots\") plot(fit9, newdata = data, ylim = c(-2.5, 0), xlab = \"Age (years)\", ylab = \"Length (SDS)\")"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"quality-of-prediction","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Quality of prediction","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 7: Comparison predicted (vertical) observed (horizontal) height SDS scale (left) CM scale (right) SMOCC data. model almost perfectly recreates observed data. Figure 7 scatter plot observed versus predicted values provides visual representation accuracy prediction model height SDS cm scales. plots suggest excellent fit observed fitted data. percentage explained variance height SDS high: 98.1%. standard deviation residuals equal 0.077 SD, small value \\(Z\\)-scale. back-converted centimeters, scatter plot observed versus predicted values even little tighter. estimate proportion explained variance close perfection: 99.9%. standard deviation residuals 4 mm, size technical error measurement (TEM) duplicate measurements infants (Ismail et al. 2016, Table 2). --sample predictive behavior comparable. randomly split data 100 times 2/3 training data 1/3 test data calculate proportion test data, obtain even slightly higher --sample values: 98.4% 99.9% 100 replications. model good can get. uncertainties associated transformation varying observation times repeated measures small. practical purposes, results linear mixed multilevel model repeated measures model likely .","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"knot-placement-strategies","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Knot placement strategies","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Fitting broken stick model requires specification knots. choice knots influences quality usefulness solution, exercise care setting appropriate knot locations. brokenstick() function uses set knots subjects. default, procedure places five internal knots (default argument k = 5) sets boundary knots equal range predictor variable. k argument quick way add k internal knots equidense quantiles time variable. example, specifying k = 1 puts knot 50th centile (median), setting k = 3 puts knots 25th, 50th 75th centiles, . convenient quick, option can result sub optimal knot placement adequate problem hand. general, best specify explicit values knots argument. suggestions knot placement knots argument: Rule thumb: Limit number knots average number data points per subject; want predict specific times, specify knots time points; Setting knots scheduled visits sensible strategy obtaining predictions precisely scheduled times; Set equidistant knots analysis requires fixed time interval; Keep number knots low, speed simplicity. many (\\(\\geq 10\\)) knots can improve fit data, also increase calculation time may result unstable solutions. problems require 10 knots, method = \"kr\" (default) faster method = \"lmer\". Use control_kr() improve stability setting correlation model. brokenstick() function accept 50 knots; place knots sparsely filled areas data, e.g., -two visits. may result erratic joins; Optionally, check whether model.matrix(fit) produces design matrix elements range \\([0, 1]\\) rows summing \\(1\\). Check colSums(model.matrix(fit)) see total number observations distributes knots; Optionally, contrast 6, add knot equal slightly higher maximum time value. ensures model specification depend range training data. See next point alternative; Prevent data-dependent boundary knots explicitly specifying boundary argument brokenstick() convenient values just outside range x variable. brokenstick() function automatically sets boundary knots range time variable, necessary extends boundary knots include range knots. Normally, concentrate setting proper knots less concerned left right boundary knots. cases, time range test data larger training data. following code block shows effect adding extra knot, according point 8 . code trims time range training data age 2.1 fits two models. Model 1 limited time range \\([0, 2.1]\\) years. Therefore predict 2.1 years, predictions contain 34 NA’s. One might say correct result fitted model informative beyond age 2.1 years, hence NA’s useful plausible. comparison, model 2 uses training test data, sets wider time interval \\([0, 3]\\). consequence, model 2 produces predictions test data. predictions might useful cases. example, simulation studies often resample regenerate data, time range may vary replications. Setting boundary include largest range possible avoids problems caused NA predictions. general, make model specification independent training data, add extra knot equal slightly higher maximum time value train test data. Due sparse data, broken stick estimates boundaries can widely erratic useful interpretation. best exclude estimates plots calculations. Depending data, erratic estimates can occur left right boundaries. code block reverses age, now sparse data left boundary. consequence, need supply hide = \"left\" (instead default hide = \"right\") argument brokenstick() function. desired, one may add hide argument also plot() overwrite fit2_mirror$hide.","code":"train <- smocc_200[smocc_200$age < 2.1, ] fit1 <- brokenstick(hgt_z ~ age | id, data = train, knots = c(0, 1, 2)) fit2 <- brokenstick(hgt_z ~ age | id, data = train, knots = c(0, 1, 2, 3)) p1 <- predict(fit1, newdata = smocc_200, shape = \"vector\") p2 <- predict(fit2, newdata = smocc_200, shape = \"vector\") table(is.na(p1)) ## ## FALSE TRUE ## 1908 34 table(is.na(p2)) ## ## FALSE ## 1942 data <- smocc_200 data$age <- -data$age fit2_mirror <- brokenstick(hgt_z ~ age | id, data = data, knots = c(-2, -1, 0), hide = \"left\") plot(fit2_mirror, groups = c(10001, 10005, 10022))"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"critical-periods","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Critical periods","title":"Broken Stick Model for Irregular Longitudinal Data","text":"following question motivated development broken stick model: ages children become overweight? Knowing answer question provides handles preventive interventions counter obesity. Dietz (1994) suggested existence three critical periods obesity adult age: prenatal period, period adiposity rebound (roughly around age 5-6 years), adolescence. Obesity formed periods likely increase obesity risk adult age complications. growth period, bounded ages \\(T_1\\) \\(T_2\\), critical adult overweight following criteria hold (de Kroon et al. 2010): significant difference mean gain score \\(Z_2-Z_1\\) subjects without adult overweight; gain score \\(Z_2-Z_1\\) independent contribution \\(Z_2\\) prediction \\(Z_{\\rm adult}\\). matters \\(T_2\\) also got ; \\(Z_2\\) correlates highly \\(Z_{\\rm adult}\\), easier (.e., higher sensitivity specificity) identify children risk adult overweight. de Kroon et al. (2010) found age interval 2-6 years met criteria critical period. re-analysis tests requirements following age intervals: Birth-4 months, 4 months-1 year, 1-2 years, 2-4 years, 4-6 years, 6-10 years 10-14 years. Hence, define following break ages: Figure 8: Scatter plot BMI SDS log(age + 0.2) Terneuzen cohort data. plot shows differential amounts clustering measurements around specified break ages. Clustering tighter ages (birth, 1y, 14y) others (4m, 2y, 24y). Terneuzen Birth Cohort (de Kroon et al. 2008) comprises 2604 children born around year 1980 Terneuzen, Netherlands. Figure 8 shows body mass index (BMI) standard deviation scores (SDS) age random subset 306 children. may easily recognize scheduled visits birth, 1y 14y, figure shows observations periods less structured. Compared analysis de Kroon et al. (2010), removed knots 8 days 18 years (appear sparse data areas) added knots 4, 14 24 years. aesthetic reasons, set right boundary knot 29y, slightly higher maximum age data. control specification prevents warnings messages result -parametrized nature model. One may stabilize model restricting variance-covariance matrix, example Argyle correlation model. result, fitted trajectories stabler regions sparse data. following snippet applies Argyle model. Figure 9: Observed fitted BMI SDS trajectories six subjects predicted lmer (red) Argyle (green) models. figure illustrates fitted trajectories Argyle model stabler areas sparse data. Figure 9 shows observed fitted BMI SDS trajectories models. per cent explained variance BMI SDS similar : 84 per cent. lmer model, fitted trajectory subject 8 reveals pretty rough estimate age 24y. Persons 1259 7460 low (-2.5 SD) high (+2.5 SD) BMI SDS adult age, respectively. Note model pulls adult BMI SDS estimates (red) towards global mean, due well-known bias-variance trade (Gelman Hill 2007, 394). Pulling vigorous extremes. effect negligible average trajectories, subject 2447. Argyle model, trajectories slightly smoother stable adult ages limited data. rough estimate subject 8 gone. still gravity towards global mean knot 24y persons 1259 7460, lesser magnitude. fitted trajectories well behaved. , therefore, select kr solution analysis. identify critical periods, need predict adult overweight. Figure 9, three six subjects BMI measurement adult age. Since want results overly depend fitted extrapolations, restrict analysis sample persons adult measurement. following lines extract repeated measures 92 (306) individuals observed adult BMI. Figure 10: Fitted BMI SDS trajectories 92 subjects, 18 persons adult overweight (red = observed BMI adult age > 1.3 SDS), 74 individuals (gray) adult overweight. figure shows BMI distribution age 2y similar groups, whereas BMI ages 10y 14y highly predictive adult overweight. Figure 10 shows 92 fitted trajectories colored adult overweight status (observed BMI SDS > 1.3). evident BMI SDS ages 14y 10y highly predictive adult overweight, also hold early childhood? Also, change specific periods predict later overweight? answer questions, fit simple linear models predict observed (fitted!) BMI SDS adult age fitted BMI SDS trajectories. following code block fits two models period 4y-6y. Model m1 predicts adult BMI SDS BMI SDS 6y, explains 45.3 per cent variance. Model m2 extends model pre-gain 4y 6y. pre-gain improves prediction, matters much gained 4y 6y. case, call interval 4y-6y critical period. found model 2 explain 53.6 per cent variance, thus 8.3 per cent . anova statement performs formal test. case, pre-gain significant last predictor 6y. Thus, interval 4y-6y classifies critical period. can repeat analyzes age intervals, similar Table 3 Kenward (1987).","code":"knots <- round(c(0, 1/3, 1, 2, 4, 6, 10, 14, 24, 29), 3) labels <- c(\"birth\", \"4m\", \"1y\", \"2y\", \"4y\", \"6y\", \"10y\", \"14y\", \"24y\", \"\") ctl <- lme4::lmerControl( check.conv.grad = lme4::.makeCC(\"warning\", 0.02, NULL), check.conv.singular = lme4::.makeCC(\"ignore\", 0.001)) fit_lmer <- brokenstick(bmi.z ~ age | id, data = mice::tbc, knots = knots, boundary = c(0, 29), method = \"lmer\", control = ctl) fit_kr <- brokenstick(bmi.z ~ age | id, data = mice::tbc, knots = knots, boundary = c(0, 29), seed = 41441, cormodel = \"argyle\") tbc1 <- mice::tbc %>% filter(!is.na(ao) & first) %>% select(id, nocc, sex) tbc2 <- mice::tbc.target %>% filter(id %in% tbc1$id) prd <- predict(fit_kr, mice::tbc, x = \"knots\", shape = \"wide\", group = tbc1$id) data <- bind_cols(prd, select(tbc1, -id), select(tbc2, -id)) head(data, 3) ## # A tibble: 3 × 14 ## id `0` `0.333` `1` `2` `4` `6` `10` `14` `24` ## ## 1 8 0.371 -0.440 0.366 1.45 1.10 0.606 0.489 0.544 -0.822 ## 2 60 0.159 -0.372 -0.0442 -0.360 -0.595 -0.818 -1.03 -1.16 -1.46 ## 3 97 1.68 0.569 0.948 1.90 1.28 0.838 0.444 0.238 0.397 ## # … with 4 more variables: nocc , sex , ao , ## # bmi.z.jv m1 <- lm(bmi.z.jv ~ `6`, data) m2 <- lm(bmi.z.jv ~ `6` + I(`6`-`4`), data) anova(m1, m2) ## Analysis of Variance Table ## ## Model 1: bmi.z.jv ~ `6` ## Model 2: bmi.z.jv ~ `6` + I(`6` - `4`) ## Res.Df RSS Df Sum of Sq F Pr(>F) ## 1 90 74.3 ## 2 89 63.4 1 10.8 15.2 0.00019 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"time-to-time-correlations","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Time-to-time correlations","title":"Broken Stick Model for Irregular Longitudinal Data","text":"conditional gain score defined (Cole 1995) \\[ {\\rm conditional}\\ Z_{\\rm gain} = \\frac{Z_2 - rZ_1}{\\sqrt{1-r^2}}, \\] \\(Z_1\\) \\(Z_2\\) standard deviation scores times \\(T_1\\) \\(T_2\\), \\(T_2>T_1\\), \\(r\\) correlation \\(Z_1\\) \\(Z_2\\). conditional gain corrects regression mean, selling point traditional velocity measures less sensitive measurement error (van Buuren 2007). practical difficulty obtain \\(r\\) given \\(T_1\\) \\(T_2\\). time--time correlation matrix needs known. Also, need interpolate \\(r\\) \\(T_1\\) \\(T_2\\) differs tabulated ages. broken stick model provides estimate time--time correlation matrix. brokenstick object stores variance-covariance matrix \\(\\Omega\\) random effects. perfectly fitting model (\\(\\sigma^2 = 0\\)) \\(\\Omega\\) equals time--time covariance matrix, get_omega(fit, cor = TRUE) gives desired time--time correlation matrix. \\(\\sigma^2 > 0\\) \\(\\Omega\\) overestimates covariances observed data. general, need add within-residual variance estimate diagonal, thus \\(\\Omega + \\hat\\sigma^2 (n_i)\\) estimate time--time covariance matrix. child growth, expect correlation tapers difference \\(T_1\\) \\(T_2\\) grows. Also, fixed interval \\(T_2-T_1\\) expect correlation increase age. Altering number location knots may change . often useful scan time--time correlation matrix gross deviations expectations. happens, one simplify model, example, subjecting \\(\\Omega\\) correlation model. code fits model 21 equidistant breakpoints, likely large enough purposes. works restricts covariance-matrix Argyle correlation model, summarizes information just two parameters. may extract re-estimate parameters create one-liner calculating \\(r\\). indefinitely add breakpoints. Suppose double number knots setting knots = seq(0, 2, 0.05). even kr able cope abort Error: Sigma symmetric positive. Thus, always, sensible ask software .","code":"fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = 1:4/2) omega <- get_omega(fit) t2t <- omega + diag(fit$sigma2, ncol(omega)) round(cov2cor(t2t), 2) ## age_0 age_0.5 age_1 age_1.5 age_2 ## age_0 1.00 0.57 0.42 0.37 0.31 ## age_0.5 0.57 1.00 0.76 0.71 0.67 ## age_1 0.42 0.76 1.00 0.80 0.78 ## age_1.5 0.37 0.71 0.80 1.00 0.82 ## age_2 0.31 0.67 0.78 0.82 1.00 fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = seq(0, 2, 0.1), cormodel = \"argyle\") omega <- get_omega(fit) t2t <- omega + diag(fit$sigma2, ncol(omega)) dim(t2t) ## [1] 21 21"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"profile-analysis","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Profile analysis","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Profile analysis (Morrison 1976; Johnson Wichern 1988) refers linear multivariate linear methods test differences population means treatment effects, typically regression analysis multivariate analysis variance (MANOVA). methods assume independence subjects, organize data subject level, express parameters interest linear combinations outcomes, like change scores, means derived quantities. Krone et al. (2020) report statistical analysis using linear mixed model time-varying individual subject data. section re-analyzes data Figure 4 using broken stick model. data available brokenstick::weightloss object. Figure 11: Daily body weight (KG) 12 subjects followed 63 days one three conditions. graph illustrates irregular nature data. trajectories almost complete regular, whereas others miss many daily measurements display surprising jumps around average weight level. Figure 11 charts daily body weight measurements twelve individuals followed nine weeks. investigators subdivided total duration three periods three weeks. Period one (week 1-3) acted control period. period 2 (week 4-6), investigators stimulated participants restrict food intake, period 3 (week 7-9) experimenters promoted physical activity. Subjects 4 12 received interventions reverse order. See Krone et al. (2020) detail. subjects adhere quite well data collection design. trajectories show gaps due missed measurements. extreme example trajectory hovers around value 95 kilograms (KG). curves display stretches lines, suggesting missed measurements linearly interpolated. One series shows surprising spikes, likely measurement errors. , data perfectly illustrate inescapable imperfections real data. remainder section discusses two ways estimate effect diet physical activity body weight.","code":"data <- brokenstick::weightloss ggplot(data, aes(day, body_weight, group = subject, color = condition)) + scale_x_continuous(name = \"Day\", breaks = c(0, 21, 42, 63), minor_breaks = c(7, 14, 28, 35, 49, 56)) + ylab(\"Body weight (KG)\") + geom_line() + geom_point(size = 0.7) + theme_light() + theme(legend.position = \"bottom\")"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"constant-model","dir":"Articles > Manual","previous_headings":"6 Applications > 6.3 Profile analysis","what":"Constant model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 12: Constant model. Observed fitted trajectories model summarizes experimental period constant. estimated level approximately mean measurements made period. model produces sudden jumps ages condition changes thus fails describe data well. model underlying Figure 12 summarizes trajectory within period constant, mean. obtain estimate means setting degree = 0 argument. model gives fair representation trajectory subjects 9 (persistent downward trend), 1 5 (trend). hand, model fails capture patterns subjects 2, 4 8 (rebound period 3) 11 (inverse rebound). straightforward quantify effects Diet Activity relative Control. next code snippet calculates effects per person, accounting intervention order reversal subjects 4 12. average weight caloric restriction 564 grams lower control. find 848 grams lower body weight stimulate physical activity. tempted believe exercise reduces weight diet. However, except subjects 4 12, investigators administered activity treatment diet treatment, difference relative control represents combined effect diet activity body weight. might relevant study difference training diet (third column). average difference -284 grams suggests diet effective physical activity. Realize also estimate entirely satisfactory. First, subjects 4 12 reversed administration, difference make sense . Second, anyone tried lose weight can attest, “quick wins” likely period 2 period 3. Although possible account sequence effects, intuitive analysis data.","code":"data <- brokenstick::weightloss fit0 <- brokenstick(body_weight ~ day | subject, data, knots = c(0, 21, 42, 63), degree = 0, method = \"lmer\", hide = \"none\") plot(fit0, size_y = 0, color_y = rep(\"gray\", 2), scales = \"free_y\", xlab = \"Day\", ylab = \"Body weight (KG)\", n_plot = 12, ncol = 4) prd <- data.frame(predict(fit0, data, x = \"knots\", shape = \"wide\")) control <- prd[, 2] diet <- prd[, 3] diet[c(4, 12)] <- prd[c(4, 12), 4] activity <- prd[, 4] activity[c(4, 12)] <- prd[c(4, 12), 3] effects <- 1000 * data.frame( diet_control = diet - control, activity_control = activity - control, activity_diet = activity - diet) round(effects) ## diet_control activity_control activity_diet ## 1 174 179 5 ## 2 -1055 -1759 -704 ## 3 961 1045 84 ## 4 -1846 -723 1123 ## 5 371 149 -223 ## 6 -1582 -3269 -1687 ## 7 -158 -514 -356 ## 8 -614 -1057 -443 ## 9 -1166 -2039 -872 ## 10 -594 -1210 -616 ## 11 63 -559 -621 ## 12 -1322 -425 897 round(colMeans(effects)) ## diet_control activity_control activity_diet ## -564 -848 -284"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"broken-stick-model-1","dir":"Articles > Manual","previous_headings":"6 Applications > 6.3 Profile analysis","what":"Broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 13: Broken stick model. Observed fitted trajectories model summarizes experimental period line. slope indicates change period. model connects lines adjacent periods provides informative description data. Figure 13 shows data Figure 12 now fitted linear broken stick model. model also suggests persistent downward trend subject 9 absence trend participants 1 5. Also, model now correctly identifies prominent zig-zag patterns persons 2, 4, 8 11 across three experimental periods. natural way quantify effect intervention calculate -estimate per period. example, person 2 effect diet \\(60,933 - 63,671 = -2,738\\) grams, activity \\(62,635 - 60,933 = +1,701\\) grams. following code accounts alternate treatment ordering subjects 4 12. average effects -201 grams (control), -683 grams (diet) -301 grams (activity). Although statistically significant, slight decrease 201 grams control period suggests weight monitoring may motivate participant lose weight. effect estimates diet activity similar magnitude . Still, can sizeble discrepancies individual level, e.g., subjects 2 11. may obtain simple estimate sequence effect linear regression Variable y change grams observed periods 2 3, activity dummy variable treatment (0 = diet, 1 = activity) activity2 dummy variable indicating activity occurred period 2 (0 = , 1 = yes). average loss weight per period equal 492 grams. second model shows diet reduces body weight activity (382 grams). third model indicates activity applied period 2 effective period 3, reduces weight additional 123 grams. course, bear mind calculated results individuals. Hence, sensitive substantial estimation error. application demonstrates broken stick model can effectively capture rapid linear changes experiments. Even though actual timing observations may erratic, easy define, interpret calculate intuitive effect estimates individual level. Note analysis assumed instantaneous effect interventions. expect delay, may right-shift knots days re-estimate broken stick model. varying number days, may able detect optimal delay factor.","code":"ctl_lmer <- lme4::lmerControl( check.conv.grad = lme4::.makeCC(\"warning\", tol = 0.01)) fit1 <- brokenstick(body_weight ~ day | subject, data, knots = c(0, 21, 42, 63), method = \"lmer\", control = ctl_lmer, hide = \"none\") plot(fit1, size_y = 0, color_y = rep(\"gray\", 2), size_yhat = 1.5, scales = \"free_y\", , xlab = \"Day\", ylab = \"Body weight (KG)\", n_plot = 12, ncol = 4) prd <- data.frame(predict(fit1, data, x = \"knots\", shape = \"wide\")) control <- prd[, 3] - prd[, 2] diet <- prd[, 4] - prd[, 3] diet[c(4, 12)] <- prd[c(4, 12), 5] - prd[c(4, 12), 4] activity <- prd[, 5] - prd[, 4] activity[c(4, 12)] <- prd[c(4, 12), 4] - prd[c(4, 12), 3] effects <- 1000 * data.frame( control = control, diet = diet, activity = activity) round(effects) ## control diet activity ## 1 -303 459 -411 ## 2 95 -2738 1701 ## 3 847 479 570 ## 4 117 682 -2168 ## 5 637 -606 659 ## 6 -756 -2594 -833 ## 7 251 -783 277 ## 8 -297 -1112 349 ## 9 -1006 -1389 -424 ## 10 -190 -1096 -290 ## 11 -908 929 -2573 ## 12 -902 -423 -468 round(colMeans(effects)) ## control diet activity ## -201 -683 -301 df <- data.frame(y = 1000 * c(diet, activity), activity = rep(c(0, 1), each = 12), activity2 = rep(c(rep(0, 3), 1, rep(0, 7), 1), 2)) coef(lm(y ~ 1, data = df)) ## (Intercept) ## -492 coef(lm(y ~ activity, data = df)) ## (Intercept) activity ## -683 382 coef(lm(y ~ activity + activity2, data = df)) ## (Intercept) activity activity2 ## -662 382 -123"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"problem","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Problem","title":"Broken Stick Model for Irregular Longitudinal Data","text":"growth chart visualizes individual trajectory relative set centile lines. may store centile line set coordinates relatively dense age grid. connect adjacent vertices straight line, centile appear smooth time. However, plotting method runs trouble ages wide apart. section shows can create realistic interpolation sparse time data.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpolation-in-measurement-scale","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Interpolation in measurement scale","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Suppose measured length boy ages 1 month (52.6 cm) 14 months (81.7 cm). following code block uses AGD::y2z() function convert measurements SDS relative reference Fourth Dutch Growth Study. Figure 14: effect three interpolation methods (linear cm (blue), linear SDS (red), broken stick model (green)). method, vertical line indicates age interpolated curve crosses mean age-conditional length distribution. linear methods results unrealistic trajectories intermediate ages. example, points blue lines low. Interpolation broken stick method alternative correctly describes faster growth first months. period boy grows moderately short (-1.0 SD month 1) relatively tall (+1.0 SD month 14). Figure 14 shows usual representation growth chart straight line drawn two values. Due concave shape centile lines, straight line connects two measurements starts -1.0 SD, touches -2.0 SD centile around 4.5 months, back -1.0 SD age 7.5 months, crosses 0.0 SD line 11.5 months, ends +1.0 SD 14 months. right hand side graph portrays interpolated growth curve SDS scale. Since length growth infancy linear time, finding real growth curve like extremely unlikely. Since just two data points smoothing data help either.","code":"boy <- data.frame(x = c(1, 14), y = c(52.6, 81.7)) ref <- AGD::nl4.hgt boy$z <- AGD::y2z(y = boy$y, x = boy$x/12, sex = \"M\", ref = ref) boy$z ## [1] -0.980 0.994"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpolation-in-the-sds-scale","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Interpolation in the SDS scale","title":"Broken Stick Model for Irregular Longitudinal Data","text":"first alternative apply linear interpolation SDS scale. option attractive centile lines straight SDS scale. red curves Figure 14 illustrate interpolation SDS scale. definition, line connects measurements straight SDS score scale. cm scale, representation realistic pleasing eye. curve crosses 0 SD line halfway, 7.5 months. approach considerable improvement interpolation \\(Y\\)-scale, still ideal. assumption underlying interpolation SDS increment constant across time. assumption false , however. Since length growth faster first half-year, expect larger share increment occur earlier months. words, cross-point 7.5 months late.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpolation-by-the-broken-stick-model","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Interpolation by the broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"second alternative model-based interpolation. Assuming availability fitted broken stick model, specify time grid, say twice month, predict length ages given data observed trajectory. expected curve represents likely values model intermediate ages. following code calculates relevant estimates fit_200 fitted model: green curve Figure 14 shows results broken stick model. curve measurement scale represents likely course according broken stick model. Note now child realizes larger share change first months. result, cross-point predicted value intersects 0 SD line now around 4.5 months, considerably earlier obtained two interpolation methods. right hand side plot confirms steeper slope first part. Note method treats rising declining curves alike. example, boy’s length 57 cm month 1 (+1.0 SD) 76 cm month 14 (-1.0 SD), cross-point also around 4.5 months (shown). Observe method leaves world pure interpolation moves towards approximation data model. observed predicted lengths exactly equal. difference small may hardly notice discrepancy plotted measurement scale, conspicuous plotted SDS. Thanks added knowledge child growth process, broken stick model provides realistic expected trajectory intermediate ages. Note green curve entirely smooth, due linearity assumption model. create smoother curve using finer grid break points. Alternatively, use correlation model predicting correlation intermediate ages. latter option convenient, currently possible predict(). Adding support correlation models area development.","code":"age <- round(seq(1, 14, 0.5), 3) z <- rep(NA, length(age)) z[1] <- boy$z[1]; z[length(z)] <- boy$z[2] zout <- predict(fit_200, x = age/12, y = z, shape = \"vector\") yout <- AGD::z2y(x = age/12, z = zout, ref = ref)"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"multiple-imputation","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Multiple imputation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Remember Section 5.5 broken stick estimates conditional means. may tempted analyze estimates “just data”, variability real data. example, suppose calculate correlation matrix broken stick estimates. know values matrix exceed underlying observed data. accounting fact leads overconfident predictions results good true. Multiple imputation (Rubin 1987; van Buuren 2018b) restores variability adding noise. may fit standard complete-data software imputed data, obtain valid regression weights, confidence intervals \\(p\\) values wide range conditions. default, method kr executes 200 iterations Kasim-Raudenbush sampler. nimp argument control_kr() function specifies number multiple imputations. following call brokenstick() function creates plots 20 imputations missing outcome (hgt_z ). Figure 15: Observed data (blue) 20 imputed trajectories (gray) three subjects SMOCC data. Imputed trajectories possible realizations observed data hypothetical case observations made specified break ages. Note pattern child 10001 certain child 10022. Figure 15 displays observed data three persons plotted top 20 imputed trajectories. within-person within-time average gray trajectories approximates broken stick estimate (shown ). observed curve panel occasionally strays towards boundaries gray bundle. behavior expected indicates blue curve performs like gray curve. Section 6.2 showed can estimate time--time correlation matrix. alternative way calculate imputed data, follows: Another important application multiply-imputed curves obtain correct confidence intervals \\(p\\) values estimates scientific interest. convenient way convert brokenstick object object class \"mids\", defined mice package. brokenstick package currently features perform conversion.","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) data <- bind_rows(smocc_200[!is.na(smocc_200$hgt_z), ], expand.grid(id = unique(smocc_200$id), age = knots)) fit_kr <- brokenstick(hgt_z ~ age | id, data = data, knots = knots, nimp = 20, seed = 15244) plot(fit_kr, show = c(TRUE, FALSE, TRUE), group = c(10001, 10005, 10022), xlab = \"Age (years)\", ylab = \"Length (SDS)\") cormat <- cor(matrix(t(fit_kr$imp), ncol = length(knots))) dimnames(cormat) <- list(knots, knots) round(cormat, 2) ## 0 0.0833 0.1667 0.25 0.5 0.75 1 1.25 1.5 2 ## 0 1.00 0.68 0.70 0.63 0.47 0.43 0.38 0.33 0.32 0.24 ## 0.0833 0.68 1.00 0.81 0.79 0.70 0.58 0.53 0.51 0.50 0.39 ## 0.1667 0.70 0.81 1.00 0.81 0.73 0.60 0.52 0.49 0.52 0.42 ## 0.25 0.63 0.79 0.81 1.00 0.75 0.64 0.58 0.56 0.53 0.46 ## 0.5 0.47 0.70 0.73 0.75 1.00 0.83 0.81 0.73 0.75 0.65 ## 0.75 0.43 0.58 0.60 0.64 0.83 1.00 0.84 0.77 0.77 0.71 ## 1 0.38 0.53 0.52 0.58 0.81 0.84 1.00 0.84 0.81 0.76 ## 1.25 0.33 0.51 0.49 0.56 0.73 0.77 0.84 1.00 0.84 0.82 ## 1.5 0.32 0.50 0.52 0.53 0.75 0.77 0.81 0.84 1.00 0.83 ## 2 0.24 0.39 0.42 0.46 0.65 0.71 0.76 0.82 0.83 1.00"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"curve-matching","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Curve matching","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Curve matching (van Buuren 2014) tool assist interpretation prediction individual growth curves. idea follows. Suppose measure growth target child half year plot measurements onto growth chart. Curve matching nearest-neighbor technique relies historical growth data. finds, say, ten children similar target child, adds curves matches child’s chart. matching done right, bundle historic growth curves suggests target child develop future. Figure 16: Curve matching. Predict infant length 14 months given length data 6 months using 10 matches. red curve observed data target child. bundle gray curves observed length curves children match trajectory target child month 6. blue line represents likely future trajectory target child towards month 14. variation gray curves represents amount uncertainty trajectory prediction. Figure 16 screen shot demo Shiny app Joint Automatic Measurement Evaluation System (JAMES). red curve corresponds five measurements target child made first six months. ten gray curves historic growth curves ten matched children. may define similarity many ways. use linear model predict length age 14m previous length data. distance target child another child equal difference predicted values. procedure lifts data matches database, plots observed growth curves onto chart gray curves. method finding nearest neighbors known predictive mean matching grown powerful technique missing data (van Buuren 2018b). bundle gray curves indicates possible future trajectories target child. wider bundle, uncertain future growth (Toet et al. 2019). mean bundle likely path. Graphically dotted blue curve last measurement age outcome. Let’s look numerical example. split data one target child 199 donor children, fit broken stick model donor set. time points donor data enter broken stick model. Note target_data contains observations first five visits. now fit prediction model child-level donor data. prediction model contains broken stick estimates length SDS 6 months, well sex, gestational age birth weight covariates. next step extract model predictions donors target find ten closest donors. steps contain basic ingredients find_matches() function chartplotter package (van Buuren 2021a). Finally, let us study observed fitted trajectories ten matches. Figure 17: Curve matching. Observed (blue) fitted (red) trajectories 10 closest matches subject 10001. Fitted values outcome age (1.25y) close predicted value target child (0.101 SD). ten trajectories close prediction (0.101 SD) target child age 1.25 years. Note guarantee histories identical. matches relatively flat curves, (10051, 11023, 11086) show striking rising patterns. Nevertheless, candidates best terms model prediction. wish curves matches first six months closer target case, consider alternative metrics. simple measure sum squares differences broken stick estimates. selection may visually pleasing, expense prediction accuracy. hand, less tied setting one particular future time point, measures may work better “future” vaguely defined time interval. still open research question strike balance. Whatever objectives preferences user might , curve matching methodology, illustrated , tremendous flexibility easy adapt.","code":"donor_data <- smocc_200 %>% filter(id != \"10001\") target_data <- smocc_200 %>% filter(id == \"10001\" & age < 0.51) knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit <- brokenstick(hgt_z ~ age | id, data = donor_data, knots = knots, seed = 15244) covariates <- donor_data %>% group_by(id) %>% slice(1) bse <- predict(fit, donor_data, x = \"knots\", shape = \"wide\") donors <- bind_cols(covariates, select(bse, -id)) model <- lm(`1.25` ~ `0` + `0.0833` + `0.1667` + `0.25` + `0.5` + sex + ga + bw, data = donors) summary(model) ## ## Call: ## lm(formula = `1.25` ~ `0` + `0.0833` + `0.1667` + `0.25` + `0.5` + ## sex + ga + bw, data = donors) ## ## Residuals: ## Min 1Q Median 3Q Max ## -1.3328 -0.2567 -0.0151 0.2634 1.4653 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 4.87e-01 8.99e-01 0.54 0.589 ## `0` 6.74e-02 5.33e-02 1.27 0.207 ## `0.0833` 5.89e-02 8.69e-02 0.68 0.499 ## `0.1667` -2.55e-01 9.92e-02 -2.57 0.011 * ## `0.25` -2.16e-01 1.07e-01 -2.01 0.046 * ## `0.5` 1.21e+00 7.54e-02 16.07 <2e-16 *** ## sexmale 9.13e-02 6.42e-02 1.42 0.157 ## ga -7.05e-03 2.25e-02 -0.31 0.754 ## bw -7.53e-05 1.09e-04 -0.69 0.491 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.436 on 190 degrees of freedom ## Multiple R-squared: 0.777, Adjusted R-squared: 0.767 ## F-statistic: 82.5 on 8 and 190 DF, p-value: <2e-16 donors_pred <- predict(model) names(donors_pred) <- donors$id target <- bind_cols( slice(target_data, 1), select(predict(fit, target_data, x = \"knots\", shape = \"wide\"), -id)) target_pred <- predict(model, newdata = target) matches <- sort(abs(donors_pred - target_pred))[1:10] matches ## 11013 10032 11035 10093 10051 11063 11086 11083 11102 ## 0.00422 0.00578 0.01833 0.01889 0.02507 0.02657 0.03069 0.03744 0.05118 ## 11049 ## 0.05922 ids <- as.numeric(names(matches)) plot(fit, group = ids, xlim = c(0, 1.4), size_y = 1, size_yhat = 0, xlab = \"Age (years)\", ylab = \"Length (SDS)\", ncol = 5)"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"overview-1","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Overview","title":"Broken Stick Model for Irregular Longitudinal Data","text":"paper introduces new approach solve problem irregular longitudinal data. method absorbs time-dependent information set broken stick estimates subject level. primary advantage simplifies analysis splitting modelling problem two steps. First, solve timing problem, solve substantive/scientific problem. method mathematically simple, conceptually appealing, yet principled.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"distinctive-features","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Distinctive features","title":"Broken Stick Model for Irregular Longitudinal Data","text":"assumptions model cover many cases practical interest: straight line breakpoints, multivariate normal distribution random effects, MAR assumption including future data. Despite relatively low number model parameters, possible obtain close fit data, sometimes almost perfect reconstruction (c.f., Figure 7). need specify equidistant breakpoints. Applications human growth development often natural using non-uniformly spaced knots, easy model. Many people find easier understand raw data values summaries. broken stick model invites visualization actual data points time makes easy portray uncertainty bundle curves. direct vizualisation options contribute explainable responsible personalized analyzes appeal broad user group.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"current-limitations","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Current limitations","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model, presented , uses just three variables: time, measurement group. design choice simplifies interpretation estimation. lack covariates model implies transformation irregular data repeated measures identical every subject. long residual error small, relations ---model variables thus remain intact. possibility include covariates second-round enhances modular modern analytic pipelines. Yet, prefer direct estimation effects one extensive analysis. current package support covariates. broken stick method intended aligning observations, every individual number location breakpoints. technique assumes subjects share time axis. applications, synchronization start natural (e.g., birth, start experiment), easy . cases, one might prefer anchor middle, e.g., menarche, occurs different ages different individuals (Naumova, Must, Laird 2001), scientific interest happens anchor. also make sense fasten end, e.g., graduation death. choice anchor may matter less cyclic processes. example, weekly data may important anchor day week actual date age. Irrespective actual timings observed data, number location breakpoints identical subjects. method less suited applications sensible common time axis, breakpoints vary individuals.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"software","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Software","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Kasim-Raudenbush sampler (Kasim Raudenbush 1998) fast flexible. produces estimates residual error variance per subject, can accommodate correlation models supports multiple imputation ---box. research needed establish statistical properties especially compared lmer() established methods. also interesting study suitability correlation models implemented lme4qtl package (Ziyatdinov et al. 2018). training data stored, instances light \"brokenstick\" class objects tiny, often 15–20 Kb. Features implemented, useful future versions include separate impute() function inputs class \"brokenstick\" returns class \"mids\", Trelliscope (Hafen Schloerke 2020) viewer quickly peruse hundreds individual model fits, extension multivariate time-varying child-level data, generalization degree > 1 support quadratic cubic splines.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"methodological-advances","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Methodological advances","title":"Broken Stick Model for Irregular Longitudinal Data","text":"primary modelling task user set proper knot locations. One might envision scenarios want search “best” locations. yet clear , far automate knot placement strategies. need insight statistical properties procedures execute analysis sequence steps. relative pro’s con’s choices multiple imputation versus random effects yet fully understood. current procedure assumes within-person error constant across time points. However, might expect observing data close breakpoint reduce uncertainty estimate. applications, might require estimate equal observed data value observation time coincides breakpoints. models scenarios considerably complicated, also increase efficiency.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"conclusion-1","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Conclusion","title":"Broken Stick Model for Irregular Longitudinal Data","text":"paper highlighted various applications broken stick model: Critical periods, time--time correlation, profile analysis, curve interpolation, multiple imputation personalized prediction. applications certainly exhaust potential model. hope availability software stimulate creative uses, ideas experiments.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"computational-setup","dir":"Articles > Manual","previous_headings":"","what":"Computational setup","title":"Broken Stick Model for Irregular Longitudinal Data","text":"running Mac Studio, MacOS Venture, V 13.1, 32GB RAM R version 4.2.2 (2022-10-31) brokenstick version 2.4.0 (2022-10-30).","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"acknowledgment","dir":"Articles > Manual","previous_headings":"","what":"Acknowledgment","title":"Broken Stick Model for Irregular Longitudinal Data","text":"thank editor reviewers suggestions helped improve manuscript software. work supported Bill & Melinda Gates Foundation. contents sole responsibility author may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"background","dir":"Articles","previous_headings":"","what":"Background","title":"Help for old friends","text":"brokenstick package three major interfaces: version brokenstick 0.62.1 (May 2020) version brokenstick 1.1.1 (May 2020 - Nov 2021) Versions higher brokenstick 2.0.0 (Nov 2021 - now) document summarises main changes brokenstick 2.0.0. See “Help old friends” brokenstick 1.1.1 overview previous changes 0.75.0 1.1.1.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"main-changes","dir":"Articles","previous_headings":"Background","what":"Main changes","title":"Help for old friends","text":"Function brokenstick() version 2.0.0 sets Kasim-Raudenbush sampler default method. former method lme4::lmer() remains available setting method = \"lmer\" argument. Version 2.0.0 adopts variable names coda package (e.g., start, end, thin, niter, ) stores results Kasim-Raudenbush sampler objects class mcmc. method = \"kr\" one may now inspect solution sampler standard functions coda package. method = \"lmer\" can apply functions lme4 package merMod objects. Version 2.0.0 redefines brokenstick class. New entries include call, formula, internal, sample, light, data, imp mod. Removed entries knots (renamed internal) draws (renamed imp). may omit newdata argument training data. Setting light = TRUE creates small version brokenstick object. Objects class brokenstick backwards compatible, one regenerate objects class brokenstick order use newer features 2.0.0. Version 2.0.0 conforms classic model fitting interface R. Renames new_data argument newdata conform predict.lm(). Methods plot() predict() longer require newdata argument. special cases predict() updated explained documentation examples. Version 2.0.0 adds methods coef(), fitted(), model.frame(), model.matrix(), print() summary() brokenstick object. Simplifies algorithmic control. Renames control_brokenstick() set_control() removes layer control list. Added support hide argument user-oriented functions. Automatic suppression last knot.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"minor-changes","dir":"Articles","previous_headings":"Background","what":"Minor changes","title":"Help for old friends","text":"Stabilises rgamma() calls KR-algorithm edge cases. predict_brokenstick() can now work (internal) training (external) test data. Removes superfluous type argument predict.brokenstick() Adds function get_omega() extract variance-covariance matrix broken stick estimates Improves error messages edge cases test-brokenstick_edge.R Perform stricter tests arguments brokenstick() Introduces argument warn_splines make_basis() suppress uninteresting warns splines::bs() Removes superfluous knotnames argument make_basis() Argument x make_basis() now vector instead column vector Introduces new xname argument make_basis() set xname","code":""},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"install-legacy-version","dir":"Articles","previous_headings":"","what":"Install legacy version","title":"Help for old friends","text":"recommend changing code reflect changes run brokenstick 2.4.0 higher. needed, version 1.1.1 can installed ","code":"library(\"devtools\") install_github(\"growthcharts/brokenstick@9b969af\")"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"example-1-fit-model","dir":"Articles","previous_headings":"Examples","what":"Example 1: Fit model","title":"Help for old friends","text":"Fit model, brokenstick package version 0.75.0 - 1.1.1: Fit model, brokenstick package version 2.4.0:","code":"library(brokenstick) data <- brokenstick::smocc_200 # formula interface fit1 <- brokenstick(hgt.z ~ age | id, data) # XY interface - numeric vector # Deprecated in v2.0.0 fit2 <- with(data, brokenstick(age, hgt.z, id)) # XY interface - data.frame # Deprecated in v2.0.0 fit3 <- with(data, brokenstick(data.frame(age), hgt.z, id)) # XY interface - matrix # Deprecated in v2.0.0 tt <- as.matrix(data[, c(1, 2, 7)]) fit4 <- brokenstick(tt[, \"age\", drop = FALSE], tt[, \"hgt.z\", drop = FALSE], tt[, \"id\", drop = FALSE]) library(brokenstick) data <- brokenstick::smocc_200 # formula interface fit1 <- brokenstick(hgt_z ~ age | id, data)"},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"example-2-predict-model","dir":"Articles","previous_headings":"Examples","what":"Example 2: Predict model","title":"Help for old friends","text":"Predict model, brokenstick package version 0.75.0 - 1.1.1: Predict model, brokenstick package version 2.4.0:","code":"# predict at observed data p1 <- predict(fit1, data) # predict at knots p2 <- predict(fit1, data, x = \"knots\") # predict at both observed data and knots p3 <- predict(fit1, data, x = \"knots\", strip_data = FALSE) # predict knots, broad matrix p4 <- predict(fit1, data, x = \"knots\", shape = \"wide\") # predict at observed data p1 <- predict(fit1) # predict at knots p2 <- predict(fit1, x = \"knots\", include_data = FALSE) # predict at both observed data and knots p3 <- predict(fit1, x = \"knots\") # predict knots, broad matrix p4 <- predict(fit1, x = \"knots\", shape = \"wide\")"},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"example-3-plot-model","dir":"Articles","previous_headings":"Examples","what":"Example 3: Plot model","title":"Help for old friends","text":"Plot trajectories, brokenstick package version 0.75.0 - 1.1.1: Plot trajectories, brokenstick package version 2.4.0:","code":"ids <- c(10001, 10005, 10022) plot(fit1, data, group = ids, what = \"all\") ids <- c(10001, 10005, 10022) plot(fit1, group = ids, hide = \"none\")"},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"objective","dir":"Articles","previous_headings":"","what":"Objective","title":"Check perfect model","text":"general, broken stick model smoothes observed growth trajectory. happens observations already aligned break ages? model perfectly represent data? covariance matrix random effects (\\(\\Omega)\\) equal covariance measurements? \\(\\sigma^2\\) equal zero?","code":""},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"data-generation","dir":"Articles","previous_headings":"","what":"Data generation","title":"Check perfect model","text":"adapt code http://www.davekleinschmidt.com/sst-mixed-effects-simulation/simulations_slides.pdf generate test data: choose perfect situation \\(\\sigma^2 = 0\\) noisy case \\(\\sigma^2 = 1\\) ages align perfectly. wish reproduce correlation matrix among \\(y\\)’s mixed model estimates. target correlation matrix :","code":"library(\"plyr\") library(\"mvtnorm\") make_data_generator <- function(resid_var = 1, ranef_covar = diag(c(1, 1)), n = 100 ) { ni <- nrow(ranef_covar) generate_data <- function() { # sample data set under mixed effects model with random slope/intercepts simulated_data <- rdply(n, { b <- t(rmvnorm(n = 1, sigma = ranef_covar)) epsilon <- rnorm(n = length(b), mean = 0, sd = sqrt(resid_var)) b + epsilon }) data.frame( subject = rep(1:n, each = ni), age = rep(1:ni, n), simulated_data) } } resid_var <- 0 resid_var <- 1 set.seed(77711) covar <- matrix(c(1, 0.7, 0.5, 0.3, 0.7, 1, 0.8, 0.5, 0.5, 0.8, 1, 0.6, 0.3, 0.5, 0.6, 1), nrow = 4) gen_dat <- make_data_generator(n = 10000, ranef_covar = covar, resid_var = resid_var) data <- gen_dat() head(data) ## subject age .n X1 ## 1 1 1 1 -0.9478 ## 2 1 2 1 -2.0837 ## 3 1 3 1 -2.6512 ## 4 1 4 1 -2.5526 ## 5 2 1 2 -0.0825 ## 6 2 2 2 -1.2707 library(\"tidyr\") library(\"dplyr\") ## ## Attaching package: 'dplyr' ## The following objects are masked from 'package:plyr': ## ## arrange, count, desc, failwith, id, mutate, rename, summarise, ## summarize ## The following objects are masked from 'package:stats': ## ## filter, lag ## The following objects are masked from 'package:base': ## ## intersect, setdiff, setequal, union d <- as_tibble(data[,-3]) broad <- t(spread(d, subject, X1))[-1,] cor(broad) ## [,1] [,2] [,3] [,4] ## [1,] 1.000 0.350 0.255 0.161 ## [2,] 0.350 1.000 0.406 0.246 ## [3,] 0.255 0.406 1.000 0.313 ## [4,] 0.161 0.246 0.313 1.000"},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"fit-model","dir":"Articles","previous_headings":"","what":"Fit model","title":"Check perfect model","text":"Fit broken stick model, knots specified ages 1:4.","code":"library(\"brokenstick\") knots <- 1:3 boundary <- c(1, 4) fit <- brokenstick(X1 ~ age | subject, data, knots = knots, boundary = boundary, method = \"lmer\") ## Warning: number of observations (=40000) <= number of random effects (=40000) ## for term (0 + age_1 + age_2 + age_3 + age_4 | subject); the random-effects ## parameters and the residual variance (or scale parameter) are probably ## unidentifiable ## Warning in checkConv(attr(opt, \"derivs\"), opt$par, ctrl = control$checkConv, : ## Model failed to converge with max|grad| = 0.0323545 (tol = 0.002, component 1) omega <- get_omega(fit, hide = \"no\") beta <- coef(fit, hide = \"no\") sigma2 <- fit$sigma2 round(beta, 2) ## age_1 age_2 age_3 age_4 ## -0.02 -0.02 0.01 0.01 round(sigma2, 4) ## [1] 0.818 # correlation random effects round(covar, 3) ## [,1] [,2] [,3] [,4] ## [1,] 1.0 0.7 0.5 0.3 ## [2,] 0.7 1.0 0.8 0.5 ## [3,] 0.5 0.8 1.0 0.6 ## [4,] 0.3 0.5 0.6 1.0 round(omega, 2) ## age_1 age_2 age_3 age_4 ## age_1 1.23 0.71 0.52 0.33 ## age_2 0.71 1.16 0.82 0.49 ## age_3 0.52 0.82 1.22 0.63 ## age_4 0.33 0.49 0.63 1.17 # covariances measured data round(omega + diag(sigma2, 4), 3) ## age_1 age_2 age_3 age_4 ## age_1 2.052 0.706 0.521 0.326 ## age_2 0.706 1.982 0.816 0.489 ## age_3 0.521 0.816 2.034 0.630 ## age_4 0.326 0.489 0.630 1.992 round(cov(broad), 3) ## [,1] [,2] [,3] [,4] ## [1,] 2.052 0.706 0.521 0.326 ## [2,] 0.706 1.982 0.816 0.489 ## [3,] 0.521 0.816 2.034 0.630 ## [4,] 0.326 0.489 0.630 1.992 # convert to time-to-time correlation matrix round(cov2cor(omega + diag(sigma2, 4)), 3) ## age_1 age_2 age_3 age_4 ## age_1 1.000 0.350 0.255 0.161 ## age_2 0.350 1.000 0.406 0.246 ## age_3 0.255 0.406 1.000 0.313 ## age_4 0.161 0.246 0.313 1.000 round(cor(broad), 3) ## [,1] [,2] [,3] [,4] ## [1,] 1.000 0.350 0.255 0.161 ## [2,] 0.350 1.000 0.406 0.246 ## [3,] 0.255 0.406 1.000 0.313 ## [4,] 0.161 0.246 0.313 1.000 z <- predict(fit, x = \"knots\", include_data = FALSE, shape = \"wide\")[, -1] # off-diagonal elements of covariance of broken stick estimates approach correlation # not enough variance in the diagonal because of smoothing cov(z) ## 1 2 3 ## 1 0.795 0.595 0.475 ## 2 0.595 0.791 0.681 ## 3 0.475 0.681 0.821 # correlations of broken stick estimates are inflated because of smoothing cor(z) ## 1 2 3 ## 1 1.000 0.750 0.587 ## 2 0.750 1.000 0.845 ## 3 0.587 0.845 1.000"},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"conclusions","dir":"Articles","previous_headings":"","what":"Conclusions","title":"Check perfect model","text":"\\(\\sigma^2=0\\), -diagonal elements \\(\\Omega\\) reproduce correlations among \\(y\\)’s. estimate \\(\\sigma^2\\) high (0.13 instead 0). \\(\\sigma^2 > 0\\), \\(\\hat C = \\Omega + \\hat\\sigma^2 (n_i)\\) reproduces sample covariance matrix \\(y\\)’s exactly. cov2cor(hatC) reproduces sample time--time correlation matrix. Conclusion: unbiased estimate time--time correlation matrix among (unobserved) measurements knots:","code":"cov <- get_omega(fit) chat <- cov + diag(fit$sigma2, nrow(cov)) r <- cov2cor(chat) r ## age_1 age_2 age_3 ## age_1 1.000 0.350 0.255 ## age_2 0.350 1.000 0.406 ## age_3 0.255 0.406 1.000"},{"path":"https://growthcharts.org/brokenstick/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Stef van Buuren. Author, maintainer.","code":""},{"path":"https://growthcharts.org/brokenstick/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"van Buuren S (2023). “Broken Stick Model Irregular Longitudinal Data.” Journal Statistical Software, 106(7), 1–51. doi:10.18637/jss.v106.i07.","code":"@Article{, title = {Broken Stick Model for Irregular Longitudinal Data}, author = {Stef {van Buuren}}, journal = {Journal of Statistical Software}, year = {2023}, volume = {106}, number = {7}, pages = {1--51}, doi = {10.18637/jss.v106.i07}, }"},{"path":"https://growthcharts.org/brokenstick/index.html","id":"brokenstick","dir":"","previous_headings":"","what":"Broken Stick Model for Irregular Longitudinal Data","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model describes set individual curves linear mixed model using second-order linear B-splines. main use model align irregularly observed data user-specified grid break ages. fitting can done Z-score scale, nonlinearities irregular data can treated separate problems. package contains functions fitting broken stick model data, exporting parameters model independent use outside package, predicting broken stick curves new data.","code":""},{"path":"https://growthcharts.org/brokenstick/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Install brokenstick package CRAN follows: latest version (revision branch) can installed GitHub follows:","code":"install.packages(\"brokenstick\") install.packages(\"remotes\") remotes::install_github(\"growthcharts/brokenstick\")"},{"path":"https://growthcharts.org/brokenstick/index.html","id":"overview","dir":"","previous_headings":"","what":"Overview","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model describes set individual curves linear mixed model using linear B-splines. model can used smooth growth curves series connected straight lines; align irregularly observed curves common age grid; create synthetic curves user-specified set break ages; estimate time--time correlation matrix; predict future observations. user specifies set break ages straight lines connect. individual obtains estimate break age, set estimates individual form smoothed version observed trajectory. main assumptions broken stick model : trajectory break ages follows straight line, generally particular interest; Broken stick estimates follow common multivariate normal distribution; Missing data missing random (MAR); Individuals exchangeable uncorrelated. order conform assumption multivariate normality, user may fit broken stick model suitably transformed data yield standard normal (Z) scale. Unique feature broken stick model : Modular: Issues related non-linearity growth curves observed scale can treated separately, .e., outside broken stick model; Local: given data point contribute estimates corresponding closest break ages; Exportable: broken stick model can exported reused prediction new data alternative computing environments. brokenstick package contains functions Fitting broken stick model data, Plotting individual trajectories, Predicting broken stick estimates new data.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/index.html","id":"background","dir":"","previous_headings":"Resources","what":"Background","title":"Broken Stick Model for Irregular Longitudinal Data","text":"took name broken stick Ruppert, Wand, Carroll (2003), page 59-61, actually much older. far know, de Kroon et al. (2010) first publication uses broken stick model without intercept mixed modelling context. See Terneuzen birth cohort: BMI changes 2 6 years correlate strongest adult overweight. model formally defined extended Flexible Imputation Missing Data (second edition). See van Buuren (2018). evaluation Anderson et al. (2019) concluded: recommend use brokenstick model standardised Z‐score data. Aside accuracy fit, another key advantage brokenstick model easier fit provides easily interpretable estimates child growth trajectories.","code":""},{"path":"https://growthcharts.org/brokenstick/index.html","id":"instructive-materials","dir":"","previous_headings":"Resources","what":"Instructive materials","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Companion site contains vignettes articles explain model use software; Publication: Broken Stick Model Irregular Longitudinal Data doi:10.18637/jss.v106.i07.","code":""},{"path":"https://growthcharts.org/brokenstick/index.html","id":"acknowledgment","dir":"","previous_headings":"Resources","what":"Acknowledgment","title":"Broken Stick Model for Irregular Longitudinal Data","text":"work supported Bill & Melinda Gates Foundation. contents sole responsibility authors may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":null,"dir":"Reference","previous_headings":"","what":"Empirical Bayes predictor for random effects — EB","title":"Empirical Bayes predictor for random effects — EB","text":"function can estimate random effect given set model estimates new user data. unit may new model. methods implements EB estimate (also known BLUP) described Skrondral Rabe-Hasketh, 2009, p. 683. function can also provide broken stick estimate given level, sum global (fixed) individual (random) effects. current implementation provide prediction errors.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Empirical Bayes predictor for random effects — EB","text":"","code":"EB(model, y, X, Z = X, BS = TRUE)"},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Empirical Bayes predictor for random effects — EB","text":"model object class brokenstick. y vector new measurements unit j, scaled metric fitted model. X nj * p matrix fixed effects unit j, typically produced bs(). Z nj * q matrix random effects unit j. default sets Z equal X. BS logical indicating whether broken stick estimates returned (BS = TRUE) random effects (BS = FALSE). default TRUE.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Empirical Bayes predictor for random effects — EB","text":"vector length q containing random effect broken stick estimates unit j.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Empirical Bayes predictor for random effects — EB","text":"Skrondal, ., Rabe-Hesketh, S. (2009). Prediction multilevel generalized linear models. J. R. Statist. Soc. , 172, 3, 659-687.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Empirical Bayes predictor for random effects — EB","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":null,"dir":"Reference","previous_headings":"","what":"Class brokenstick — brokenstick-class","title":"Class brokenstick — brokenstick-class","text":"main fitting function brokenstick() returns object class brokenstick. object collects fitted broken stick model.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Class brokenstick — brokenstick-class","text":"package exports S3 methods brokenstick class following generic functions: coef(), fitted(), model.frame(), model.matrix(), plot(), predict(), print(), residuals() summary(). package exports following helper functions brokenstick objects: get_knots(), get_omega() get_r2(). brokenstick object list following named elements:","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"elements","dir":"Reference","previous_headings":"","what":"Elements","title":"Class brokenstick — brokenstick-class","text":"call Call created object names named list three elements (\"x\", \"y\", \"g\") providing variable name time, outcome subject, respectively. internal Numeric vector internal knots. boundary Numeric vector length 2 boundary knots. degree degree B-spline. See splines::bs(). Support values 0 (step model) 1 (broken stick model). method String, either \"kr\" \"lmer\", identifying fitting model. control List control options returned set_control() used set algorithmic details. beta Numeric vector fixed effect estimates. omega Numeric matrix variance-covariance estimates broken stick estimates. sigma2 Numeric scalar mean residual variance. sample numeric vector descriptives training data. light returned object lighter? light = TRUE returned object contain model settings parameter estimates store sigma2j, sample, data, imp mod elements. light object can used predict broken stick estimates new data, disclose training data small. hide output boundary knots hidden? Can \"right\", \"left\", \"boundary\", \"internal\" \"none\". default \"right\". sigma2j Numeric vector estimates residual variance per group. used method \"kr\". data training data used fit model. imp imputations generated missing outcome data. method = \"kr\". mod method = \"kr\": named list four components, class coda::mcmc. method = \"lmer\": object class lme4::merMod.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Class brokenstick — brokenstick-class","text":"doi:10.18637/jss.v106.i07","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Class brokenstick — brokenstick-class","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":null,"dir":"Reference","previous_headings":"","what":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"broken stick model describes set individual curves linear mixed model using second-order linear B-splines. main use model align irregularly observed data user-specified grid break ages.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"brokenstick package contains functions fitting broken stick model data, predicting broken stick curves new data, plotting results.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"work supported Bill & Melinda Gates Foundation. contents sole responsibility authors may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"brokenstick-functions","dir":"Reference","previous_headings":"","what":"brokenstick functions","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"main functions : following functions user-oriented helpers: following functions perform calculations:","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"van Buuren, S. (2023). Broken Stick Model Irregular Longitudinal Data. Journal Statistical Software, 106(7), 1--51. doi:10.18637/jss.v106.i07 van Buuren, S. (2018). Flexible Imputation Missing Data. Second Edition. Chapman & Hall/CRC. Chapter 11. https://stefvanbuuren.name/fimd/sec-rastering.html#sec:brokenstick","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Fit a brokenstick model to irregular data — brokenstick","title":"Fit a brokenstick model to irregular data — brokenstick","text":"brokenstick() function fits irregularly observed series measurements onto user-specified grid points (knots). model codes grid series linear B-splines. modelled trajectory consists straight lines join chosen knots look like broken stick. Differences observations expressed random effect per knot.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Fit a brokenstick model to irregular data — brokenstick","text":"","code":"brokenstick( formula, data, knots = NULL, boundary = NULL, k = 5L, degree = 1L, method = c(\"kr\", \"lmer\"), control = set_control(method = method, ...), na.action = na.exclude, light = FALSE, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), ... )"},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Fit a brokenstick model to irregular data — brokenstick","text":"formula formula specifying outcome, predictor group variable data. generic shape formula = y ~ x | group. left-hand side outcome, right-hand side predictor, name grouping variable occurs | sign. Formula treatment non-standard: 1) y x numeric, 2) one variable allowed model term (additional variables ignored). data data frame matrix containing outcome (numeric), predictor (numeric) group (numeric, factor, character) variable. knots Optional, recommended. Numerical vector locations internal knots placed values predictor. function sorts internal knots increasing order. boundary Optional, recommended. Numerical vector length 2 left right boundary knot. boundary setting passed splines::bs() Boundary.knots argument. specified, function determines boundary knots range(x). specified, boundary range internally expanded include least range(knots). k Optional, convenience parameter number internal knots. specified, k internal knots placed equidense quantiles predictor. example, specifying k = 1 puts knot 50th quantile (median), setting k = 3 puts knots 25th, 50th 75th quantiles, . user specifies k knots arguments knots takes precedence. default k = 5, user specify knots, boundary k, knots 16th, 33th, 50th, 66th 84th quantile predictor. degree degree spline. broken stick model requires linear splines, default degree = 1. Setting degree = 0 yields (crisp) dummy coding, one column less degree = 1. brokenstick package supports degree = 0 degree = 1. method Estimation method. Either \"kr\" (Kasim-Raudenbush sampler) \"lmer\" (lme4::lmer()). Version 1.1.1.9000 changed default method = \"kr\". control List control options returned set_control() used set algorithmic details. list parameters. specified, functions sets defaults method \"kr\" control_kr(), method \"lmer\" lme4::lmerControl(). ease use, user may set individual options \"kr\" (e.g. niter = 500) via ... arguments. na.action function indicates lme4::lmer() data contain NAs. Default set na.exclude. used method \"lmer\". light returned object lighter? light = TRUE returned object contain model settings parameter estimates store data, imp mod elements. light object can used predict broken stick estimates new data, disclose training data small (often <20 Kb). hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". ... Forwards arguments control_kr().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Fit a brokenstick model to irregular data — brokenstick","text":"object class brokenstick.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Fit a brokenstick model to irregular data — brokenstick","text":"choice method = \"kr\" method = \"lmer\" depends size data complexity model. general, setting method = \"lmer\" can require substantial calculation time complex models (say > 8 internal knots) may converge. Method \"kr\" less sensitive model complexity small samples, added benefit variance-covariance matrix random effects can constrained cormodel argument. hand, \"lmer\" better-researched method, efficient simpler models datasets many rows. default algorithm since version 2.0 Bayesian Kasim-Raudenbush sampler (method = \"kr\"). variance-covariance matrix broken stick estimates absorbs relations time. \"kr\" method allows enforcing simple structure variance-covariance matrix. Currently, three correlation models: \"none\" (default), \"argyle\" \"cole\". Specify seed argument reproducibility. See control_kr() details. alternative method = \"lmer\" fits broken stick model lme4::lmer(). method, variance-covariance matrix can unstructured. estimate may unstable number children small relative number specified knots. default setting lme4::lmerControl() check.nobs.vs.nRE= \"stop\". [set_control()] function changes check.nobs.vs.nRE= \"warning\" default, since otherwise many broken stick models run . method throws warnings estimates stable. can time models many internal knots. Despite warnings, results often look reasonable. Diagnostics coda lme4: function returns object class brokenstick. method = \"kr\" list component named \"mod\" contains list mcmc objects can analysed coda::acfplot(), coda::autocorr(), coda::crosscorr(), coda::cumuplot(), coda::densplot(), coda::effectiveSize(), coda::geweke.plot(), coda::raftery.diag(), coda::traceplot() usual plot() summary() functions. method = \"lmer\" list component named \"mod\" contains object class lme4::merMod. model objects omitted light brokenstick objects.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Fit a brokenstick model to irregular data — brokenstick","text":"Note automatic knot specification data-dependent, may reproduce data. Likewise, knots specified via k data-dependent transfer data sets. Fixing model requires specifying knots boundary.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Fit a brokenstick model to irregular data — brokenstick","text":"","code":"# \\donttest{ data <- smocc_200[1:1198, ] # using kr method, default f1 <- brokenstick(hgt_z ~ age | id, data, knots = 0:2, seed = 123) plot(f1, data, n_plot = 9) # study sampling behaviour of the sigma2 parameter with coda library(\"coda\") plot(f1$mod$sigma2) acfplot(f1$mod$sigma2) # using lmer method f2 <- brokenstick(hgt_z ~ age | id, data, knots = 0:2, method = \"lmer\") plot(f2, data, n_plot = 9) # drill down into merMod object with standard diagnostics in lme4 summary(f2$mod) #> Linear mixed model fit by REML ['lmerMod'] #> Formula: hgt_z ~ 0 + age_0 + age_1 + age_2 + age_2.6776 + (0 + age_0 + #> age_1 + age_2 + age_2.6776 | id) #> Data: data #> Control: control #> #> REML criterion at convergence: 2088.7 #> #> Scaled residuals: #> Min 1Q Median 3Q Max #> -3.8278 -0.5279 0.0025 0.5652 3.4227 #> #> Random effects: #> Groups Name Variance Std.Dev. Corr #> id age_0 1.2929 1.1370 #> age_1 0.6759 0.8221 0.47 #> age_2 0.7082 0.8415 0.45 0.94 #> age_2.6776 3.5673 1.8887 0.45 0.58 0.63 #> Residual 0.1783 0.4222 #> Number of obs: 1185, groups: id, 124 #> #> Fixed effects: #> Estimate Std. Error t value #> age_0 -0.02596 0.10452 -0.248 #> age_1 0.03550 0.07838 0.453 #> age_2 0.05766 0.08689 0.664 #> age_2.6776 0.56284 0.75759 0.743 #> #> Correlation of Fixed Effects: #> age_0 age_1 age_2 #> age_1 0.407 #> age_2 0.394 0.719 #> age_2.6776 0.089 0.167 -0.114 plot(f2$mod) # a model with more knots knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24, 36) / 12, 4) # method kr takes about 2 seconds f3 <- brokenstick(hgt_z ~ age | id, data, knots, seed = 222) plot(f3, data, n_plot = 9) # method lmer takes about 40 seconds f4 <- brokenstick(hgt_z ~ age | id, data, knots, method = \"lmer\") #> Warning: number of observations (=1185) <= number of random effects (=1364) for term (0 + age_0 + age_0.0833 + age_0.1667 + age_0.25 + age_0.5 + age_0.75 + age_1 + age_1.25 + age_1.5 + age_2 + age_3 | id); the random-effects parameters and the residual variance (or scale parameter) are probably unidentifiable #> boundary (singular) fit: see help('isSingular') plot(f4, data, n_plot = 9) # }"},{"path":"https://growthcharts.org/brokenstick/reference/coef.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","title":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","text":"Extract Model Coefficients brokenstick Object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/coef.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","text":"","code":"# S3 method for brokenstick coef( object, complete = TRUE, ..., hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\") )"},{"path":"https://growthcharts.org/brokenstick/reference/coef.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","text":"object brokenstick object complete default (used lm, etc) aov methods: logical indicating full coefficient vector returned also case -determined system coefficients set NA, see also alias. Note default differs lm() aov() results. ... arguments. hide output boundary knots hidden print, summary plot functions? Can \"right\", \"left\", \"boundary\", \"internal\" \"none\". specified, read object$hide.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":null,"dir":"Reference","previous_headings":"","what":"Set controls for Kasim-Raudenbush sampler — control_kr","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"Set controls Kasim-Raudenbush sampler","code":""},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"","code":"control_kr( niter = 200L, nimp = 0L, start = 101L, thin = 1L, seed = NA_integer_, cormodel = c(\"none\", \"argyle\", \"cole\"), ... )"},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"niter Integer. Number samples posterior. Default: 200. nimp Integer. Number multiple imputations. Default: 0. start Integer. iteration number first observation thin Integer. thinning interval consecutive observations seed Integer. Seed number base::set.seed(). Use NA bypass seed setting. cormodel String indicating correlation model: \"none\" (default), \"argyle\" \"cole\" ... Allow dot parameters","code":""},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"list eight components. function calculates parameters end (iteration number last iteration) thin_imp (thinning factor multiple imputations) inputs.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200.html","id":null,"dir":"Reference","previous_headings":"","what":"Broken stick model with nine lines for 200 children — fit_200","title":"Broken stick model with nine lines for 200 children — fit_200","text":"Object fit_200 class brokenstick contains fitted broken stick model, including training data diagnostics.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Broken stick model with nine lines for 200 children — fit_200","text":"object class brokenstick, fitted brokenstick().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Broken stick model with nine lines for 200 children — fit_200","text":"dataset constructed ","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit_200 <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = knots, seed = 1)"},{"path":"https://growthcharts.org/brokenstick/reference/fit_200_light.html","id":null,"dir":"Reference","previous_headings":"","what":"Broken stick model with nine lines for 200 children (light) — fit_200_light","title":"Broken stick model with nine lines for 200 children (light) — fit_200_light","text":"Object fit_200_light class brokenstick stores model settings parameter estimates.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200_light.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Broken stick model with nine lines for 200 children (light) — fit_200_light","text":"object class brokenstick, fitted brokenstick().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200_light.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Broken stick model with nine lines for 200 children (light) — fit_200_light","text":"datasets constructed ","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit_200_light <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = knots, light = TRUE, seed = 1)"},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate fitted values — fitted.brokenstick","title":"Calculate fitted values — fitted.brokenstick","text":"Calculate fitted values","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate fitted values — fitted.brokenstick","text":"","code":"# S3 method for brokenstick fitted(object, newdata = NULL, ...)"},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate fitted values — fitted.brokenstick","text":"object brokenstick object. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... Additional arguments. Ignored.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate fitted values — fitted.brokenstick","text":"numerical vector predictions. number elements equals number rows newdata. newdata specified, function looks training data object element named data.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":null,"dir":"Reference","previous_headings":"","what":"Obtain the knots from a broken stick model — get_knots","title":"Obtain the knots from a broken stick model — get_knots","text":"Obtain knots broken stick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Obtain the knots from a broken stick model — get_knots","text":"","code":"get_knots( object, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), whatknots = \"all\", what = \"all\" )"},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Obtain the knots from a broken stick model — get_knots","text":"object object class brokenstick hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". whatknots Deprecated. Use hide instead. Deprecated. Use hide instead.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Obtain the knots from a broken stick model — get_knots","text":"vector knot locations, either , internal boundary , depending hide. result NULL object proper class. Returns numeric(0) internal knots.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Obtain the knots from a broken stick model — get_knots","text":"","code":"get_knots(fit_200, hide = \"bo\") #> [1] 0.0833 0.1667 0.2500 0.5000 0.7500 1.0000 1.2500 1.5000 2.0000"},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract Variance and Correlation Components — get_omega","title":"Extract Variance and Correlation Components — get_omega","text":"Extracts variance-covariance correlation matrix brokenstick object.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract Variance and Correlation Components — get_omega","text":"","code":"get_omega( x, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), cor = FALSE, whatknots = \"all\", what = \"cov\" )"},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract Variance and Correlation Components — get_omega","text":"x Object class brokenstick hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". cor Logical. function return correlation matrix instead covariance matrix? default FALSE. whatknots Deprecated. Deprecated.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract Variance and Correlation Components — get_omega","text":"numeric matrix, possibly zero rows columns names match","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract Variance and Correlation Components — get_omega","text":"","code":"f1 <- brokenstick(hgt_z ~ age | id, smocc_200[1:1000, ], knots = 0:2, seed = 1) get_omega(f1, cor = TRUE, hide = \"boundary\") #> age_1 age_2 #> age_1 1.0000000 0.9173999 #> age_2 0.9173999 1.0000000"},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":null,"dir":"Reference","previous_headings":"","what":"Obtain proportion of explained variance from a broken stick model — get_r2","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"Obtain proportion explained variance broken stick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"","code":"get_r2(object, newdata = NULL)"},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"object object class brokenstick newdata Data r.squared must calculated","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"Proportion explained variance","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"","code":"get_r2(fit_200) #> [1] 0.9808152 get_r2(fit_200_light, newdata = smocc_200) #> [1] 0.9808152"},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":null,"dir":"Reference","previous_headings":"","what":"Kasim-Raudenbush sampler for two-level normal model — kr","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"Simulates posterior distributions parameters two-level normal model heterogeneous within-cluster variances (Kasim Raudenbush, 1998). Imputations can drawn extra step algorithm.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"","code":"kr(y, x, g, control = control_kr())"},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"y Vector outcome value x Matrix predictor value g Vector group values control list created control_kr() sets algorithmic options sampler correlation model.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"object class kr, basically list components: number rows imp equal number missing values outcome vector y. number columns equals nimp.","code":"* `beta` Fixed effects * `omega` Variance-covariance of random effects * `sigma2_j` Residual variance per group * `sigma2` Average residual variance * `sample` Descriptive statistics about the data * `imp` Numeric matrix with `nimp` multiple imputations. * `mod` A list of objects of class [coda::mcmc()]"},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"speed Kasim-Raudenbush sampler almost independent number random effect, foremost depends total number iterations. defaults start = 100, n = 200 thin = 1 provide 200 parameter draws reasonable approximation variance-covariance matrix random effects. closer approximations 200 draws set control = control_kr(thin = 10) (better) thin = 20 (best), expense linear increase calculation time. Drawing fewer 50 observations recommended, results best treated indicative. possible draw multiple imputations setting nimp parameter. example, draw five imputations missing outcome specify control = control_kr(nimp = 5).","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"Kasim RM, Raudenbush SW. (1998). Application Gibbs sampling nested variance components models heterogeneous within-group variance. Journal Educational Behavioral Statistics, 23(2), 93--116.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"Stef van Buuren, based mice::mice.impute.2l.norm()","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":null,"dir":"Reference","previous_headings":"","what":"Create linear splines basis — make_basis","title":"Create linear splines basis — make_basis","text":"function creates basis function second-order (linear) splines user-specific set break points.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create linear splines basis — make_basis","text":"","code":"make_basis( x, xname = \"x\", internal = NULL, boundary = range(x), degree = 1L, warn = TRUE )"},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create linear splines basis — make_basis","text":"x numeric vector xname predictor name. Default \"x\" internal vector internal knots, excluding boundary knots boundary vector external knots degree degree spline. broken stick model requires linear splines, default degree = 1. Setting degree = 0 yields (crisp) dummy coding, one column less degree = 1. warn logical indicating whether warnings splines::bs() given.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create linear splines basis — make_basis","text":"matrix length(x) rows length(breaks) columns, extra attributes described bs().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Create linear splines basis — make_basis","text":"version 0.54, standard practice knots array always included boundary[1L].","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Create linear splines basis — make_basis","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":null,"dir":"Reference","previous_headings":"","what":"Parse formula for brokenstick model — parse_formula","title":"Parse formula for brokenstick model — parse_formula","text":"bare bones formula parser extract variables names formulas y ~ x | g. return name first variable mentioned formula component.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Parse formula for brokenstick model — parse_formula","text":"","code":"parse_formula(f)"},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Parse formula for brokenstick model — parse_formula","text":"f formula object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Parse formula for brokenstick model — parse_formula","text":"list elements x, y g. element length 1.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Parse formula for brokenstick model — parse_formula","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot observed and fitted trajectories by group — plot.brokenstick","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"plot method brokenstick object plots observed fitted trajectories one groups.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"","code":"# S3 method for brokenstick plot(x, newdata = NULL, ...)"},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"x object class brokenstick. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... Extra arguments passed predict.brokenstick() plot_trajectory().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"object class ggplot2::ggplot.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"default, plot(fit) plot observed fitted data first three groups data. default setting drops fitted value right boundary knot display.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"","code":"if (FALSE) { # fit model on raw hgt with knots at 0, 1, 2 and 3 years fit1 <- brokenstick(hgt ~ age | id, smocc_200, knots = 0:2) gp <- c(10001, 10005, 10022) plot(fit1, group = gp, xlab = \"Age (years)\", ylab = \"Length (cm)\") # fit model on standard deviation score fit2 <- brokenstick(hgt_z ~ age | id, smocc_200, knots = 0:2) plot(fit2, group = gp, xlab = \"Age (years)\", ylab = \"Length (SDS)\") # built-in model with 11 knots plot(fit_200, group = gp, xlab = \"Age (years)\", ylab = \"Length (SDS)\") # black and white version plot(fit_200, group = gp, xlab = \"Age (years)\", ylab = \"Length (SDS)\", color_y = rep(\"black\", 2), shape_y = 1, linetype_y = 3, color_yhat = rep(\"grey20\", 2), shape_yhat = NA) }"},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"Plot observed fitted trajectories fitted brokenstick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"","code":"plot_trajectory( x, newdata = NULL, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), .x = NULL, group = NULL, color_y = c(grDevices::hcl(240, 100, 40, 0.7), grDevices::hcl(240, 100, 40, 0.8)), size_y = 2, linetype_y = 1, shape_y = 19, color_yhat = c(grDevices::hcl(0, 100, 40, 0.7), grDevices::hcl(0, 100, 40, 0.8)), size_yhat = 2, linetype_yhat = 1, shape_yhat = 19, color_imp = c(\"grey80\", \"grey80\"), size_imp = 2, ncol = 3L, xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, show = c(TRUE, TRUE, FALSE), n_plot = 3L, scales = \"fixed\", theme = ggplot2::theme_light(), whatknots = \"droplast\", ... )"},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"x object class brokenstick. newdata data.frame matrix hide Character indicating knots .x x argument predict.brokenstick() function. group vector group identifications color_y character vector two elements specifying symbol line color measured data points size_y Dot size measured data points linetype_y Line type data points shape_y Symbol data points color_yhat character vector two elements specifying symbol line color predicted data points size_yhat Dot size predicted data points linetype_yhat Line type predicted data shape_yhat Symbol predicted data color_imp character vector two elements specifying symbol line color imputed data size_imp Dot size imputed data ncol Number columns plot xlab label x-axis ylab label y-axis xlim Vector length 2 range x-axis ylim Vector length 2 range y-axis show logical vector length 3. Element 1 specifies whether observed data plotted, element 2 specifies whether broken stick plotted, element 3 specifies whether imputations plotted. default c(TRUE, TRUE, FALSE). n_plot integer indicating number individual plots. default 3, plots trajectories first three groups. n_plot safety measure prevent unintended plots entire data set. scales Axis scaling, e.g. \"fixed\", \"free\", theme Plotting theme whatknots Deprecated. ... Extra arguments passed predict.brokenstick().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"object class ggplot","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":null,"dir":"Reference","previous_headings":"","what":"Predict from a brokenstick model — predict.brokenstick","title":"Predict from a brokenstick model — predict.brokenstick","text":"predictions broken stick model coincide group-conditional means random effects. function takes object class brokenstick returns predictions one several formats. user can calculate predictions new persons, .e., persons part fitted model, x y arguments.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Predict from a brokenstick model — predict.brokenstick","text":"","code":"# S3 method for brokenstick predict( object, newdata = NULL, ..., x = NULL, y = NULL, group = NULL, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), shape = c(\"long\", \"wide\", \"vector\"), include_data = TRUE, strip_data = TRUE, whatknots = \"all\" )"},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Predict from a brokenstick model — predict.brokenstick","text":"object brokenstick object. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... used, required extensibility. x Optional. numeric vector values predictor. also special keyword x = \"knots\" replaces x positions knots. y Optional. numeric vector measurements. group vector group identifications hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". shape string: \"long\" (default), \"wide\" \"vector\" specifying shape return value. Note use \"wide\" many unique values x creates unwieldy, large sparse matrix. include_data logical indicating whether observed data object$data newdata included return value. default TRUE. Use include_data = FALSE keep added data points (e.g. knots observed data specified x y). Setting include_data = FALSE useful combination shape = \"wide\" avoid warning Values '.pred' uniquely identified. convenience, special case x = \"knots\" function overwrites include_data FALSE evade observed ages show wide matrix. strip_data Deprecated. Use include_data instead. whatknots Deprecated. Use hide instead.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Predict from a brokenstick model — predict.brokenstick","text":"shape == \"long\" long data.frame predictions. x, y group specified, number rows data frame guaranteed number rows newdata. shape == \"wide\" wide data.frame predictions, one record per group. Note format inefficient observations times vary subjects. shape == \"vector\" vector predicted values, x-values groups. function finds data, throws warnings returns NULL.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Predict from a brokenstick model — predict.brokenstick","text":"function predict() calculates predictions every row newdata. user specifies newdata argument, function sets newdata equal training data (object$data object$light FALSE). light object without newdata argument, function throws warning \"Argument 'newdata' required light brokenstick object.\" returns NULL. possible tailor behaviour predict() x, y group arguments. exactly happens depends arguments specified: user specifies x, y group, function returns - every group newdata - predictions specified x values. method use data newdata. user specifies x y group, function forms hypothetical new group x y values. method uses information newdata, also works light brokenstick object. user specifies group, x y, function searches relevant data newdata limits predictions groups. useful user needs prediction one groups. work light brokenstick object. user specifies x group, y, function create new values x group, search relevant data newdata provide predictions values x groups. user specifies x, y group, function assumes vectors contain additional data top already available newdata. lengths x, y group must match. light brokenstick object, case effectively becomes case 6. See . case 5, now without newdata available. data specified x, y group form data frame. Matching newdata attempted, long group id's different training sample effectively new cases made.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Predict from a brokenstick model — predict.brokenstick","text":"","code":"library(\"dplyr\") #> #> Attaching package: ‘dplyr’ #> The following objects are masked from ‘package:stats’: #> #> filter, lag #> The following objects are masked from ‘package:base’: #> #> intersect, setdiff, setequal, union # -- Data train <- smocc_200[1:1198, ] test <- smocc_200[1199:1940, ] if (FALSE) { # -- Fit model fit <- brokenstick(hgt_z ~ age | id, data = train, knots = 0:2, seed = 1) fit_light <- brokenstick(hgt_z ~ age | id, data = train, knots = 0:2, light = TRUE, seed = 1 ) # -- Predict, standard cases # Use train data, return column with predictions pred <- predict(fit) identical(nrow(train), nrow(pred)) # Predict without newdata, not possible for light object predict(fit_light) # Use test data pred <- predict(fit, newdata = test) identical(nrow(test), nrow(pred)) # Predict, same but using newdata with the light object pred_light <- predict(fit_light, newdata = test) identical(pred, pred_light) # -- Predict, special cases # -- Case 1: x, -y, -group # Case 1: x as \"knots\", standard estimates, train sample (n = 124) z <- predict(fit, x = \"knots\", shape = \"wide\") head(z, 3) # Case 1: x as values, linearly interpolated, train sample (n = 124) z <- predict(fit, x = c(0.5, 1, 1.5), shape = \"wide\", include_data = FALSE) head(z, 3) # Case 1: x as values, linearly interpolated, test sample (n = 76) z <- predict(fit, test, x = c(0.5, 1, 1.5), shape = \"wide\", include_data = FALSE) head(z, 3) # Case 1: x, not possible for light object z <- predict(fit_light, x = \"knots\") # -- Case 2: x, y, -group # Case 2: form one new group with id = 0 predict(fit, x = \"knots\", y = c(1, 1, 0.5, 0), shape = \"wide\") # Case 2: works also for a light object predict(fit_light, x = \"knots\", y = c(1, 1, 0.5, 0), shape = \"wide\") # -- Case 3: -x, -y, group # Case 3: Predict at observed age for subset of groups, training sample pred <- predict(fit, group = c(10001, 10005, 10022)) head(pred, 3) # Case 3: Of course, we cannot do this for light objects pred_light <- predict(fit_light, group = c(10001, 10005, 10022)) # Case 3: We can use another sample. Note there is no child 999 pred <- predict(fit, test, group = c(11045, 11120, 999)) tail(pred, 3) # Case 3: Works also for a light object pred_light <- predict(fit_light, test, group = c(11045, 11120, 999)) identical(pred, pred_light) # -- Case 4: x, -y, group # Case 4: Predict at specified x, only in selected groups, train sample pred <- predict(fit, x = c(0.5, 1, 1.25), group = c(10001, 10005, 10022), include_data = FALSE) pred # Case 4: Same, but include observed data and sort pred_all <- predict(fit, x = c(0.5, 1, 1.25), group = c(10001, 10005, 10022)) %>% dplyr::arrange(id, age) # Case 4: Applies also to test sample pred <- predict(fit, test, x = c(0.5, 1, 1.25), group = c(11045, 11120, 999), include_data = FALSE) pred # Case 4: Works also with light object pred_light <- predict(fit_light, test, x = c(0.5, 1, 1.25), group = c(11045, 11120, 999), include_data = FALSE) identical(pred_light, pred) # -- Case 5: x, y, group # Case 5: Add new data to training sample, and refreshes broken stick # estimate at age x. # Note that novel child (not in train) 999 has one data point predict(fit, x = c(0.9, 0.9, 0.9), y = c(1, 1, 1), group = c(10001, 10005, 999), include_data = FALSE) # Case 5: Same, but now for test sample. Novel child 899 has two data points predict(fit, test, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899), include_data = FALSE) # Case 5: Also works for light object predict(fit_light, test, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899), include_data = FALSE) # -- Case 6: As Case 5, but without previous data # Case 6: Same call as last, but now without newdata = test # All children are de facto novel as they do not occur in the training # or test samples. # Note: Predictions for 11045 and 11120 differ from prediction in Case 5. predict(fit, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899)) # This also work for the light brokenstick object predict(fit_light, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899)) }"},{"path":"https://growthcharts.org/brokenstick/reference/print.html","id":null,"dir":"Reference","previous_headings":"","what":"Print brokenstick object — print.brokenstick","title":"Print brokenstick object — print.brokenstick","text":"Print brokenstick object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/print.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Print brokenstick object — print.brokenstick","text":"","code":"# S3 method for brokenstick print( x, digits = getOption(\"digits\"), ..., hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\") )"},{"path":"https://growthcharts.org/brokenstick/reference/print.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Print brokenstick object — print.brokenstick","text":"x brokenstick object digits minimal number significant digits, see print.default. ... arguments passed methods. hide output boundary knots hidden print, summary plot functions? Can \"right\", \"left\",\"boundary\", \"internal\" \"none\". specified, read field x$hide.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract residuals from brokenstick model — residuals.brokenstick","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"Extract residuals brokenstick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"","code":"# S3 method for brokenstick residuals(object, newdata = NULL, ...)"},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"object brokenstick object. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... Additional arguments. Ignored.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"numerical vector residuals number elements equals number rows newdata. newdata specified, function looks training data object element named data.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":null,"dir":"Reference","previous_headings":"","what":"Set controls to steer calculations — set_control","title":"Set controls to steer calculations — set_control","text":"Set controls steer calculations","code":""},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set controls to steer calculations — set_control","text":"","code":"set_control( method = c(\"kr\", \"lmer\"), kr = control_kr(...), lmer = lmerControl(check.nobs.vs.nRE = \"warning\"), ... )"},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set controls to steer calculations — set_control","text":"method String indicating estimation method: \"kr\" \"lmer\" kr list generated control_kr. lmer list generated lme4::lmerControl. default set lmerControl(check.nobs.vs.nRE = \"warning\"), turns fatal errors respect number parameters warnings. Use lmerControl(check.nobs.vs.nRE = \"ignore\") silence lmer(). ... Forwards arguments control_kr()","code":""},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set controls to steer calculations — set_control","text":"method \"kr\", list returned control_kr(). method \"lmer\", object class lmerControl. methods, set_control() returns NULL.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set controls to steer calculations — set_control","text":"","code":"# defaults control <- set_control() control #> $niter #> [1] 200 #> #> $nimp #> [1] 0 #> #> $start #> [1] 101 #> #> $end #> [1] 301 #> #> $thin #> [1] 1 #> #> $thin_imp #> [1] Inf #> #> $seed #> [1] NA #> #> $cormodel #> [1] \"none\" #>"},{"path":"https://growthcharts.org/brokenstick/reference/smocc_200.html","id":null,"dir":"Reference","previous_headings":"","what":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","title":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","text":"Longitudinal height weight measurements ages 0-2 years representative sample 1933 Dutch children born 1988-1989. dataset smocc_200 sample size 200 full data.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/smocc_200.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","text":"tibble 1942 rows 7 columns: id ID, unique id child (numeric) age Decimal age, 0-2.68 years (numeric) sex Sex, \"male\" \"female\" (character) ga Gestational age, completed weeks (numeric) bw Birth weight grammes (numeric) hgt Height measurement cm (numeric) hgt_z Height SDS relative Fourth Dutch Growth Study 1997 (numeric)","code":""},{"path":"https://growthcharts.org/brokenstick/reference/smocc_200.html","id":"source","dir":"Reference","previous_headings":"","what":"Source","title":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","text":"Herngreen WP, van Buuren S, van Wieringen JC, Reerink JD, Verloove-Vanhorick SP & Ruys JH (1994). Growth length weight birth 2 years representative sample Netherlands children (born 1988-89) related socio-economic status background characteristics. Annals Human Biology, 21, 449-463.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/summary.html","id":null,"dir":"Reference","previous_headings":"","what":"Create summary of brokenstick object — summary.brokenstick","title":"Create summary of brokenstick object — summary.brokenstick","text":"Create summary brokenstick object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/summary.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create summary of brokenstick object — summary.brokenstick","text":"","code":"# S3 method for brokenstick summary( object, ..., cor = FALSE, lower = TRUE, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\") )"},{"path":"https://growthcharts.org/brokenstick/reference/summary.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create summary of brokenstick object — summary.brokenstick","text":"object brokenstick object ... additional arguments affecting summary produced. cor Logical. function return correlation matrix instead covariance matrix? default FALSE. lower Logical. Print lower triangle correlation/covariance matrix? hide output boundary knots hidden print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". specified, read field object$hide.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":null,"dir":"Reference","previous_headings":"","what":"Weight loss self-measurement data — weightloss","title":"Weight loss self-measurement data — weightloss","text":"Longitudinal weight measurements 12 individuals 63 daily measurement three conditions.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Weight loss self-measurement data — weightloss","text":"data.frame 695 rows 6 columns: subject ID, consecutive person number 1-12 (integer) day Measurement day, 0-62 (integer) sex Sex, 1 = male, 0 = female (integer) week Week number, 1-9 (integer) condition Condition (control, diet, activity) (factor) body_weight Body weight kg (numeric)","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":"source","dir":"Reference","previous_headings":"","what":"Source","title":"Weight loss self-measurement data — weightloss","text":"Krone T, Boessen R, Bijlsma S, van Stokkum R, Clabbers NDS, Pasman WJ (2020). possibilities use N--1 --trials nutritional research. PloS ONE, 15, 5, e0232680.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Weight loss self-measurement data — weightloss","text":"Constructed file pone.0232680.s001.csv. renumbered subject consecutive integers 1-2 (paper), corrected error condition variable subjects 4 12 match paper's Figure 4, filtered records ones woth observed body_weight variable.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-250","dir":"Changelog","previous_headings":"","what":"brokenstick 2.5.0","title":"brokenstick 2.5.0","text":"Updates manual vignette conform accepted JSS manuscript (March 2023) Updates documentation CRAN release Adds doi:10.18637/jss.v106.i07 forthcoming JSS paper DESCRIPTION documentation","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-240","dir":"Changelog","previous_headings":"","what":"brokenstick 2.4.0","title":"brokenstick 2.4.0","text":"CRAN release: 2022-10-30","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"major-changes-2-4-0","dir":"Changelog","previous_headings":"","what":"Major changes:","title":"brokenstick 2.4.0","text":"Update JSS manuscript version dated 30-10-2022 Hiding knots now convenient automatic setting hide entry brokenstick object. replaces whatknots argument.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"minor-changes-2-4-0","dir":"Changelog","previous_headings":"","what":"Minor changes:","title":"brokenstick 2.4.0","text":"Adds hide field brokenstick object Adds hide arguments coef.brokenstick(), summary.brokenstick(), plot(), get_knots() get_omega Adds cor lower arguments summary.brokenstick() Replaces argument get_omega() cor Deprecates whatknots argument plot(), get_knots() get_omega() Separates summary() print() functionality Updates smocc_200 fit_200 objects Updates roxygen 7.2.1 Replace hard-coded variable name hgt_z dynamic name (#8)","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-230","dir":"Changelog","previous_headings":"","what":"brokenstick 2.3.0","title":"brokenstick 2.3.0","text":"CRAN release: 2022-09-07 Replaces argument get_knots() whatknots Adds support whatknots get_omega() Extends capabilities plot_trajectory() shape linetype options Adds example plot.brokenstick() create decent black white figure trajectories Replaces knots = 0:3 knots = 0:2 examples Updates perfectmodel vignette","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"major-changes-2-2-0","dir":"Changelog","previous_headings":"","what":"Major changes:","title":"brokenstick 2.2.0","text":"Changes default number knots brokenstick() 5. former default produced solution without internal knots. new default produces generally informative starting model user specify knots (using knots = c(..., ...)) number knots (using k = ...). Replaces strip_data argument predict() intuitive include_data argument. default, observed data now included predictions, similar predict.lm(). Turns error Argument 'newdata' required light brokenstick object. brokenstick() warning returns NULL. Updates vignette Broken Stick Model Irregular Longitudinal Data sync revision JSS.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"minor-changes-2-2-0","dir":"Changelog","previous_headings":"","what":"Minor changes:","title":"brokenstick 2.2.0","text":"Expression predict(fit_200_light, x = \"knots\") now produces warning message instead crashing Updates objects fit_200 fit_200_light use automatic boundary (2.68y) instead 3 yrs Automatically sorts user-specified values knots increasing order evade problems predict()","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-210","dir":"Changelog","previous_headings":"","what":"brokenstick 2.1.0","title":"brokenstick 2.1.0","text":"CRAN release: 2022-03-30","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"incorporate-changes-and-updates-required-by-jss-2-1-0","dir":"Changelog","previous_headings":"","what":"Incorporate changes and updates required by JSS","title":"brokenstick 2.1.0","text":"Reorganises vignettes Renames brokenstick-article.Rmd manual/manual.Rmd, include high-res version site take package save space Updates vignettes/bibliography.bib title case Removes superfluous navigation vigettes Defines model.frame.brokenstick() function adheres conventions Changes return values fitted() residuals() vectors Defines less verbose print.brokenstick() helper Make calls library() character argument Removes library(lme4) code evade changing search path","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-202","dir":"Changelog","previous_headings":"","what":"brokenstick 2.0.2","title":"brokenstick 2.0.2","text":"Shrinks size brokenstick object removing formula list element","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-201","dir":"Changelog","previous_headings":"","what":"brokenstick 2.0.1","title":"brokenstick 2.0.1","text":"Shrinks size light objects removing sigma2j vector light brokenstick class","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-200","dir":"Changelog","previous_headings":"","what":"brokenstick 2.0.0","title":"brokenstick 2.0.0","text":"CRAN release: 2021-11-11","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"main-changes-2-0-0","dir":"Changelog","previous_headings":"","what":"Main changes","title":"brokenstick 2.0.0","text":"Function brokenstick() version 2.0.0 sets Kasim-Raudenbush sampler default method. former method lme4::lmer() remains available setting method = \"lmer\" argument. Version 2.0.0 adopts variable names coda package (e.g., start, end, thin, niter, ) stores results Kasim-Raudenbush sampler objects class mcmc. method = \"kr\" one may now inspect solution sampler standard functions coda package. method = \"lmer\" can apply functions lme4 package merMod objects. Version 2.0.0 redefines brokenstick class. New entries include call, formula, internal, sample, light, data, imp mod. Removed entries knots (renamed internal) draws (renamed imp). may omit newdata argument training data. Setting light = TRUE creates small version brokenstick object. Objects class brokenstick backwards compatible, one regenerate objects class brokenstick order use newer features 2.0.0. Version 2.0.0 conforms classic model fitting interface R. Renames new_data argument newdata conform predict.lm(). Methods plot() predict() longer require newdata argument. special cases predict() updated explained documentation examples. Version 2.0.0 adds methods coef(), fitted(), model.frame(), model.matrix(), print() summary brokenstick object. Simplifies algorithmic control. Renames control_brokenstick() set_control() removes layer control list.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"minor-changes-2-0-0","dir":"Changelog","previous_headings":"","what":"Minor changes","title":"brokenstick 2.0.0","text":"Stabilises rgamma() calls KR-algorithm edge cases. predict_brokenstick() can now work (internal) training (external) test data. Removes superfluous type argument predict.brokenstick() Adds function get_omega() extract variance-covariance matrix broken stick estimates Adds choice \"dropfirst\" get_knots() Improves error messages edge cases test-brokenstick_edge.R Perform stricter tests arguments brokenstick() Introduces argument warn_splines make_basis() suppress uninteresting warns splines::bs() Removes superfluous knotnames argument make_basis() Argument x make_basis() now vector instead column vector Introduces new xname argument make_basis() set xname","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-111","dir":"Changelog","previous_headings":"","what":"brokenstick 1.1.1","title":"brokenstick 1.1.1","text":"Handles edge case crashed predict()","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-110","dir":"Changelog","previous_headings":"","what":"brokenstick 1.1.0","title":"brokenstick 1.1.0","text":"CRAN release: 2020-11-02 version adds couple minor alterations. Updates cran-comments Adds link JSS manuscript description field Removes unnecessary \\dontrun{} directives Exports parse_formula() remove ::: examples Sanitises chunk names removing : _ characters Corrects “first-order” mindo’s “second-order” Repairs plotting glitch oldfriends.Rmd Limits number printed rows predict.brokenstick() example","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-100","dir":"Changelog","previous_headings":"","what":"brokenstick 1.0.0","title":"brokenstick 1.0.0","text":"Ready CRAN –> Move version 1.0.0 package now hosted https://github.com/growthcharts/brokenstick/","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0780","dir":"Changelog","previous_headings":"","what":"brokenstick 0.78.0","title":"brokenstick 0.78.0","text":"Prepare package first CRAN submission","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0770","dir":"Changelog","previous_headings":"","what":"brokenstick 0.77.0","title":"brokenstick 0.77.0","text":"Add documentation brokenstick class object Add JSS manuscript vignette Remove prediction vignette dependencies Extend plot.brokenstick() ability plot imputed trajectories Add weightloss data Fail early user specifies degree > 1","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0760","dir":"Changelog","previous_headings":"","what":"brokenstick 0.76.0","title":"brokenstick 0.76.0","text":"Adds argument plot.brokenstick() Solves bug always yielded zero rows case 3 prediction Solves data combination problem predict() group variable factor Add better explanation boundary parameter Evades model.matrix() removes rows NA degree = 0","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0750","dir":"Changelog","previous_headings":"","what":"brokenstick 0.75.0","title":"brokenstick 0.75.0","text":"version trims package various ways Removes dependencies hardhat recipes Makes brokenstick object smaller since blueprints stored Removes recipe interface brokenstick() function Moves ggplot2 suggests Copies install..demand() function mice","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0721","dir":"Changelog","previous_headings":"","what":"brokenstick 0.72.1","title":"brokenstick 0.72.1","text":"Imports recipes::recipe() inform R package installation process","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0720","dir":"Changelog","previous_headings":"","what":"brokenstick 0.72.0","title":"brokenstick 0.72.0","text":"Adds badges, resources references README Updates license Updates CITATION","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0710","dir":"Changelog","previous_headings":"","what":"brokenstick 0.71.0","title":"brokenstick 0.71.0","text":"Removes dependency growthstandards Updates corrects plot examples Tries evade ggplot2 --range/missing messages better filtering","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0701","dir":"Changelog","previous_headings":"","what":"brokenstick 0.70.1","title":"brokenstick 0.70.1","text":"Adds support brokenstick model degree = 0","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0700","dir":"Changelog","previous_headings":"","what":"brokenstick 0.70.0","title":"brokenstick 0.70.0","text":"version jump illustrates big breaking changes: brokenstick adopted tidymodels philosophy, now includes dependency hardhat. now possible fit model using five different interfaces. need anymore hardcode variable names source data. version introduces new estimation method, Kasim-Raudenbush sampler. new method flexible faster lme4::lmer() number knots large. version introduces two simple correlation models may used smooth variance-covariance matrix random effects. definition brokenstick class changed. Objects class brokenstick longer store training data. brokenstick_export class retired. predict() function fully rewritten now new interface. Since brokenstick class store training data anymore, predict() function now obtains new_data argument. Syntax worked brokenstick package 0.70.0 work anymore updated. shape argument replaces output argument. plot() function rewritten, now requires new_data specification. Retired functions: brokenstick() replaces fit_brokenstick(), predict.brokenstick() replaces predict.brokenstick_export(), get_r2() replaces get_pev() Removed functions: get_data(), get_X(), export()","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0620","dir":"Changelog","previous_headings":"","what":"brokenstick 0.62.0","title":"brokenstick 0.62.0","text":"version simplifies plotting functions Renders ggplot objects sharper vignettes svglite Drops pkg argument plot.brokenstick() Lessens dependency rbokeh Replaces hbgd (longer developed) growthstandards package Replaces smocc_50/fit_50 smocc_200/fit_200 Added NEWS.md file track changes package","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0610","dir":"Changelog","previous_headings":"","what":"brokenstick 0.61.0","title":"brokenstick 0.61.0","text":"Added smocc_50 fit_50 demo data Removed smocc.hgtwgt, smocc_hgtwgt fit_206 datasets Adapt code vignettes reflect replacement demo data","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0600","dir":"Changelog","previous_headings":"","what":"brokenstick 0.60.0","title":"brokenstick 0.60.0","text":"Adapted source R 4.0.0.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-055","dir":"Changelog","previous_headings":"","what":"brokenstick 0.55","title":"brokenstick 0.55","text":"Added new utility function get_pev() proportion explained variance get_knots() gets argument Now using smarter defaults plot() Simplified arguments plot() Simplified vignette “Overview main functions”","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-054","dir":"Changelog","previous_headings":"","what":"brokenstick 0.54","title":"brokenstick 0.54","text":"Added Support ggplot2 Made ggplot2 plot default Changed default show_references flag FALSE","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-053","dir":"Changelog","previous_headings":"","what":"brokenstick 0.53","title":"brokenstick 0.53","text":"version announced invited lecture 7th Channel Network Conference, Hasselt, Belgium. abstract lecture: Broken stick model individual growth curves Stef van Buuren Netherlands Organization Applied Scientific Research TNO Utrecht University broken stick model describes set individual curves linear mixed model using second-order linear B-splines. model can used smooth growth curves series connected straight lines; align irregularly observed curves common age grid; create synthetic curves user-specified set break ages; estimate time--time correlation matrix; predict future observations. user specifies set break ages straight lines connect. individual obtains estimate break age, set estimates individual form smoothed version observed trajectory. main assumptions broken stick model development break ages follows straight line, broken stick estimates follow common multivariate normal distribution. order conform assumption multivariate normality, user may fit broken stick model suitably transformed data yield standard normal (Z-score) scale. lecture outlines model introduces brokenstick R package.","code":""}] +[{"path":"https://growthcharts.org/brokenstick/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2023 brokenstick Stef van Buuren Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"what-is-the-broken-stick-model","dir":"Articles","previous_headings":"","what":"What is the broken stick model?","title":"Getting started","text":"broken stick model describes set individual curves linear mixed model using second-order linear B-splines. model can used smooth growth curves series connected straight lines; align irregularly observed curves common age grid; create synthetic curves user-specified set break ages; estimate time--time correlation matrix; predict future observations. user specifies set break ages straight lines connect. individual obtains estimate break age, set estimates individual form smoothed version observed trajectory.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"what-are-the-main-model-assumptions","dir":"Articles","previous_headings":"","what":"What are the main model assumptions?","title":"Getting started","text":"main assumptions broken stick model : development break ages follows straight line; Broken stick estimates follow common multivariate normal distribution; order conform assumption multivariate normality, user may fit broken stick model suitably transformed data yield standard normal (\\(Z\\)) scale.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"why-should-i-want-to-use-the-broken-stick-model","dir":"Articles","previous_headings":"","what":"Why should I want to use the broken stick model?","title":"Getting started","text":"Three unique features broken stick model : Modular: Issues related nonlinearities growth curves observed scale can treated separately, .e., outside broken stick model; Local: given data point contribute estimates corresponding closest break ages; Exportable: broken stick model can exported reused prediction new data alternative computing environments.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"what-is-in-the-package","dir":"Articles","previous_headings":"","what":"What is in the package?","title":"Getting started","text":"brokenstick package contains functions fit, predict plot data. See reference page overview.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/brokenstick.html","id":"acknowledgment","dir":"Articles","previous_headings":"What is in the package?","what":"Acknowledgment","title":"Getting started","text":"work supported Bill & Melinda Gates Foundation. contents sole responsibility authors may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"objective","dir":"Articles","previous_headings":"","what":"Objective","title":"Overview of main functions","text":"vignette demonstrates three major functions brokenstick package: brokenstick(), predict() plot(). also need dplyr ggplot2. elaborate documentation, see manual.","code":"require(\"brokenstick\") require(\"dplyr\") require(\"ggplot2\")"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"plot-trajectories","dir":"Articles","previous_headings":"","what":"Plot trajectories","title":"Overview of main functions","text":"smocc_200 data brokenstick package contain heights 200 Dutch children measured 10 visits ages 0-2 years. Figure 1 dispays data first 500 rows set growth curves Dutch children. Curves steeper first months, child growth faster young infants. Note also cross-overs first half year, whereas fewer occur later. means relative positions settled age 2 years, - put differently - correlation time points ages high. Figure 2 dispays data, vertical axis changed Standard Deviation Scores (SDS), \\(Z\\)-score. \\(Z\\)-score height corrected age relative Dutch height reference Fourth Dutch Growth Study. \\(Z\\)-score transformation takes away major time trend, curves less flat. allows us see detailed assessment individual growth. plots also show measurements clustered around ten ages: birth, 1, 2, 3, 6, 9, 12, 15, 18 24 months. design followed rigorously study, variation timing inevitable weekends, holidays, sickness, events. timing variation poses problem directly compare measurement different children (especially figure 1). Also, easily construct “broad” matrix 10 time point per child. course, can divide time axis ten age groups, treat point within age group measured point. probably good strategy nicely looking data - -, approach problematic data irregular time intervals, multiple measurement per age group, measurement schedules vary child, data combined studies employed different designs. brokenstick package contains tools approximate observed data series connecting straight lines. lines closely follow data, may replace trajectory values breakpoints. statistical analysis can done regularised trajectories, easier working observed data.","code":"data <- brokenstick::smocc_200 head(data, 3) ## # A tibble: 3 × 7 ## id age sex ga bw hgt hgt_z ## ## 1 10001 0 female 40 3960 52 0.575 ## 2 10001 0.0821 female 40 3960 55.6 0.888 ## 3 10001 0.159 female 40 3960 58.2 0.797 ggplot(data[1:500, ], aes(x = age, y = hgt_z, group = id, color = as.factor(id))) + geom_line(size = 0.1) + geom_point(size = 0.7) + scale_colour_viridis_d(option = \"cividis\") + xlab(\"Age (years)\") + ylab(\"Length SDS\") + theme_light() + theme(legend.position = \"none\")"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"fit-broken-stick-model-with-one-line","dir":"Articles","previous_headings":"","what":"Fit broken stick model with one line","title":"Overview of main functions","text":"fit trivial broken stick model just one line ages birth two years, plot trajectories three selected children follows: following plot displays data, standardised units increase analytic resolution: Note approximations describe individual trend data, address systematic deviations trend.","code":"set.seed(123) fit <- brokenstick(hgt ~ age | id, data, knots = c(0, 2)) ids <- c(10001, 10005, 10022) plot(fit, group = ids, xlab = \"Age (years)\", ylab = \"Length (cm)\") fit0 <- brokenstick(hgt_z ~ age | id, data, knots = c(0, 2)) plot(fit0, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\")"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"fit-broken-stick-model-with-two-lines","dir":"Articles","previous_headings":"","what":"Fit broken stick model with two lines","title":"Overview of main functions","text":"broken stick model describes trajectory series connected straight lines. first calculate model two connected lines. first line starts birth end age exactly 1 years. second line spans period 1 2 years. addition, lines must connect age 1 year. estimate plot model follows: plot shows two-line model still fairly crude. fit2 object holds parameter estimates model: console output lists knots model, including left right boundary knots 0 2.6776. row means correspond fixed effect estimates linear mixed model. may interpret global means. Next, output lists variance-covariance matrix random effects. model contains 16 parameters total: four fixed effects (means), four random effects (diagonal elements), 6 covariance (-diagonal elements) 2 error variances (one residual error variance, one variability error per cluster). parameters enough reconstruct broken stick model, apply new data.","code":"fit2 <- brokenstick(hgt_z ~ age | id, data = data, knots = c(0, 1, 2)) plot(fit2, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\") summary(fit2) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 16 (total), 4 (fixed), 4 (variance), 6 (covariance), 2 (error) ## Knots 0 1 2 ## Means -0.0394 0.0278 0.0646 ## Residuals 0.113 0.146 0.168 0.195 0.383 (min, P25, P50, P75, max) ## Mean resid 0.179 ## R-squared 0.867 ## ## Variance-covariance matrix ## age_0 age_1 age_2 ## age_0 1.218 ## age_1 0.481 0.823 ## age_2 0.485 0.782 0.884"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"extend-to-nine-lines","dir":"Articles","previous_headings":"","what":"Extend to nine lines","title":"Overview of main functions","text":"refine model first two years adding knot age visit scheduled. model can run optimization problem difficult, takes slightly longer run. results nine-line model summarises data 79 parameters. model fits substantially better. model residuals substantially smaller (0.075 instead 0.179) proportions explained variance much higher (0.983 instead 0.867). figure shows nine-line broken stick model fits observed data well.","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit9 <- brokenstick(hgt_z ~ age | id, data = data, knots = knots) summary(fit9) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 79 (total), 11 (fixed), 11 (variance), 55 (covariance), 2 (error) ## Knots 0.0000 0.0833 0.1667 0.2500 0.5000 0.7500 1.0000 1.2500 1.5000 2.0000 ## Means -0.18618 0.02163 0.00262 0.06602 0.06346 -0.01955 0.00781 0.03233 -0.02665 0.11470 ## Residuals 0.0176 0.0268 0.0329 0.0494 4.5190 (min, P25, P50, P75, max) ## Mean resid 0.0752 ## R-squared 0.983 ## ## Variance-covariance matrix ## age_0 age_0.0833 age_0.1667 age_0.25 age_0.5 age_0.75 age_1 age_1.25 ## age_0 1.740 ## age_0.0833 1.118 1.337 ## age_0.1667 1.077 1.095 1.246 ## age_0.25 0.900 1.005 0.999 1.052 ## age_0.5 0.627 0.821 0.822 0.815 0.943 ## age_0.75 0.597 0.696 0.693 0.718 0.867 0.938 ## age_1 0.495 0.611 0.579 0.606 0.786 0.819 0.869 ## age_1.25 0.432 0.614 0.575 0.601 0.757 0.807 0.834 0.953 ## age_1.5 0.455 0.614 0.624 0.604 0.808 0.824 0.836 0.914 ## age_2 0.361 0.483 0.517 0.539 0.720 0.753 0.783 0.883 ## age_1.5 age_2 ## age_0 ## age_0.0833 ## age_0.1667 ## age_0.25 ## age_0.5 ## age_0.75 ## age_1 ## age_1.25 ## age_1.5 1.039 ## age_2 0.919 1.06"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"obtain-predicted-values","dir":"Articles","previous_headings":"","what":"Obtain predicted values","title":"Overview of main functions","text":"predict() function allows us obtain various types predictions broken stick model. simplest call produces tibble one column called .pred row data. can bind column .pred data processing. Sometimes, also want prediction knot values, example, create graphs contain observed modelled trajectories. obtain predictions knots special x = \"knots\" argument, e.g. use include_data = FALSE argument remove predictions observed data. output verbose includes grid knots child (id, age). column .source equal added rows non-observed data. Note also knots ages 0.00 2.68 years. boundary knots, added brokenstick() function. boundary knots effectively filter observations enter calculations. default, boundary knots span age range data. technical reasons, broken stick model also defines estimates parameters knots, may general ignored, especially data near boundary knots sparse. wish obtain estimates knots observed data use: return 1942 rows data 800 rows knots.","code":"p1 <- predict(fit2) head(p1) ## .pred ## 1 0.720 ## 2 0.660 ## 3 0.604 ## 4 0.534 ## 5 0.352 ## 6 0.171 identical(nrow(data), nrow(p1)) ## [1] TRUE p2 <- predict(fit2, x = \"knots\", include_data = FALSE) head(p2) ## .source id age sex ga bw hgt hgt_z .pred ## 1 added 10001 0 NA NA NA NA 0.71989 ## 2 added 10001 1 NA NA NA NA -0.00939 ## 3 added 10001 2 NA NA NA NA 0.05785 ## 4 added 10002 0 NA NA NA NA -0.23264 ## 5 added 10002 1 NA NA NA NA -0.37772 ## 6 added 10002 2 NA NA NA NA -0.50233 nrow(p2) ## [1] 600 p3 <- predict(fit2, x = \"knots\", hide = \"none\") table(p3$.source) ## ## added data ## 800 1942"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"explained-variance","dir":"Articles","previous_headings":"","what":"Explained variance","title":"Overview of main functions","text":"proportion variance outcome explained two-line model second model get nine-line broken stick model explains 98 percent variance height SDS.","code":"get_r2(fit2) ## [1] 0.867 get_r2(fit9) ## [1] 0.983"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"subject-level-analysis","dir":"Articles","previous_headings":"","what":"Subject level analysis","title":"Overview of main functions","text":"Suppose interest knowing effect sex, gestational age birth weight height SDS age 2 years. analysis subject level. Let us first extract subject-level data variables vary subjects . also need outcome variable. take broken stick estimates nine line solution append subject level data. names columns bs correspond knot values. effect subject’s sex, gestational age birth weight height SDS age 2 years (denoted variable named 2) can estimated Note analysis shows substantial effect birth weight. course, might birth weight directly related height age 2 years. Alternatively, relation mediated birth length. following model adds birth length (variable named 0) model: effect birth length length age 2 strong. separate effect birth weight anymore, analysis suggests relation birth weight length age 2 can explained mutual associations birth length.","code":"subj <- data %>% select(id, sex, ga, bw) %>% group_by(id) %>% slice(1) head(subj, 3) ## # A tibble: 3 × 4 ## # Groups: id [3] ## id sex ga bw ## ## 1 10001 female 40 3960 ## 2 10002 male 38 3210 ## 3 10003 female 40 4170 bs <- predict(fit9, x = \"knots\", shape = \"wide\", include_data = FALSE) data <- bind_cols(subj, select(bs, -id)) head(data, 3) ## # A tibble: 3 × 14 ## # Groups: id [3] ## id sex ga bw `0` `0.0833` `0.1667` `0.25` `0.5` `0.75` `1` ## ## 1 10001 female 40 3960 0.569 0.865 0.735 0.657 0.232 -0.172 0.118 ## 2 10002 male 38 3210 -0.184 -0.329 -0.252 -0.319 -0.218 -0.281 -0.344 ## 3 10003 female 40 4170 1.17 2.11 1.97 2.04 2.03 1.81 1.32 ## # … with 3 more variables: `1.25` , `1.5` , `2` fit1_lm <- lm(`2` ~ sex + ga + I(bw / 1000), data = data) summary(fit1_lm) ## ## Call: ## lm(formula = `2` ~ sex + ga + I(bw/1000), data = data) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.8965 -0.4525 0.0817 0.6424 2.0369 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 1.0361 1.4705 0.70 0.48187 ## sexmale 0.0109 0.1285 0.08 0.93249 ## ga -0.0700 0.0433 -1.62 0.10752 ## I(bw/1000) 0.5343 0.1420 3.76 0.00022 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.879 on 196 degrees of freedom ## Multiple R-squared: 0.0757, Adjusted R-squared: 0.0616 ## F-statistic: 5.35 on 3 and 196 DF, p-value: 0.00145 fit2_lm <- lm(`2` ~ sex + ga + I(bw / 1000) + `0`, data = data) summary(fit2_lm) ## ## Call: ## lm(formula = `2` ~ sex + ga + I(bw/1000) + `0`, data = data) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.9375 -0.5326 0.0426 0.6292 1.8792 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 3.226719 1.662005 1.94 0.0536 . ## sexmale -0.000703 0.126542 -0.01 0.9956 ## ga -0.089472 0.043247 -2.07 0.0399 * ## I(bw/1000) 0.143924 0.201777 0.71 0.4765 ## `0` 0.245522 0.091492 2.68 0.0079 ** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.865 on 195 degrees of freedom ## Multiple R-squared: 0.109, Adjusted R-squared: 0.0904 ## F-statistic: 5.94 on 4 and 195 DF, p-value: 0.000156"},{"path":"https://growthcharts.org/brokenstick/articles/mainfunctions.html","id":"conclusion","dir":"Articles","previous_headings":"","what":"Conclusion","title":"Overview of main functions","text":"vignette illustrated use brokenstick(), plot() predict() functions. vignettes highlight various capabilities package.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"abstract","dir":"Articles > Manual","previous_headings":"","what":"Abstract","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Many longitudinal studies collect data irregular observation times, often requiring application linear mixed models time-varying outcomes. paper presents alternative splits quantitative analysis two steps. first step converts irregularly observed data set repeated measures broken stick model. second step estimates parameters scientific interest repeated measurements subject level. broken stick model approximates subject’s trajectory series connected straight lines. breakpoints, specified user, divide time axis consecutive intervals common subjects. Specification model requires just three variables: time, measurement subject. model special case linear mixed model, time linear \\(B\\)-spline subject grouping factor. main assumptions : subjects exchangeable, trajectories consecutive breakpoints straight, random effects follow multivariate normal distribution, unobserved data missing random. R package brokenstick v2.5.0 offers tools calculate, predict, impute visualise broken stick estimates. package supports two optimisation methods, including options constrain variance-covariance matrix random effects. demonstrate six applications model: detection critical periods, estimation time--time correlations, profile analysis, curve interpolation, multiple imputation personalised prediction future outcomes curve matching.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"introduction","dir":"Articles > Manual","previous_headings":"","what":"Introduction","title":"Broken Stick Model for Irregular Longitudinal Data","text":"longitudinal studies plan data collection occur fixed set time points. practice, realized times can differ — sometimes substantially — scheduled times. may many reasons differences. example, planned visit weekend holiday, subject show , measurement device order, investigator fell ill. Varying observation times may also result combining data multiple studies, collected according design. Timing variation can substantial observational studies, especially survey lacks pre-specified schedule. Longitudinal data timing differences subjects said irregular. Irregular observation times present significant challenges quantitative analysis. example, easy calculate time--time correlation matrix data spread thinly time. might also complex predict future past data subject times differ. Observation times may also relate process interest. example, severely ill patients get measured frequently; unmotivated cohort members respond rarely, . Conventional methods like MANOVA, regression cluster analysis break observation times differ drop-selective. irregular observation times occur science, universal principled approach resolve problem. One straightforward fix take dates data available (e.g., dates stocks traded), thus ignoring times markets closed. One may also create bins time intervals around planned times, thereby ignoring within-period differences. Another ad-hoc method predicts value scheduled time neighboring data, e.g., linear interpolation smoothing, typically reducing variability data. quick fixes create data sets timing problem seems “gone away”, may tempt analyzingt ignore potential effects data patch-substantive conclusions. convenient straightforward, thoughtless application fixes introduces significant spurious relations time, especially spacing observations highly irregular (Rehfeld et al. 2011). Binning can lead “surprisingly large” biases (Towers 2014). timing variation related outcome interest, methods may result biased estimates exaggerated claims (Pullenayegum Lim 2016). linear mixed model longitudinal data (Laird Ware 1982; Fitzmaurice, Laird, Ware 2011) standard analyzing irregular data. model represents subject’s observed curve parametric function time. parameter estimates function specific subject modeled random effects. linear mixed model beneficial irregular data. borrows strength across different realizations process, summarizing trajectory small number parameters vary subjects. analyst can break distribution random effects function individual characteristics. linear mixed model attractive number measurements differs individuals measurements taken different times. paper explores use broken stick model transform irregularly observed data repeated measures. broken stick model describes curve series connected straight lines. model long history known many names, among others, segmented straight lines (Bellman Roth 1969), piece-wise regression (Toms Lesperance 2003), structural change models (Bai Perron 2003), broken line smoothing (Koutsoyiannis 2000) segmented regression (Lerman 1980). term broken stick goes back least MacArthur (1957), used analogy indicate abundance species. literature broken stick model concentrates problem finding optimal times lines connect. Instead, present paper focus problem summarizing irregular individual trajectories estimates made pre-specified time grid. time grid identical individuals, need equidistant. model formulation special case linear mixed model, time modeled set random effects coded linear \\(B\\)-spline subjects grouping factor. output transformation set repeated measures, every subject obtains score every time point. Many R packages offer tools interpolation. splines package (Team, n.d.) akima package (Akima et al. 2021) contains classic interpolation methods one- two-dimensional smoothing. contributed packages concentrate time series spatial interpolation. See Li Heap (2014) Lepot, Aubin, Clemens (2017) overviews different concepts methodologies. interpolation techniques rely neighboring information, time, space . broken stick model addresses problem many independent replications provide short irregular multivariate time series, say 5-30 time points. scientific interest dynamically predict update future observations. model applies linear mixed model increase stability series borrowing information across replicates. satisfactory solutions problem, brokenstick package (van Buuren 2023) intends fill gap. Package brokenstick available Comprehensive R Archive Network https://CRAN.R-project.org/package=brokenstick. Substantive researchers often favor repeated measures use linear mixed models simplicity. example, can easily fit subject-level model predict future outcomes conditional earlier data repeated measures data. simple regression models may less efficient modelling complete data (Diggle et al. 2002, sec. 6.1), increased insight may valuable increased precision. broken stick model requires specification sensible set time points measurements ideally taken. subject, model predicts imputes hypothetical observations times, substantive analysis applies repeated measures instead irregular data. strategy akin Diggle’s multi-stage model-fitting approach (Diggle 1988). envisioned two-step analytic process aims provide best worlds. applications broken stick model : approximate individual trajectories series connected straight lines; align irregularly observed curves joint age grid; impute realizations individual trajectories; estimate time--time correlation matrix; predict future observations. original motivation developing broken stick model facilitate statistical analysis testing critical ages onset childhood obesity (de Kroon et al. 2010), extensions multiple imputation (van Buuren 2018b). good support R fitting child growth data. mention related approaches. Methods estimating growth references parametric models gamlss() gamlss (Stasinopoulos Rigby 2007) Bayesian incarnation bamlss() bamlss (Umlauf et al. 2021). Nonparametric alternatives estimate quantiles directly rq() quantreg (Koenker et al. 2018) expectreg.ls() expectreg (Otto-Sobotka et al. 2021). Methods modelling smoothing growth curves fit trajectories per child include smooth.basisPar() fda (Ramsay, Graves, Hooker 2021), gam() mgcv (Wood 2011), loess() smooth.spline() base stats (Team, n.d.). Models smooth borrowing strength across children face.sparse() face (Xiao et al. 2021), lmer() lme4 (Bates et al. 2015), sitar() sitar (Cole 2022). broken stick model fits latter tradition, features intuitive parametrization individual growth curve series connected straight lines. See Anderson et al. (2019) overview comparison methods. present paper highlights various computational tools brokenstick v2.5.0 package. package contains tools fit broken stick model data, export fitted model’s parameters, create imputed values model, predict broken stick estimates new data. Also, text illustrates tool helps solve various analytic problems.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"illustration-of-broken-stick-model","dir":"Articles > Manual","previous_headings":"","what":"Illustration of broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"first step, let us study variation age measurement 200 children SMOCC study (Herngreen et al. 1994). Lokku et al. (2020) suggest abacus plot visualize variation. Figure 1: Abacus plot observation times first 20 children SMOCC data. Data collection done 10 waves. dot represents age observation made. variability timing children rises age. blue points Figure 1 indicate observation times. Generally, blue points close scheduled ages (indicated vertical lines), especially first half-year. Observation times vary older children. Several children one missing visits (e.g., 10002, 10008, 10024). children (10012, 10015) fairly close visits. Child 10028 dropped month 9. Let us fit two models, two nine lines, respectively, body length’s standard deviation score (SDS). Figure 2: Data fitted curves three children (blue = observed data, red = fitted curves). broken stick model two lines (top) gives crude approximation data. model nine lines (bottom) follows data quite closely. Knot values rounded simplify presentation. Figure 2 shows individual trajectories three children. blue points coincide observed data, whereas red curves calculated according broken stick model. two fitted models. simpler model (top) uses just two line segments. first line starts birth ends age exactly 1 year. second line spans period 1 2 years. Note two lines connect breakpoint, age 1 year. red curves two-line model crude approximation data. can create better model setting breakpoints equal scheduled ages. Since 10 scheduled ages, construct nine straight lines. contrast two-line model, nine-line broken stick model sensitive small bumps observed trajectory closely fits empirical data. residual variance nine-line model low (0.059), proportion explained variance SDS high (0.98). observation times data differ children, broken stick curves use identical time points across subjects. idea now can add broken stick estimates child-level data long--wide conversion analyze supplemented columns repeated measures. repeated measures analysis usually simpler equivalent temporally misaligned data. example, easy calculate mean profiles arbitrary groups, estimate time--time covariance matrix, build predictive models child level. See Hand Taylor (1987) lucid overview linear techniques repeated measures.","code":"fit2 <- brokenstick(hgt_z ~ age | id, smocc_200, seed = 1, knots = 0:2) fit9 <- brokenstick(hgt_z ~ age | id, smocc_200, seed = 1, knots = round(c(0:3, 6, 9, 12, 15, 18, 24)/12, 4))"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"notation","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Notation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"adopt notation Fitzmaurice, Laird, Ware (2011). Let \\(Y_{ij}\\) denote response variable \\(^{\\rm th}\\) subject \\(j^{\\rm th}\\) measurement occasion time \\(t_{ij}\\). Data collected sample \\(N\\) persons \\(=1,\\dots,N\\). Let repeated measurements \\(^{\\rm th}\\) subject grouped \\[ Y_i = \\left( \\begin{array} {l} Y_{i1} \\\\ Y_{i2} \\\\ \\vdots \\\\ Y_{in_i} \\end{array} \\right), \\quad = 1, \\dots, N. \\] measures observed common set occasions, drop index \\(\\) \\(t_{ij}\\) since \\(t_{ij} = t_j\\) \\(= 1, \\dots, N\\). focus case \\(t_{ij}\\) varies \\(\\). addition, let use define \\(n_i \\times p\\) matrices \\[ X_i = \\left( \\begin{array} {llll} X_{i11} & X_{i12} & \\cdots & X_{i1p} \\\\ X_{i21} & X_{i22} & \\cdots & X_{i2p} \\\\ \\vdots & \\vdots & \\ddots & \\vdots \\\\ X_{in_i1} & X_{in_i2} & \\cdots & X_{in_ip} \\end{array} \\right), \\quad = 1, \\dots, N, \\] rows \\(X_i\\) contain \\(p\\) covariates associated responses \\(n_i\\) measurement occasions. columns may time-varying covariates. certain covariate fixed time (e.g., sex, treatment, education), values within corresponding column \\(X_i\\) identical.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"broken-stick-model","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model avoids modeling observation times \\(t_{ij}\\) directly representing \\(t_{ij}\\) relative position within time interval. example, suppose \\(t_{ij} = 0.6\\) years time interval given 0.5-1.0 years. position relative left break age \\(x_{\\rm left} = (1.0-0.6)/(1.0-0.5) = 0.8\\), whereas relative right break age \\(x_{\\rm right} = (0.6-0.5)/(1.0-0.5) = 0.2\\). order fit broken stick model, need replace time point \\(t_{ij} = 0.6\\) two values: 0.8 (break age 0.5), 0.2 (break age 1.0). Note values add 1. Coding time way simplifies modeling continuous time set discrete break ages. specifically, let \\(t_{ij}\\) coded second-order (linear) \\(B\\)-spline using \\(k\\) internal knots \\(\\kappa\\) placed \\(k+1\\) ordered ages \\[ \\kappa_0 = \\kappa_1 < \\dots < \\kappa_k < \\kappa_{k+1} \\] internal knots \\(\\kappa_1, \\dots, \\kappa_k\\) correspond set ages obtain broken stick estimates, specified user. left boundary knot \\(\\kappa_0 = \\kappa_1\\) left-anchored minimum time \\(\\min(t_{ij})\\) data. point defines starting event participant, birth study enrollment. right hand boundary knot \\(\\kappa_{k+1} \\geq \\max(t_{ij})\\). second-order \\(B\\)-spline (de Boor 1978, 32), \\[ H_s(t) = \\left\\{ \\begin{array} {l@{\\quad,\\quad}l} (t-\\kappa_{s-1})/(\\kappa_s - \\kappa_{s-1}) & \\kappa_{s-1} < t \\leq \\kappa_s,\\\\ (\\kappa_{s+1}-t)/(\\kappa_{s+1} - \\kappa_s) & \\kappa_s \\leq t < \\kappa_{s+1},\\\\ 0 & {\\rm otherwise.} \\end{array} \\right. \\] applied \\(t_{ij}\\) obtain \\((k+1)\\) transformed variables \\(x_{} = t_{ij}\\) \\(s = 1,\\dots,k+1\\). variables can conveniently grouped \\(n_i \\times (k+1)\\) matrix covariates \\(X_i = (x_{i1}, \\dots, x_{ik}, x_{(k+1)})\\). row \\(X_i\\) one two non-zero elements, sum 1. Using \\(X_i\\), broken stick model special case (\\(Z_i = X_i\\)) two-stage random-effects model (Laird Ware 1982) \\[ Y_i = X_i\\beta + X_ib_i + \\epsilon_i \\] \\(k+1\\) column vector \\(\\beta\\) contains \\(k+1\\) fixed effect coefficients common persons, \\(k+1\\) column vector \\(b_i\\) accommodates \\(k+1\\) subject-specific random parameters, \\(n_i\\) column vector \\(\\epsilon_i\\) holds subject-specific residuals. order complete model specification, assume residuals identically independently distributed \\(\\epsilon_i \\sim N(0,\\sigma^2 (n_i))\\), \\(\\sigma^2\\) common variance parameter, \\((n_i)\\) identity matrix order \\(n_i\\). Thus, equation represents population parameters (fixed effects), individual effects (random effects), amount within-person dispersion persons. Section 4.2 also considers heterogeneous model allows \\(\\sigma_i^2\\) vary subjects. summary, given knot specification choice response scale, parameters broken stick model : \\(\\beta\\), vector \\(k + 1\\) fixed parameters; \\(\\Omega\\), \\((k+1) \\times (k+1)\\) covariance matrix random effects; \\(\\sigma^2\\), within-person error variance. total number parameters solution \\(k\\) internal knots thus equal \\((k^2 + 5k + 6)/2\\). example, model \\(k = 3\\) knots (.e., two connected lines) 15 parameters, model \\(k = 4\\) 21 parameters, model \\(k = 10\\) break ages 78 parameters. heterogeneous model one additional parameter measures variation \\(\\sigma_i^2\\).","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"model-assumptions","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Model assumptions","title":"Broken Stick Model for Irregular Longitudinal Data","text":"person level, assume \\(b_i \\sim N(0, \\Omega)\\), .e., random coefficients subjects multivariate normal distribution zero mean \\((k+1) \\times (k+1)\\) covariance matrix \\(\\Omega\\). base model allows elements \\(\\Omega\\) vary freely. time-dependent data, constrained versions \\(\\Omega\\) also interest (Fitzmaurice, Laird, Ware 2011, Ch. 7). Section 4.2 highlights two extensions. also assume covariance \\(b_i\\) \\(\\epsilon_i\\) zero. simplicity, paper restricted case \\(X_i\\) includes time, covariates. broken stick model builds upon three main modeling assumptions: trajectory break ages follows straight line. assumption may fail processes convex concave time. example, human height growth centimeters concave time, setting breakpoints far apart introduces systematic negative bias. Modeling height SDS instead raw height prevent bias. broken stick estimates follow joint multivariate normal distribution. assumption may fail skewed measurements, beneficial transform outcomes distribution closer normal. data missing random (MAR) given outcomes subjects observation times. assumption restrictive sense missingness may depend observed outcomes, covariates time. time, assumption liberal sense missingness may depend future outcomes. MAR-future assumption unusual literature drop-observation time models, sensible strategy creating imputations preserve relations time, especially intermittent missing data. course, subsequent substantive analysis imputed data needs aware causal direction time.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpretation","dir":"Articles > Manual","previous_headings":"3 Methodology","what":"Interpretation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Given model estimates person data, can calculate random effect \\(b_i\\). broken stick parameter \\(\\gamma_{} = \\beta_s + b_{}\\) subject-specific mean \\(Y_i\\) time \\(\\kappa_s\\), \\(s = 1,\\dots, k + 1\\). set \\(\\gamma_{}\\) parameters describes mean response profile subject \\(\\) \\(k\\) lines connect \\(k + 1\\) coordinates \\((\\kappa_s, \\gamma_{})\\). broken stick parameter likely value outcome \\(Y_i\\) subject \\(\\) time \\(\\kappa_s\\) given person’s observed data given fitted model (represents evolution trajectories training data). parameter center posterior predictive distribution normal \\(Y_i\\). two-sided \\(100(1-\\alpha)\\%\\) prediction interval true, though often unobserved, value \\(Y_{,\\kappa_s}\\) equal \\[ [Y_{,\\kappa_s}^{\\rm lo}, Y_{,\\kappa_s}^{\\rm hi}] = \\gamma_{} \\pm t_{(1-\\alpha/2;N-1)}\\sigma, \\] \\(t_{(1-\\alpha/2;N-1)}\\) \\(100(1-\\alpha/2)\\) percentile Student’s \\(t\\)-distribution \\(N - 1\\) degrees freedom. example, 50% prediction interval \\(\\gamma_{} \\pm 0.68\\sigma\\) contain 50% true values. normal \\(Y_i\\), length 50% prediction interval equivalent interquartile range (IQR). residual variation \\(\\sigma^2\\) small (say \\(\\sigma^2 < 0.1\\)), IQR 0.22, half true values within 0.22 SD \\(\\gamma_{}\\), small difference. large \\(\\sigma^2\\) (e.g., \\(\\sigma^2 > 0.2\\)), \\(\\gamma_{}\\) vector smoothed representation \\(Y_{}\\). smoothness amplifies low-frequency features trajectories, also introduce biases subsequent analysis suppressing high-frequency variation. case, analyst needs check whether reduction variation affect parameters substantive interest. may restore high-frequency variation adding random draws residual distribution \\(N(0, \\sigma^2)\\). , small step multiple imputation, well-developed methodology drawing valid inferences incomplete data (Rubin 1987; van Buuren 2018b). \\(n_i \\gg k\\) broken stick model provides parsimonious representation measurements. Reversely, \\(n_i \\ll k\\) model infers plausible values subject \\(\\) building strength across persons. broken stick model converts \\(n_i\\) irregularly observed measurements new set \\(k\\) values \\(\\gamma_{}\\) common ages \\(\\kappa_1, ..., \\kappa_k\\), \\(s = 1,\\dots, k\\). Since row \\(X_i\\) sums unity, broken stick model global intercept. linear \\(B\\)-spline coding effectively replaces global random intercept term \\(k + 1\\) local intercepts, one break age. local intercept summarizes information available adjacent left right age intervals ignores information beyond two adjacent knots. broken stick estimates thus primarily local. Outcome data observed outside two adjacent age intervals influence broken stick estimates subject-level part model, particular \\(\\Omega\\).","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"main-function","dir":"Articles > Manual","previous_headings":"4 Estimation","what":"Main function","title":"Broken Stick Model for Irregular Longitudinal Data","text":"brokenstick() function estimates parameters broken stick model. user needs specify outcome, predictor grouping variable, well location knots predictor variable. call produces object class \"brokenstick\": object contains model setting, data results. column names \\(X\\) consist name time variable knot values appended. Thus, age_0 birth length age_1 length age 1y. find estimates fixed effects \\(\\beta\\) means, residual variance \\(\\sigma^2\\) mean resid variance-covariance matrix random effects \\(\\Omega\\) get_omega(fit). calculate broken stick estimates knot locations wide matrix predict() function follows: specification x = \"knots\" uses special keyword \"knots\" set predictor values equal knot locations used fit model. argument shape = \"wide\" returns predicted values wide matrix (one row per group, one column per predictor value). result now individual trajectory summarized six estimates.","code":"fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = c( 0, 0.5, 1, 2), seed = 12321) summary(fit) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 22 (total), 5 (fixed), 5 (variance), 10 (covariance), 2 (error) ## Knots 0.0 0.5 1.0 2.0 ## Means -0.0939 0.0926 -0.0137 0.0842 ## Residuals 0.106 0.129 0.146 0.169 0.361 (min, P25, P50, P75, max) ## Mean resid 0.156 ## R-squared 0.893 ## ## Variance-covariance matrix ## age_0 age_0.5 age_1 age_2 ## age_0 1.409 ## age_0.5 0.718 0.905 ## age_1 0.521 0.755 0.765 ## age_2 0.395 0.721 0.783 0.941 bse <- predict(fit, x = \"knots\", shape = \"wide\") dim(bse) ## [1] 200 5 head(bse, 3) ## # A tibble: 3 × 5 ## id `0` `0.5` `1` `2` ## ## 1 10001 0.789 0.247 0.0256 0.0341 ## 2 10002 -0.267 -0.228 -0.421 -0.514 ## 3 10003 1.67 2.00 1.28 1.10"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"estimation-steps-explained","dir":"Articles > Manual","previous_headings":"4 Estimation","what":"Estimation steps explained","title":"Broken Stick Model for Irregular Longitudinal Data","text":"may break estimation process two main steps. first step calculates matrix \\(B\\)-splines time variable age core splines::bs() (Team, n.d.) function: numerical example shows bs() function transforms age variable five columns, \\(B\\)-spline basis, names like age_0 age_0.5. age coincides one (e.g., top row), corresponding column receives 1. cases, age distributes two adjacent columns. Setting degree = 1 specifies \\(B\\)-spline gives broken stick model name characteristic shape. Although strictly needed, applications paper assume left boundary knot marks start time, e.g., birth day enrollment. subtleties using splines::bs() create linear \\(B\\)-spline basis. Matrix X values range \\([0, 1]\\) maximum two non-zero values per row sum \\(1\\). conditions require Boundary.knots span least range data. requirement easy achieve setting Boundary.knots = range(data$age), done default. Also, need ensure range knots outside Boundary.knots. may achieve setting Boundary.knots include least range(knots). practice, user need worry boundaries since brokenstick() function takes care conditions expanding boundary range needed. primary reason setting explicit boundaries make independent data. second step specify model estimate parameters. two methods : \"kr\" \"lmer\". Method \"lmer\" relies popular function lme4::lmer() (Bates et al. 2015) fit linear mixed normal model. formula removes intercept specifies knot random effect child id grouping factor. control argument suppresses warning Model failed converge max|grad| = 0.0360913. warnings occur often model many random effects. warnings may also thrown child data outliers (example pre-terms). found broken estimates generally look sound reasonable despite warnings. Note however experience derives primarily child growth data, guarantee apparent robustness hold types data. Warnings lmer() become frequent higher number knots, smaller samples data observations made irregular time points. Object mod_lmer class \"lmerMod\" may use standard plot(), predict() summary methods offered lme4 package. Converting result broken stick estimates requires summing fixed random effects. calculation time lme4::lmer() rapidly increases number random effects. ten random effects (knots) takes significant time, beyond 15 knots generally impossible fit. example, using dataset 33,000 records 2,600 individuals, M1 Max processor takes 8 seconds (5 knots), 107 seconds (9 knots), 403 seconds (12 knots) 1172 seconds (15 knots). brokenstick package provides another alternative, Kasim-Raudenbush (KR) sampler (Kasim Raudenbush 1998). method simulates draws posterior distributions parameters two-level normal model heterogeneous within-subject variances. speed Kasim-Raudenbush sampler almost insensitive number random effects depends primarily total number iterations somewhat sample size. Execution KR method problem takes 15 seconds (5 knots), 17 seconds (9 knots), 19 seconds (12 knots) 20 seconds (15 knots). method available function kr() brokenstick package default since version 2.0.0. control_kr() function tweaks estimation options: call control_kr() produces list settings sampler according conventions coda package (Plummer et al. 2006). defaults control_kr() reasonable across wide range cases. list component mod_kr$mod contains various objects class \"mcmc\" sampling history detailed results. example, inspect fixed effect estimates Also, may obtain trace plots densities. example try plot(mod_kr$mod$beta). obtain results method \"lmer\" argument shape = \"wide\" specifies form return value. broken stick estimates kr lmer methods similar, identical. fact, substantial discrepancies may occur areas data sparse, example, right boundary knot. Apart faster complex models, KR-sampler opens interesting analytic options: relatively easy constrain fitted covariance random effects, \\(\\Omega\\), matrix simple structure. Informing sampler time-dependent structure random effect leads stabler estimates \\(\\Omega\\). package currently implements two correlations models. models express correlation \\(\\rho(t_1, t_2)\\) two Z -scores \\(Z_1\\) \\(Z_2\\) successive ages \\(t_1\\) \\(t_2\\) function ages. Argyle model (Argyle, Seheult, Wooff 2008) \\(\\rho(t_1, t_2) = \\exp(-\\lambda|T_1-T_2|)\\), \\(T_i = \\log(\\tau+t_i)\\) logarithmic rescaling time axis \\(\\rho=exp(-\\lambda)\\). Cole correlation model (Cole 1995) describes Fisher-transformed correlation function average \\((t_1+t_2)/2\\) difference \\((t_2-t_1)\\), including two multiplicative terms. Note models proposed context child growth, may fit less well types time-dependent data. Kasim-Raudenbush sampler fits slightly general linear-mixed model heterogeneous within-subject variances, .e., residual variance \\(\\sigma_i^2\\) per subject \\(\\) instead global residual \\(\\sigma^2\\). makes easier identify, study weight subjects based well fit model. third option simulate imputations extra step sampler. subjects large \\(\\sigma_i^2\\), random effect estimates smooth representation data, leading inappropriate variance estimates estimates analyzed “just data”. Section 11.3 van Buuren (2018b) pioneered solution constructs multiple trajectories adding proper amount residual noise random effect estimates. variance estimation proceeds according principles multiple imputation (Rubin 1987).","code":"library(\"splines\") data <- brokenstick::smocc_200 internal <- c(0, 0.5, 1, 2) X <- bs(data$age, knots = internal, Boundary.knots = c(0, 2.68), degree = 1) colnames(X) <- paste(\"age\", c(internal, 2.68), sep = \"_\") head(X) ## age_0 age_0.5 age_1 age_2 age_2.68 ## [1,] 1.000 0.000 0.0000 0 0 ## [2,] 0.836 0.164 0.0000 0 0 ## [3,] 0.682 0.318 0.0000 0 0 ## [4,] 0.491 0.509 0.0000 0 0 ## [5,] 0.000 0.992 0.0076 0 0 ## [6,] 0.000 0.494 0.5058 0 0 data <- cbind(brokenstick::smocc_200[, c(\"id\", \"age\", \"hgt_z\")], X) ctl_lmer <- lme4::lmerControl( check.conv.grad = lme4::.makeCC(\"warning\", tol = 0.04)) f <- hgt_z ~ 0 + age_0 + age_0.5 + age_1 + age_2 + age_2.68 + (0 + age_0 + age_0.5 + age_1 + age_2 + age_2.68 | id) mod_lmer <- lme4::lmer(f, data, control = ctl_lmer) class(mod_lmer) ## [1] \"lmerMod\" ## attr(,\"package\") ## [1] \"lme4\" bse_lmer <- t(t(lme4::ranef(mod_lmer)$id) + lme4::fixef(mod_lmer)) head(round(bse_lmer, 3), 3) ## age_0 age_0.5 age_1 age_2 age_2.68 ## 10001 0.778 0.272 -0.01 0.076 0.095 ## 10002 -0.278 -0.206 -0.46 -0.477 -0.223 ## 10003 1.681 1.969 1.28 1.115 -0.256 ctl_kr <- control_kr() mod_kr <- kr(y = data$hgt_z, x = X, g = data$id, control = ctl_kr) library(\"coda\") summary(mod_kr$mod$beta) ## ## Iterations = 101:300 ## Thinning interval = 1 ## Number of chains = 1 ## Sample size per chain = 200 ## ## 1. Empirical mean and standard deviation for each variable, ## plus standard error of the mean: ## ## Mean SD Naive SE Time-series SE ## age_0 -0.0966 0.0875 0.00619 0.01001 ## age_0.5 0.0897 0.0625 0.00442 0.00442 ## age_1 -0.0196 0.0626 0.00443 0.00526 ## age_2 0.0768 0.0749 0.00530 0.00715 ## age_2.68 0.2087 0.4594 0.03249 0.15269 ## ## 2. Quantiles for each variable: ## ## 2.5% 25% 50% 75% 97.5% ## age_0 -0.2623 -0.1582 -0.0897 -0.0354 0.0600 ## age_0.5 -0.0188 0.0454 0.0943 0.1320 0.2139 ## age_1 -0.1502 -0.0633 -0.0183 0.0223 0.0922 ## age_2 -0.0623 0.0257 0.0806 0.1263 0.2168 ## age_2.68 -0.6762 -0.0168 0.1983 0.4737 1.2039 fit_lmer <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = c( 0, 0.5, 1, 2), method = \"lmer\", control = ctl_lmer) head(predict(fit_lmer, x = \"knots\", shape = \"wide\"), 3) ## # A tibble: 3 × 5 ## id `0` `0.5` `1` `2` ## ## 1 10001 0.778 0.272 -0.0101 0.0763 ## 2 10002 -0.278 -0.206 -0.460 -0.477 ## 3 10003 1.68 1.97 1.28 1.12"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"overview","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Overview","title":"Broken Stick Model for Irregular Longitudinal Data","text":"brokenstick package contains functions fit, predict plot data. Main functions, user-oriented helpers, internal functions computation used brokenstick package summarized Table 1. Table 1: Main functions, user-oriented helpers, internal functions computation used brokenstick package. package exports S3 methods class \"brokenstick\" following generic functions coef(), fitted(), model.frame(), model.matrix(), plot(), predict(), print(), residuals() summary(). object class \"brokenstick\" stores training data default. desired, specify brokenstick(..., light = TRUE) create small object just parameter estimates. course, extract original data light object. However, can still use calculate brokenstick estimates new cases using predict(object, newdata = ...).","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"data-preparation","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Data preparation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"can fit model, data need shape. brokenstick() function takes tidy data long-form. Every row data corresponds one visit. Two columns identify visit: subject variable time variable. Thus, subject one three visits subject two five visits, combined data eight records. section uses built-smocc_200 data, containing heights 200 children measured ten visits two years (Herngreen et al. 1994). subject variable id time variable age.","code":"library(\"brokenstick\") head(smocc_200, 3) ## # A tibble: 3 × 7 ## id age sex ga bw hgt hgt_z ## ## 1 10001 0 female 40 3960 52 0.575 ## 2 10001 0.0821 female 40 3960 55.6 0.888 ## 3 10001 0.159 female 40 3960 58.2 0.797"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"transformation-to-standard-deviation-scores-sds","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Transformation to Standard Deviation Scores (SDS)","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model can fit observations either raw scale \\(Y\\) (cm, kg, ) \\(Z\\)-score. normal distribution mean \\(\\mu\\) standard deviation \\(\\sigma\\) \\(Z\\)-score data value \\(Y\\) defined \\(Z = (Y - \\mu)/\\sigma\\). statistics, customary estimate \\(\\mu\\) \\(\\sigma\\) data, can also take values external reference table. example, heights boys age \\(t\\) follow approximate normal distribution age-specific mean \\(\\mu_t\\) age-specific standard deviation \\(\\sigma_t\\). reference table consists estimates \\(\\mu_t\\) \\(\\sigma_t\\) different ages \\(t\\). calculate standard deviation score (SDS) boy height \\(Y\\) age \\(t\\) \\(Z = (Y - \\mu_t)/\\sigma_t\\), \\(\\mu_t\\) \\(\\sigma_t\\) taken reference table. can compare \\(Z\\)-score directly reference population, compare two measurements taken different ages age effect removed. SDS calculation standard methodology child growth, available many distributions. See Stasinopoulos Rigby (2007) details. Analysis \\(Z\\)-scores preferable raw scale several reasons: growth curve follows centile reference distribution translates horizontal line \\(Z\\)-score scale, simplifies modeling; Observations \\(Z\\)-score scale closer multivariate normality; Analysis \\(Z\\)-scores removes overpowering impact age sex growth, becomes easier highlight interesting variation within children; Fitting \\(Z\\)-score data leads fewer convergence issues. area child growth, easy convert raw measurements \\(Z\\)-score scale, fit model, convert back raw scale afterwards, desired. several R packages assist calculations: AGD (van Buuren 2018a), anthro (Schumacher, Borghi, Polonsky 2020), childsds (Vogel 2020), growthstandards (Hafen 2021), nlreferences (van Buuren 2021b), sitar (Cole 2022) zscorer (Myatt Guevarra 2019). smocc_200 data contains height measurement original scale cm (hgt) \\(Z\\)-score scale (hgt_z) relative height references Fourth Dutch Growth study (Fredriks et al. 2000). illustration, let us calculate check height SDS using AGD package. Figure 3: Distribution height SDS 200 SMOCC children aged 0-2 years relative Dutch 1997 length references. distribution closely follows normal distribution. outliers left tail genuine observations children born pre-term. Figure 3 shows , expected, empirical Z-score distribution close standard normal. extremely low heights correspond pre-term born infants. Section 5.4 concentrates modelling hgt_z. Function z2y() applies inverse transformation \\(Z\\)-scores original scale. following snippet converts hgt_z cm scale. used Dutch 1997 height references , similar transforms made using references. Many age- sex-conditional references exist field child growth. fields, references may rare uncommon. case, may achieve benefits \\(Z\\)-scale analysis applying broken stick model standardized residuals preliminary non-linear regression outcome time.","code":"library(\"AGD\") z <- with(smocc_200, y2z(y = hgt, x = age, sex = ifelse( sex == \"male\", \"M\", \"F\"), ref = nl4.hgt)) identical(z, smocc_200$hgt_z) ## [1] TRUE y <- with(smocc_200, AGD::z2y(z = hgt_z, x = age, sex = ifelse( sex == \"male\", \"M\", \"F\"), ref = nl4.hgt)) all.equal(y, smocc_200$hgt, tol = 0.0001) ## [1] TRUE"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"model-fitting","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Model fitting","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 4: Detrended growth chart. Length growth 52 infants 0-2 years expressed Z-score scale. trajectory represents child. Trajectories almost flat representation. centile crossings occur near start trajectory. Figure 4 displays growth curves subset 52 children. \\(Z\\)-score transformation takes away major time trend, trajectories less flat. display allows us see extremely detailed assessment individual growth. Note measurements cluster around ten ages: Birth, 1, 2, 3, 6, 9, 12, 15, 18 24 months. data collectors rigorously followed study design, variation timing inevitable weekends, holidays, sickness, events.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"fit-one-line","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.4 Model fitting","what":"Fit one line","title":"Broken Stick Model for Irregular Longitudinal Data","text":"start, let us fit simple straight line model age range 0y-2y. argument knots = c(0, 2) specifies wish model data age range 0y-2y straight line. Closer inspection get_knots(fit1, hide = \"none\") reveals actually another knot right boundary age 2.68 years. knot needs ensure data taken account, direct interest. can plot individual trajectories : Figure 5: Observed data (blue) fitted broken stick model (red) straight line birth two years. model picks overall trend, ignores systematic patterns around line. Figure 5 shows observed (blue) fitted (red) trajectories three selected children. side note, can actually plot model full age range data adding argument hide = \"none\" plot() function (shown). Observe model captures overall age trend, fit data moderate.","code":"fit1 <- brokenstick(hgt_z ~ age | id, smocc_200, knots = c(0, 2)) get_knots(fit1, hide = \"none\") ## [1] 0.00 2.00 2.68 ids <- c(10001, 10005, 10022) plot(fit1, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\")"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"fit-two-lines","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.4 Model fitting","what":"Fit two lines","title":"Broken Stick Model for Irregular Longitudinal Data","text":"now extend two connected lines. first line start birth end age one year. second line spans period one two years. lines must connect age one year. estimate plot model follows: resulting plot already shown Figure 2 (top line). fit2 object holds parameter estimates model: printed output lists knots model 0, 1 2 years. left right boundaries located 0 2.68, respectively, corresponding lowest highest ages data. data right boundary suppressed since brokenstick() function sets fit2$hide = \"right\" default. means entry lists fixed effect estimates, interpret average SDS per time point. time--time variance-covariance matrix covers four random effects (3 visits + 1 end knot). two error parameters measure variability discrepancies model observed data. three parameters (fixed, random, residual variance) well interpretable fully record fitted broken stick model.","code":"fit2 <- brokenstick(hgt_z ~ age | id, smocc_200, knots = 0:2) plot(fit2, group = ids, xlab = \"Age (years)\", ylab = \"Length (SDS)\") summary(fit2) ## Class brokenstick (kr) ## Variables hgt_z (outcome), age (predictor), id (group) ## Data 1942 (n), 36 (nmis), 200 (groups) ## Parameters 16 (total), 4 (fixed), 4 (variance), 6 (covariance), 2 (error) ## Knots 0 1 2 ## Means -0.0450 0.0179 0.0611 ## Residuals 0.125 0.150 0.170 0.200 0.379 (min, P25, P50, P75, max) ## Mean resid 0.182 ## R-squared 0.866 ## ## Variance-covariance matrix ## age_0 age_1 age_2 ## age_0 1.226 ## age_1 0.494 0.841 ## age_2 0.454 0.794 0.874"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"fit-nine-lines","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.4 Model fitting","what":"Fit nine lines","title":"Broken Stick Model for Irregular Longitudinal Data","text":"two-line model fit well. substantially refine model adding knot scheduled visit. code run model small residual variance 0.077, nine-line broken stick model fits observed data well. Figure 2 (bottom line) illustrates nine-line model follows data much better. training set includes subjects. Depending study goals, may wish improve model fit removing children data. example, might children observations available, children diseases, children trajectories unusual faulty. distribution subject-specific residuals, plotted hist(fit9$sigma2j), shows one severe outlier. can locate plot outlier plot(fit9, group = unique(fit9$data$id)[(fit9$sigma2j > 4)]). remove increase model fit, course, removals may affect external generalizability.","code":"fit9 <- brokenstick(hgt_z ~ age | id, smocc_200, seed = 1, knots = round(c(0:3, 6, 9, 12, 15, 18, 24)/12, 4))"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"prediction","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Prediction","title":"Broken Stick Model for Irregular Longitudinal Data","text":"fitted model, may obtain predictions. subject(s) part training sample, also consist new children.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"all-subjects","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.5 Prediction","what":"All subjects","title":"Broken Stick Model for Irregular Longitudinal Data","text":"predict() function obtains predictions broken stick model. function flexible, allows prediction new subjects arbitrary ages variety output formats. simplest call produces vector containing 1942 predictions observed ages. values represent compromise person’s measurement global mean. general, fewer less extreme data points person , closer compromise toward global mean. compromise called conditional mean posterior distribution, sum fixed random effects. can obtain predictions knot every person specifying x = \"knots\" argument, e.g., result p2 table 200 rows values 10 knots. values represent regularized version observed curve, .e., predicted value knot location. Add argument hide = \"none\" predict() calculate values right boundary knot. may request combination types predictions one call result long matrix 3942 rows. two special columns. Column .pred contains predicted values. Column .source identifies whether row comes training data (value data) corresponds one knots (value added). number records training data knots : dataset perfectly suited plot summarizes data model predictions. Now suppose desire predict height SDS ages, e.g., 0.42, 1.33 4 years. can include_data = FALSE argument removes observed data result prevent conversion overly large inefficient wide matrix. Thus, considerable flexibility work times breakpoints. Remember though underlying model change. example, magically predict outside model age 4, values get NA.","code":"p1 <- predict(fit9, shape = \"vector\") head(p1) ## [1] 0.574 0.852 0.750 0.643 0.231 -0.168 p2 <- predict(fit9, x = \"knots\", shape = \"wide\") head(p2, 3) ## # A tibble: 3 × 11 ## id `0` 0.083…¹ 0.166…² `0.25` `0.5` `0.75` `1` `1.25` `1.5` ## ## 1 10001 0.574 0.856 0.739 0.650 0.237 -0.172 0.121 0.163 -0.193 ## 2 10002 -0.189 -0.311 -0.260 -0.315 -0.229 -0.282 -0.336 -0.494 -0.490 ## 3 10003 1.17 2.10 1.98 2.02 2.04 1.81 1.31 1.14 0.880 ## # … with 1 more variable: `2` , and abbreviated variable names ## # ¹​`0.0833`, ²​`0.1667` p3 <- predict(fit9, x = \"knots\") head(p3, 3) ## .source id age sex ga bw hgt hgt_z .pred ## 1 data 10001 0.0000 female 40 3960 52.0 0.575 0.574 ## 2 data 10001 0.0821 female 40 3960 55.6 0.888 0.852 ## 3 data 10001 0.1588 female 40 3960 58.2 0.797 0.750 table(p3$.source) ## ## added data ## 2000 1942 head(predict(fit9, x = c(0.42, 1.33, 4), shape = \"wide\", include_data = FALSE), 3) ## # A tibble: 3 × 4 ## id `0.42` `1.33` `4` ## ## 1 10001 0.369 0.0492 NA ## 2 10002 -0.257 -0.493 NA ## 3 10003 2.03 1.05 NA"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"single-subject","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.5 Prediction","what":"Single subject","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Obtaining predicted values selected subjects requires group argument (case 3 predict()). example returns vector predictions child 10001. Appending child’s data conveniently done removing shape argument. Also, can predict times using x argument, e.g. ages 0.42 1.33 (case 4 predict()). Now suppose subject 10001 additional height data ages 0.42 1.33 years, say -0.5 SDS -1 SDS, respectively. Can predict child’s trajectory new points included? answer yes: command (case 5 predict()) appends two new records data child 10001, recalculates trajectory using data child 10001. Note last two rows contain specified values columns age hgt_z, well predicted value .pred. predicted values different calculated case 4 two additional observations. desired user also fill values columns sex, ga, .","code":"predict(fit9, group = 10001, shape = \"vector\") ## [1] 0.574 0.852 0.750 0.643 0.231 -0.168 0.121 0.151 -0.150 ## [10] 0.142 predict(fit9, x = c(0.42, 1.33), group = 10001, shape = \"vector\") ## [1] 0.5744 0.8519 0.7503 0.6428 0.2308 -0.1682 0.1214 0.1505 ## [9] -0.1500 0.1424 0.3693 0.0492 predict(fit9, x = c(0.42, 1.33), y = c(-0.5, -1), group = c(10001, 10001)) ## .source id age sex ga bw hgt hgt_z .pred ## 1 data 10001 0.0000 female 40 3960 52.0 0.575 0.61363 ## 2 data 10001 0.0821 female 40 3960 55.6 0.888 0.78191 ## 3 data 10001 0.1588 female 40 3960 58.2 0.797 0.67251 ## 4 data 10001 0.2546 female 40 3960 61.2 0.661 0.46165 ## 5 data 10001 0.5038 female 40 3960 67.2 0.290 0.00908 ## 6 data 10001 0.7529 female 40 3960 70.2 -0.398 -0.28561 ## 7 data 10001 1.0021 female 40 3960 75.7 0.202 -0.01344 ## 8 data 10001 1.1745 female 40 3960 78.5 0.268 -0.13440 ## 9 data 10001 1.5661 female 40 3960 81.8 -0.332 -0.39919 ## 10 data 10001 2.0096 female 40 3960 88.3 0.227 0.05064 ## 11 added 10001 0.4200 NA NA NA -0.500 0.15972 ## 12 added 10001 1.3300 NA NA NA -1.000 -0.27760"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"new-subject","dir":"Articles > Manual","previous_headings":"5 Functionality > 5.5 Prediction","what":"New subject","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Suppose measured two new children, Fred Alice. wish obtain predictions using model fit9. following snippet calculates predictions observed ages knot locations: can plot trajectories data Figure 6: Broken stick model prediction sparse data. Alice Fred observations (blue points). broken stick model borrows information children calculate fitted trajectories full age range (red points). Alice contributes two data points first half-year. model expects height SDS around $-$1 SD age two years. Using data 1.1 years, model predicts Fred’s growth curve remains around -2.0 SD Fred 1.5 years, increases around -1.8 SD. predicted trajectories extreme extrapolations, example illustrates possible make informed predictions using just handful data points. brokenstick:::EB() function implements empirical Bayes (EB) estimate (Skrondal Rabe‐Hesketh (2009), p. 683). procedure workhorse underlying predict() method.","code":"data <- data.frame(age = c(0, 0.12, 0.32, 0.62, 1.1, 0.25, 0.46), hgt_z = c(-1.2, -1.8, -1.7, -1.9, -2.1, -1.9, -1.5), id = c( rep(\"Fred\", 5), rep(\"Alice\", 2))) p <- predict(fit9, newdata = data, x = \"knots\") plot(fit9, newdata = data, ylim = c(-2.5, 0), xlab = \"Age (years)\", ylab = \"Length (SDS)\")"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"quality-of-prediction","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Quality of prediction","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 7: Comparison predicted (vertical) observed (horizontal) height SDS scale (left) CM scale (right) SMOCC data. model almost perfectly recreates observed data. Figure 7 scatter plot observed versus predicted values provides visual representation accuracy prediction model height SDS cm scales. plots suggest excellent fit observed fitted data. percentage explained variance height SDS high: 98.1%. standard deviation residuals equal 0.077 SD, small value \\(Z\\)-scale. back-converted centimeters, scatter plot observed versus predicted values even little tighter. estimate proportion explained variance close perfection: 99.9%. standard deviation residuals 4 mm, size technical error measurement (TEM) duplicate measurements infants (Ismail et al. 2016, Table 2). --sample predictive behavior comparable. randomly split data 100 times 2/3 training data 1/3 test data calculate proportion test data, obtain even slightly higher --sample values: 98.4% 99.9% 100 replications. model good can get. uncertainties associated transformation varying observation times repeated measures small. practical purposes, results linear mixed multilevel model repeated measures model likely .","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"knot-placement-strategies","dir":"Articles > Manual","previous_headings":"5 Functionality","what":"Knot placement strategies","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Fitting broken stick model requires specification knots. choice knots influences quality usefulness solution, exercise care setting appropriate knot locations. brokenstick() function uses set knots subjects. default, procedure places five internal knots (default argument k = 5) sets boundary knots equal range predictor variable. k argument quick way add k internal knots equidense quantiles time variable. example, specifying k = 1 puts knot 50th centile (median), setting k = 3 puts knots 25th, 50th 75th centiles, . convenient quick, option can result sub optimal knot placement adequate problem hand. general, best specify explicit values knots argument. suggestions knot placement knots argument: Rule thumb: Limit number knots average number data points per subject; want predict specific times, specify knots time points; Setting knots scheduled visits sensible strategy obtaining predictions precisely scheduled times; Set equidistant knots analysis requires fixed time interval; Keep number knots low, speed simplicity. many (\\(\\geq 10\\)) knots can improve fit data, also increase calculation time may result unstable solutions. problems require 10 knots, method = \"kr\" (default) faster method = \"lmer\". Use control_kr() improve stability setting correlation model. brokenstick() function accept 50 knots; place knots sparsely filled areas data, e.g., -two visits. may result erratic joins; Optionally, check whether model.matrix(fit) produces design matrix elements range \\([0, 1]\\) rows summing \\(1\\). Check colSums(model.matrix(fit)) see total number observations distributes knots; Optionally, contrast 6, add knot equal slightly higher maximum time value. ensures model specification depend range training data. See next point alternative; Prevent data-dependent boundary knots explicitly specifying boundary argument brokenstick() convenient values just outside range x variable. brokenstick() function automatically sets boundary knots range time variable, necessary extends boundary knots include range knots. Normally, concentrate setting proper knots less concerned left right boundary knots. cases, time range test data larger training data. following code block shows effect adding extra knot, according point 8 . code trims time range training data age 2.1 fits two models. Model 1 limited time range \\([0, 2.1]\\) years. Therefore predict 2.1 years, predictions contain 34 NA’s. One might say correct result fitted model informative beyond age 2.1 years, hence NA’s useful plausible. comparison, model 2 uses training test data, sets wider time interval \\([0, 3]\\). consequence, model 2 produces predictions test data. predictions might useful cases. example, simulation studies often resample regenerate data, time range may vary replications. Setting boundary include largest range possible avoids problems caused NA predictions. general, make model specification independent training data, add extra knot equal slightly higher maximum time value train test data. Due sparse data, broken stick estimates boundaries can widely erratic useful interpretation. best exclude estimates plots calculations. Depending data, erratic estimates can occur left right boundaries. code block reverses age, now sparse data left boundary. consequence, need supply hide = \"left\" (instead default hide = \"right\") argument brokenstick() function. desired, one may add hide argument also plot() overwrite fit2_mirror$hide.","code":"train <- smocc_200[smocc_200$age < 2.1, ] fit1 <- brokenstick(hgt_z ~ age | id, data = train, knots = c(0, 1, 2)) fit2 <- brokenstick(hgt_z ~ age | id, data = train, knots = c(0, 1, 2, 3)) p1 <- predict(fit1, newdata = smocc_200, shape = \"vector\") p2 <- predict(fit2, newdata = smocc_200, shape = \"vector\") table(is.na(p1)) ## ## FALSE TRUE ## 1908 34 table(is.na(p2)) ## ## FALSE ## 1942 data <- smocc_200 data$age <- -data$age fit2_mirror <- brokenstick(hgt_z ~ age | id, data = data, knots = c(-2, -1, 0), hide = \"left\") plot(fit2_mirror, groups = c(10001, 10005, 10022))"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"critical-periods","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Critical periods","title":"Broken Stick Model for Irregular Longitudinal Data","text":"following question motivated development broken stick model: ages children become overweight? Knowing answer question provides handles preventive interventions counter obesity. Dietz (1994) suggested existence three critical periods obesity adult age: prenatal period, period adiposity rebound (roughly around age 5-6 years), adolescence. Obesity formed periods likely increase obesity risk adult age complications. growth period, bounded ages \\(T_1\\) \\(T_2\\), critical adult overweight following criteria hold (de Kroon et al. 2010): significant difference mean gain score \\(Z_2-Z_1\\) subjects without adult overweight; gain score \\(Z_2-Z_1\\) independent contribution \\(Z_2\\) prediction \\(Z_{\\rm adult}\\). matters \\(T_2\\) also got ; \\(Z_2\\) correlates highly \\(Z_{\\rm adult}\\), easier (.e., higher sensitivity specificity) identify children risk adult overweight. de Kroon et al. (2010) found age interval 2-6 years met criteria critical period. re-analysis tests requirements following age intervals: Birth-4 months, 4 months-1 year, 1-2 years, 2-4 years, 4-6 years, 6-10 years 10-14 years. Hence, define following break ages: Figure 8: Scatter plot BMI SDS log(age + 0.2) Terneuzen cohort data. plot shows differential amounts clustering measurements around specified break ages. Clustering tighter ages (birth, 1y, 14y) others (4m, 2y, 24y). Terneuzen Birth Cohort (de Kroon et al. 2008) comprises 2604 children born around year 1980 Terneuzen, Netherlands. Figure 8 shows body mass index (BMI) standard deviation scores (SDS) age random subset 306 children. may easily recognize scheduled visits birth, 1y 14y, figure shows observations periods less structured. Compared analysis de Kroon et al. (2010), removed knots 8 days 18 years (appear sparse data areas) added knots 4, 14 24 years. aesthetic reasons, set right boundary knot 29y, slightly higher maximum age data. control specification prevents warnings messages result -parametrized nature model. One may stabilize model restricting variance-covariance matrix, example Argyle correlation model. result, fitted trajectories stabler regions sparse data. following snippet applies Argyle model. Figure 9: Observed fitted BMI SDS trajectories six subjects predicted lmer (red) Argyle (green) models. figure illustrates fitted trajectories Argyle model stabler areas sparse data. Figure 9 shows observed fitted BMI SDS trajectories models. per cent explained variance BMI SDS similar : 84 per cent. lmer model, fitted trajectory subject 8 reveals pretty rough estimate age 24y. Persons 1259 7460 low (-2.5 SD) high (+2.5 SD) BMI SDS adult age, respectively. Note model pulls adult BMI SDS estimates (red) towards global mean, due well-known bias-variance trade (Gelman Hill 2007, 394). Pulling vigorous extremes. effect negligible average trajectories, subject 2447. Argyle model, trajectories slightly smoother stable adult ages limited data. rough estimate subject 8 gone. still gravity towards global mean knot 24y persons 1259 7460, lesser magnitude. fitted trajectories well behaved. , therefore, select kr solution analysis. identify critical periods, need predict adult overweight. Figure 9, three six subjects BMI measurement adult age. Since want results overly depend fitted extrapolations, restrict analysis sample persons adult measurement. following lines extract repeated measures 92 (306) individuals observed adult BMI. Figure 10: Fitted BMI SDS trajectories 92 subjects, 18 persons adult overweight (red = observed BMI adult age > 1.3 SDS), 74 individuals (gray) adult overweight. figure shows BMI distribution age 2y similar groups, whereas BMI ages 10y 14y highly predictive adult overweight. Figure 10 shows 92 fitted trajectories colored adult overweight status (observed BMI SDS > 1.3). evident BMI SDS ages 14y 10y highly predictive adult overweight, also hold early childhood? Also, change specific periods predict later overweight? answer questions, fit simple linear models predict observed (fitted!) BMI SDS adult age fitted BMI SDS trajectories. following code block fits two models period 4y-6y. Model m1 predicts adult BMI SDS BMI SDS 6y, explains 45.3 per cent variance. Model m2 extends model pre-gain 4y 6y. pre-gain improves prediction, matters much gained 4y 6y. case, call interval 4y-6y critical period. found model 2 explain 53.6 per cent variance, thus 8.3 per cent . anova statement performs formal test. case, pre-gain significant last predictor 6y. Thus, interval 4y-6y classifies critical period. can repeat analyzes age intervals, similar Table 3 Kenward (1987).","code":"knots <- round(c(0, 1/3, 1, 2, 4, 6, 10, 14, 24, 29), 3) labels <- c(\"birth\", \"4m\", \"1y\", \"2y\", \"4y\", \"6y\", \"10y\", \"14y\", \"24y\", \"\") ctl <- lme4::lmerControl( check.conv.grad = lme4::.makeCC(\"warning\", 0.02, NULL), check.conv.singular = lme4::.makeCC(\"ignore\", 0.001)) fit_lmer <- brokenstick(bmi.z ~ age | id, data = mice::tbc, knots = knots, boundary = c(0, 29), method = \"lmer\", control = ctl) fit_kr <- brokenstick(bmi.z ~ age | id, data = mice::tbc, knots = knots, boundary = c(0, 29), seed = 41441, cormodel = \"argyle\") tbc1 <- mice::tbc %>% filter(!is.na(ao) & first) %>% select(id, nocc, sex) tbc2 <- mice::tbc.target %>% filter(id %in% tbc1$id) prd <- predict(fit_kr, mice::tbc, x = \"knots\", shape = \"wide\", group = tbc1$id) data <- bind_cols(prd, select(tbc1, -id), select(tbc2, -id)) head(data, 3) ## # A tibble: 3 × 14 ## id `0` `0.333` `1` `2` `4` `6` `10` `14` `24` ## ## 1 8 0.371 -0.440 0.366 1.45 1.10 0.606 0.489 0.544 -0.822 ## 2 60 0.159 -0.372 -0.0442 -0.360 -0.595 -0.818 -1.03 -1.16 -1.46 ## 3 97 1.68 0.569 0.948 1.90 1.28 0.838 0.444 0.238 0.397 ## # … with 4 more variables: nocc , sex , ao , ## # bmi.z.jv m1 <- lm(bmi.z.jv ~ `6`, data) m2 <- lm(bmi.z.jv ~ `6` + I(`6`-`4`), data) anova(m1, m2) ## Analysis of Variance Table ## ## Model 1: bmi.z.jv ~ `6` ## Model 2: bmi.z.jv ~ `6` + I(`6` - `4`) ## Res.Df RSS Df Sum of Sq F Pr(>F) ## 1 90 74.3 ## 2 89 63.4 1 10.8 15.2 0.00019 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"time-to-time-correlations","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Time-to-time correlations","title":"Broken Stick Model for Irregular Longitudinal Data","text":"conditional gain score defined (Cole 1995) \\[ {\\rm conditional}\\ Z_{\\rm gain} = \\frac{Z_2 - rZ_1}{\\sqrt{1-r^2}}, \\] \\(Z_1\\) \\(Z_2\\) standard deviation scores times \\(T_1\\) \\(T_2\\), \\(T_2>T_1\\), \\(r\\) correlation \\(Z_1\\) \\(Z_2\\). conditional gain corrects regression mean, selling point traditional velocity measures less sensitive measurement error (van Buuren 2007). practical difficulty obtain \\(r\\) given \\(T_1\\) \\(T_2\\). time--time correlation matrix needs known. Also, need interpolate \\(r\\) \\(T_1\\) \\(T_2\\) differs tabulated ages. broken stick model provides estimate time--time correlation matrix. brokenstick object stores variance-covariance matrix \\(\\Omega\\) random effects. perfectly fitting model (\\(\\sigma^2 = 0\\)) \\(\\Omega\\) equals time--time covariance matrix, get_omega(fit, cor = TRUE) gives desired time--time correlation matrix. \\(\\sigma^2 > 0\\) \\(\\Omega\\) overestimates covariances observed data. general, need add within-residual variance estimate diagonal, thus \\(\\Omega + \\hat\\sigma^2 (n_i)\\) estimate time--time covariance matrix. child growth, expect correlation tapers difference \\(T_1\\) \\(T_2\\) grows. Also, fixed interval \\(T_2-T_1\\) expect correlation increase age. Altering number location knots may change . often useful scan time--time correlation matrix gross deviations expectations. happens, one simplify model, example, subjecting \\(\\Omega\\) correlation model. code fits model 21 equidistant breakpoints, likely large enough purposes. works restricts covariance-matrix Argyle correlation model, summarizes information just two parameters. may extract re-estimate parameters create one-liner calculating \\(r\\). indefinitely add breakpoints. Suppose double number knots setting knots = seq(0, 2, 0.05). even kr able cope abort Error: Sigma symmetric positive. Thus, always, sensible ask software .","code":"fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = 1:4/2) omega <- get_omega(fit) t2t <- omega + diag(fit$sigma2, ncol(omega)) round(cov2cor(t2t), 2) ## age_0 age_0.5 age_1 age_1.5 age_2 ## age_0 1.00 0.57 0.42 0.37 0.31 ## age_0.5 0.57 1.00 0.76 0.71 0.67 ## age_1 0.42 0.76 1.00 0.80 0.78 ## age_1.5 0.37 0.71 0.80 1.00 0.82 ## age_2 0.31 0.67 0.78 0.82 1.00 fit <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = seq(0, 2, 0.1), cormodel = \"argyle\") omega <- get_omega(fit) t2t <- omega + diag(fit$sigma2, ncol(omega)) dim(t2t) ## [1] 21 21"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"profile-analysis","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Profile analysis","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Profile analysis (Morrison 1976; Johnson Wichern 1988) refers linear multivariate linear methods test differences population means treatment effects, typically regression analysis multivariate analysis variance (MANOVA). methods assume independence subjects, organize data subject level, express parameters interest linear combinations outcomes, like change scores, means derived quantities. Krone et al. (2020) report statistical analysis using linear mixed model time-varying individual subject data. section re-analyzes data Figure 4 using broken stick model. data available brokenstick::weightloss object. Figure 11: Daily body weight (KG) 12 subjects followed 63 days one three conditions. graph illustrates irregular nature data. trajectories almost complete regular, whereas others miss many daily measurements display surprising jumps around average weight level. Figure 11 charts daily body weight measurements twelve individuals followed nine weeks. investigators subdivided total duration three periods three weeks. Period one (week 1-3) acted control period. period 2 (week 4-6), investigators stimulated participants restrict food intake, period 3 (week 7-9) experimenters promoted physical activity. Subjects 4 12 received interventions reverse order. See Krone et al. (2020) detail. subjects adhere quite well data collection design. trajectories show gaps due missed measurements. extreme example trajectory hovers around value 95 kilograms (KG). curves display stretches lines, suggesting missed measurements linearly interpolated. One series shows surprising spikes, likely measurement errors. , data perfectly illustrate inescapable imperfections real data. remainder section discusses two ways estimate effect diet physical activity body weight.","code":"data <- brokenstick::weightloss ggplot(data, aes(day, body_weight, group = subject, color = condition)) + scale_x_continuous(name = \"Day\", breaks = c(0, 21, 42, 63), minor_breaks = c(7, 14, 28, 35, 49, 56)) + ylab(\"Body weight (KG)\") + geom_line() + geom_point(size = 0.7) + theme_light() + theme(legend.position = \"bottom\")"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"constant-model","dir":"Articles > Manual","previous_headings":"6 Applications > 6.3 Profile analysis","what":"Constant model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 12: Constant model. Observed fitted trajectories model summarizes experimental period constant. estimated level approximately mean measurements made period. model produces sudden jumps ages condition changes thus fails describe data well. model underlying Figure 12 summarizes trajectory within period constant, mean. obtain estimate means setting degree = 0 argument. model gives fair representation trajectory subjects 9 (persistent downward trend), 1 5 (trend). hand, model fails capture patterns subjects 2, 4 8 (rebound period 3) 11 (inverse rebound). straightforward quantify effects Diet Activity relative Control. next code snippet calculates effects per person, accounting intervention order reversal subjects 4 12. average weight caloric restriction 564 grams lower control. find 848 grams lower body weight stimulate physical activity. tempted believe exercise reduces weight diet. However, except subjects 4 12, investigators administered activity treatment diet treatment, difference relative control represents combined effect diet activity body weight. might relevant study difference training diet (third column). average difference -284 grams suggests diet effective physical activity. Realize also estimate entirely satisfactory. First, subjects 4 12 reversed administration, difference make sense . Second, anyone tried lose weight can attest, “quick wins” likely period 2 period 3. Although possible account sequence effects, intuitive analysis data.","code":"data <- brokenstick::weightloss fit0 <- brokenstick(body_weight ~ day | subject, data, knots = c(0, 21, 42, 63), degree = 0, method = \"lmer\", hide = \"none\") plot(fit0, size_y = 0, color_y = rep(\"gray\", 2), scales = \"free_y\", xlab = \"Day\", ylab = \"Body weight (KG)\", n_plot = 12, ncol = 4) prd <- data.frame(predict(fit0, data, x = \"knots\", shape = \"wide\")) control <- prd[, 2] diet <- prd[, 3] diet[c(4, 12)] <- prd[c(4, 12), 4] activity <- prd[, 4] activity[c(4, 12)] <- prd[c(4, 12), 3] effects <- 1000 * data.frame( diet_control = diet - control, activity_control = activity - control, activity_diet = activity - diet) round(effects) ## diet_control activity_control activity_diet ## 1 174 179 5 ## 2 -1055 -1759 -704 ## 3 961 1045 84 ## 4 -1846 -723 1123 ## 5 371 149 -223 ## 6 -1582 -3269 -1687 ## 7 -158 -514 -356 ## 8 -614 -1057 -443 ## 9 -1166 -2039 -872 ## 10 -594 -1210 -616 ## 11 63 -559 -621 ## 12 -1322 -425 897 round(colMeans(effects)) ## diet_control activity_control activity_diet ## -564 -848 -284"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"broken-stick-model-1","dir":"Articles > Manual","previous_headings":"6 Applications > 6.3 Profile analysis","what":"Broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Figure 13: Broken stick model. Observed fitted trajectories model summarizes experimental period line. slope indicates change period. model connects lines adjacent periods provides informative description data. Figure 13 shows data Figure 12 now fitted linear broken stick model. model also suggests persistent downward trend subject 9 absence trend participants 1 5. Also, model now correctly identifies prominent zig-zag patterns persons 2, 4, 8 11 across three experimental periods. natural way quantify effect intervention calculate -estimate per period. example, person 2 effect diet \\(60,933 - 63,671 = -2,738\\) grams, activity \\(62,635 - 60,933 = +1,701\\) grams. following code accounts alternate treatment ordering subjects 4 12. average effects -201 grams (control), -683 grams (diet) -301 grams (activity). Although statistically significant, slight decrease 201 grams control period suggests weight monitoring may motivate participant lose weight. effect estimates diet activity similar magnitude . Still, can sizeble discrepancies individual level, e.g., subjects 2 11. may obtain simple estimate sequence effect linear regression Variable y change grams observed periods 2 3, activity dummy variable treatment (0 = diet, 1 = activity) activity2 dummy variable indicating activity occurred period 2 (0 = , 1 = yes). average loss weight per period equal 492 grams. second model shows diet reduces body weight activity (382 grams). third model indicates activity applied period 2 effective period 3, reduces weight additional 123 grams. course, bear mind calculated results individuals. Hence, sensitive substantial estimation error. application demonstrates broken stick model can effectively capture rapid linear changes experiments. Even though actual timing observations may erratic, easy define, interpret calculate intuitive effect estimates individual level. Note analysis assumed instantaneous effect interventions. expect delay, may right-shift knots days re-estimate broken stick model. varying number days, may able detect optimal delay factor.","code":"ctl_lmer <- lme4::lmerControl( check.conv.grad = lme4::.makeCC(\"warning\", tol = 0.01)) fit1 <- brokenstick(body_weight ~ day | subject, data, knots = c(0, 21, 42, 63), method = \"lmer\", control = ctl_lmer, hide = \"none\") plot(fit1, size_y = 0, color_y = rep(\"gray\", 2), size_yhat = 1.5, scales = \"free_y\", , xlab = \"Day\", ylab = \"Body weight (KG)\", n_plot = 12, ncol = 4) prd <- data.frame(predict(fit1, data, x = \"knots\", shape = \"wide\")) control <- prd[, 3] - prd[, 2] diet <- prd[, 4] - prd[, 3] diet[c(4, 12)] <- prd[c(4, 12), 5] - prd[c(4, 12), 4] activity <- prd[, 5] - prd[, 4] activity[c(4, 12)] <- prd[c(4, 12), 4] - prd[c(4, 12), 3] effects <- 1000 * data.frame( control = control, diet = diet, activity = activity) round(effects) ## control diet activity ## 1 -303 459 -411 ## 2 95 -2738 1701 ## 3 847 479 570 ## 4 117 682 -2168 ## 5 637 -606 659 ## 6 -756 -2594 -833 ## 7 251 -783 277 ## 8 -297 -1112 349 ## 9 -1006 -1389 -424 ## 10 -190 -1096 -290 ## 11 -908 929 -2573 ## 12 -902 -423 -468 round(colMeans(effects)) ## control diet activity ## -201 -683 -301 df <- data.frame(y = 1000 * c(diet, activity), activity = rep(c(0, 1), each = 12), activity2 = rep(c(rep(0, 3), 1, rep(0, 7), 1), 2)) coef(lm(y ~ 1, data = df)) ## (Intercept) ## -492 coef(lm(y ~ activity, data = df)) ## (Intercept) activity ## -683 382 coef(lm(y ~ activity + activity2, data = df)) ## (Intercept) activity activity2 ## -662 382 -123"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"problem","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Problem","title":"Broken Stick Model for Irregular Longitudinal Data","text":"growth chart visualizes individual trajectory relative set centile lines. may store centile line set coordinates relatively dense age grid. connect adjacent vertices straight line, centile appear smooth time. However, plotting method runs trouble ages wide apart. section shows can create realistic interpolation sparse time data.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpolation-in-measurement-scale","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Interpolation in measurement scale","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Suppose measured length boy ages 1 month (52.6 cm) 14 months (81.7 cm). following code block uses AGD::y2z() function convert measurements SDS relative reference Fourth Dutch Growth Study. Figure 14: effect three interpolation methods (linear cm (blue), linear SDS (red), broken stick model (green)). method, vertical line indicates age interpolated curve crosses mean age-conditional length distribution. linear methods results unrealistic trajectories intermediate ages. example, points blue lines low. Interpolation broken stick method alternative correctly describes faster growth first months. period boy grows moderately short (-1.0 SD month 1) relatively tall (+1.0 SD month 14). Figure 14 shows usual representation growth chart straight line drawn two values. Due concave shape centile lines, straight line connects two measurements starts -1.0 SD, touches -2.0 SD centile around 4.5 months, back -1.0 SD age 7.5 months, crosses 0.0 SD line 11.5 months, ends +1.0 SD 14 months. right hand side graph portrays interpolated growth curve SDS scale. Since length growth infancy linear time, finding real growth curve like extremely unlikely. Since just two data points smoothing data help either.","code":"boy <- data.frame(x = c(1, 14), y = c(52.6, 81.7)) ref <- AGD::nl4.hgt boy$z <- AGD::y2z(y = boy$y, x = boy$x/12, sex = \"M\", ref = ref) boy$z ## [1] -0.980 0.994"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpolation-in-the-sds-scale","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Interpolation in the SDS scale","title":"Broken Stick Model for Irregular Longitudinal Data","text":"first alternative apply linear interpolation SDS scale. option attractive centile lines straight SDS scale. red curves Figure 14 illustrate interpolation SDS scale. definition, line connects measurements straight SDS score scale. cm scale, representation realistic pleasing eye. curve crosses 0 SD line halfway, 7.5 months. approach considerable improvement interpolation \\(Y\\)-scale, still ideal. assumption underlying interpolation SDS increment constant across time. assumption false , however. Since length growth faster first half-year, expect larger share increment occur earlier months. words, cross-point 7.5 months late.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"interpolation-by-the-broken-stick-model","dir":"Articles > Manual","previous_headings":"6 Applications > 6.4 Curve interpolation","what":"Interpolation by the broken stick model","title":"Broken Stick Model for Irregular Longitudinal Data","text":"second alternative model-based interpolation. Assuming availability fitted broken stick model, specify time grid, say twice month, predict length ages given data observed trajectory. expected curve represents likely values model intermediate ages. following code calculates relevant estimates fit_200 fitted model: green curve Figure 14 shows results broken stick model. curve measurement scale represents likely course according broken stick model. Note now child realizes larger share change first months. result, cross-point predicted value intersects 0 SD line now around 4.5 months, considerably earlier obtained two interpolation methods. right hand side plot confirms steeper slope first part. Note method treats rising declining curves alike. example, boy’s length 57 cm month 1 (+1.0 SD) 76 cm month 14 (-1.0 SD), cross-point also around 4.5 months (shown). Observe method leaves world pure interpolation moves towards approximation data model. observed predicted lengths exactly equal. difference small may hardly notice discrepancy plotted measurement scale, conspicuous plotted SDS. Thanks added knowledge child growth process, broken stick model provides realistic expected trajectory intermediate ages. Note green curve entirely smooth, due linearity assumption model. create smoother curve using finer grid break points. Alternatively, use correlation model predicting correlation intermediate ages. latter option convenient, currently possible predict(). Adding support correlation models area development.","code":"age <- round(seq(1, 14, 0.5), 3) z <- rep(NA, length(age)) z[1] <- boy$z[1]; z[length(z)] <- boy$z[2] zout <- predict(fit_200, x = age/12, y = z, shape = \"vector\") yout <- AGD::z2y(x = age/12, z = zout, ref = ref)"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"multiple-imputation","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Multiple imputation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Remember Section 5.5 broken stick estimates conditional means. may tempted analyze estimates “just data”, variability real data. example, suppose calculate correlation matrix broken stick estimates. know values matrix exceed underlying observed data. accounting fact leads overconfident predictions results good true. Multiple imputation (Rubin 1987; van Buuren 2018b) restores variability adding noise. may fit standard complete-data software imputed data, obtain valid regression weights, confidence intervals \\(p\\) values wide range conditions. default, method kr executes 200 iterations Kasim-Raudenbush sampler. nimp argument control_kr() function specifies number multiple imputations. following call brokenstick() function creates plots 20 imputations missing outcome (hgt_z ). Figure 15: Observed data (blue) 20 imputed trajectories (gray) three subjects SMOCC data. Imputed trajectories possible realizations observed data hypothetical case observations made specified break ages. Note pattern child 10001 certain child 10022. Figure 15 displays observed data three persons plotted top 20 imputed trajectories. within-person within-time average gray trajectories approximates broken stick estimate (shown ). observed curve panel occasionally strays towards boundaries gray bundle. behavior expected indicates blue curve performs like gray curve. Section 6.2 showed can estimate time--time correlation matrix. alternative way calculate imputed data, follows: Another important application multiply-imputed curves obtain correct confidence intervals \\(p\\) values estimates scientific interest. convenient way convert brokenstick object object class \"mids\", defined mice package. brokenstick package currently features perform conversion.","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) data <- bind_rows(smocc_200[!is.na(smocc_200$hgt_z), ], expand.grid(id = unique(smocc_200$id), age = knots)) fit_kr <- brokenstick(hgt_z ~ age | id, data = data, knots = knots, nimp = 20, seed = 15244) plot(fit_kr, show = c(TRUE, FALSE, TRUE), group = c(10001, 10005, 10022), xlab = \"Age (years)\", ylab = \"Length (SDS)\") cormat <- cor(matrix(t(fit_kr$imp), ncol = length(knots))) dimnames(cormat) <- list(knots, knots) round(cormat, 2) ## 0 0.0833 0.1667 0.25 0.5 0.75 1 1.25 1.5 2 ## 0 1.00 0.68 0.70 0.63 0.47 0.43 0.38 0.33 0.32 0.24 ## 0.0833 0.68 1.00 0.81 0.79 0.70 0.58 0.53 0.51 0.50 0.39 ## 0.1667 0.70 0.81 1.00 0.81 0.73 0.60 0.52 0.49 0.52 0.42 ## 0.25 0.63 0.79 0.81 1.00 0.75 0.64 0.58 0.56 0.53 0.46 ## 0.5 0.47 0.70 0.73 0.75 1.00 0.83 0.81 0.73 0.75 0.65 ## 0.75 0.43 0.58 0.60 0.64 0.83 1.00 0.84 0.77 0.77 0.71 ## 1 0.38 0.53 0.52 0.58 0.81 0.84 1.00 0.84 0.81 0.76 ## 1.25 0.33 0.51 0.49 0.56 0.73 0.77 0.84 1.00 0.84 0.82 ## 1.5 0.32 0.50 0.52 0.53 0.75 0.77 0.81 0.84 1.00 0.83 ## 2 0.24 0.39 0.42 0.46 0.65 0.71 0.76 0.82 0.83 1.00"},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"curve-matching","dir":"Articles > Manual","previous_headings":"6 Applications","what":"Curve matching","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Curve matching (van Buuren 2014) tool assist interpretation prediction individual growth curves. idea follows. Suppose measure growth target child half year plot measurements onto growth chart. Curve matching nearest-neighbor technique relies historical growth data. finds, say, ten children similar target child, adds curves matches child’s chart. matching done right, bundle historic growth curves suggests target child develop future. Figure 16: Curve matching. Predict infant length 14 months given length data 6 months using 10 matches. red curve observed data target child. bundle gray curves observed length curves children match trajectory target child month 6. blue line represents likely future trajectory target child towards month 14. variation gray curves represents amount uncertainty trajectory prediction. Figure 16 screen shot demo Shiny app Joint Automatic Measurement Evaluation System (JAMES). red curve corresponds five measurements target child made first six months. ten gray curves historic growth curves ten matched children. may define similarity many ways. use linear model predict length age 14m previous length data. distance target child another child equal difference predicted values. procedure lifts data matches database, plots observed growth curves onto chart gray curves. method finding nearest neighbors known predictive mean matching grown powerful technique missing data (van Buuren 2018b). bundle gray curves indicates possible future trajectories target child. wider bundle, uncertain future growth (Toet et al. 2019). mean bundle likely path. Graphically dotted blue curve last measurement age outcome. Let’s look numerical example. split data one target child 199 donor children, fit broken stick model donor set. time points donor data enter broken stick model. Note target_data contains observations first five visits. now fit prediction model child-level donor data. prediction model contains broken stick estimates length SDS 6 months, well sex, gestational age birth weight covariates. next step extract model predictions donors target find ten closest donors. steps contain basic ingredients find_matches() function chartplotter package (van Buuren 2021a). Finally, let us study observed fitted trajectories ten matches. Figure 17: Curve matching. Observed (blue) fitted (red) trajectories 10 closest matches subject 10001. Fitted values outcome age (1.25y) close predicted value target child (0.101 SD). ten trajectories close prediction (0.101 SD) target child age 1.25 years. Note guarantee histories identical. matches relatively flat curves, (10051, 11023, 11086) show striking rising patterns. Nevertheless, candidates best terms model prediction. wish curves matches first six months closer target case, consider alternative metrics. simple measure sum squares differences broken stick estimates. selection may visually pleasing, expense prediction accuracy. hand, less tied setting one particular future time point, measures may work better “future” vaguely defined time interval. still open research question strike balance. Whatever objectives preferences user might , curve matching methodology, illustrated , tremendous flexibility easy adapt.","code":"donor_data <- smocc_200 %>% filter(id != \"10001\") target_data <- smocc_200 %>% filter(id == \"10001\" & age < 0.51) knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit <- brokenstick(hgt_z ~ age | id, data = donor_data, knots = knots, seed = 15244) covariates <- donor_data %>% group_by(id) %>% slice(1) bse <- predict(fit, donor_data, x = \"knots\", shape = \"wide\") donors <- bind_cols(covariates, select(bse, -id)) model <- lm(`1.25` ~ `0` + `0.0833` + `0.1667` + `0.25` + `0.5` + sex + ga + bw, data = donors) summary(model) ## ## Call: ## lm(formula = `1.25` ~ `0` + `0.0833` + `0.1667` + `0.25` + `0.5` + ## sex + ga + bw, data = donors) ## ## Residuals: ## Min 1Q Median 3Q Max ## -1.3328 -0.2567 -0.0151 0.2634 1.4653 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 4.87e-01 8.99e-01 0.54 0.589 ## `0` 6.74e-02 5.33e-02 1.27 0.207 ## `0.0833` 5.89e-02 8.69e-02 0.68 0.499 ## `0.1667` -2.55e-01 9.92e-02 -2.57 0.011 * ## `0.25` -2.16e-01 1.07e-01 -2.01 0.046 * ## `0.5` 1.21e+00 7.54e-02 16.07 <2e-16 *** ## sexmale 9.13e-02 6.42e-02 1.42 0.157 ## ga -7.05e-03 2.25e-02 -0.31 0.754 ## bw -7.53e-05 1.09e-04 -0.69 0.491 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.436 on 190 degrees of freedom ## Multiple R-squared: 0.777, Adjusted R-squared: 0.767 ## F-statistic: 82.5 on 8 and 190 DF, p-value: <2e-16 donors_pred <- predict(model) names(donors_pred) <- donors$id target <- bind_cols( slice(target_data, 1), select(predict(fit, target_data, x = \"knots\", shape = \"wide\"), -id)) target_pred <- predict(model, newdata = target) matches <- sort(abs(donors_pred - target_pred))[1:10] matches ## 11013 10032 11035 10093 10051 11063 11086 11083 11102 ## 0.00422 0.00578 0.01833 0.01889 0.02507 0.02657 0.03069 0.03744 0.05118 ## 11049 ## 0.05922 ids <- as.numeric(names(matches)) plot(fit, group = ids, xlim = c(0, 1.4), size_y = 1, size_yhat = 0, xlab = \"Age (years)\", ylab = \"Length (SDS)\", ncol = 5)"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"overview-1","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Overview","title":"Broken Stick Model for Irregular Longitudinal Data","text":"paper introduces new approach solve problem irregular longitudinal data. method absorbs time-dependent information set broken stick estimates subject level. primary advantage simplifies analysis splitting modelling problem two steps. First, solve timing problem, solve substantive/scientific problem. method mathematically simple, conceptually appealing, yet principled.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"distinctive-features","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Distinctive features","title":"Broken Stick Model for Irregular Longitudinal Data","text":"assumptions model cover many cases practical interest: straight line breakpoints, multivariate normal distribution random effects, MAR assumption including future data. Despite relatively low number model parameters, possible obtain close fit data, sometimes almost perfect reconstruction (c.f., Figure 7). need specify equidistant breakpoints. Applications human growth development often natural using non-uniformly spaced knots, easy model. Many people find easier understand raw data values summaries. broken stick model invites visualization actual data points time makes easy portray uncertainty bundle curves. direct vizualisation options contribute explainable responsible personalized analyzes appeal broad user group.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"current-limitations","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Current limitations","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model, presented , uses just three variables: time, measurement group. design choice simplifies interpretation estimation. lack covariates model implies transformation irregular data repeated measures identical every subject. long residual error small, relations ---model variables thus remain intact. possibility include covariates second-round enhances modular modern analytic pipelines. Yet, prefer direct estimation effects one extensive analysis. current package support covariates. broken stick method intended aligning observations, every individual number location breakpoints. technique assumes subjects share time axis. applications, synchronization start natural (e.g., birth, start experiment), easy . cases, one might prefer anchor middle, e.g., menarche, occurs different ages different individuals (Naumova, Must, Laird 2001), scientific interest happens anchor. also make sense fasten end, e.g., graduation death. choice anchor may matter less cyclic processes. example, weekly data may important anchor day week actual date age. Irrespective actual timings observed data, number location breakpoints identical subjects. method less suited applications sensible common time axis, breakpoints vary individuals.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"software","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Software","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Kasim-Raudenbush sampler (Kasim Raudenbush 1998) fast flexible. produces estimates residual error variance per subject, can accommodate correlation models supports multiple imputation ---box. research needed establish statistical properties especially compared lmer() established methods. also interesting study suitability correlation models implemented lme4qtl package (Ziyatdinov et al. 2018). training data stored, instances light \"brokenstick\" class objects tiny, often 15–20 Kb. Features implemented, useful future versions include separate impute() function inputs class \"brokenstick\" returns class \"mids\", Trelliscope (Hafen Schloerke 2020) viewer quickly peruse hundreds individual model fits, extension multivariate time-varying child-level data, generalization degree > 1 support quadratic cubic splines.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"methodological-advances","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Methodological advances","title":"Broken Stick Model for Irregular Longitudinal Data","text":"primary modelling task user set proper knot locations. One might envision scenarios want search “best” locations. yet clear , far automate knot placement strategies. need insight statistical properties procedures execute analysis sequence steps. relative pro’s con’s choices multiple imputation versus random effects yet fully understood. current procedure assumes within-person error constant across time points. However, might expect observing data close breakpoint reduce uncertainty estimate. applications, might require estimate equal observed data value observation time coincides breakpoints. models scenarios considerably complicated, also increase efficiency.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"conclusion-1","dir":"Articles > Manual","previous_headings":"7 Conclusion","what":"Conclusion","title":"Broken Stick Model for Irregular Longitudinal Data","text":"paper highlighted various applications broken stick model: Critical periods, time--time correlation, profile analysis, curve interpolation, multiple imputation personalized prediction. applications certainly exhaust potential model. hope availability software stimulate creative uses, ideas experiments.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"computational-setup","dir":"Articles > Manual","previous_headings":"","what":"Computational setup","title":"Broken Stick Model for Irregular Longitudinal Data","text":"running Mac Studio, MacOS Venture, V 13.1, 32GB RAM R version 4.2.2 (2022-10-31) brokenstick version 2.5.0 (2023-03-22).","code":""},{"path":"https://growthcharts.org/brokenstick/articles/manual/manual.html","id":"acknowledgment","dir":"Articles > Manual","previous_headings":"","what":"Acknowledgment","title":"Broken Stick Model for Irregular Longitudinal Data","text":"thank editor reviewers suggestions helped improve manuscript software. work supported Bill & Melinda Gates Foundation. contents sole responsibility author may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"background","dir":"Articles","previous_headings":"","what":"Background","title":"Help for old friends","text":"brokenstick package three major interfaces: version brokenstick 0.62.1 (May 2020) version brokenstick 1.1.1 (May 2020 - Nov 2021) Versions higher brokenstick 2.0.0 (Nov 2021 - now) document summarises main changes brokenstick 2.0.0. See “Help old friends” brokenstick 1.1.1 overview previous changes 0.75.0 1.1.1.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"main-changes","dir":"Articles","previous_headings":"Background","what":"Main changes","title":"Help for old friends","text":"Function brokenstick() version 2.0.0 sets Kasim-Raudenbush sampler default method. former method lme4::lmer() remains available setting method = \"lmer\" argument. Version 2.0.0 adopts variable names coda package (e.g., start, end, thin, niter, ) stores results Kasim-Raudenbush sampler objects class mcmc. method = \"kr\" one may now inspect solution sampler standard functions coda package. method = \"lmer\" can apply functions lme4 package merMod objects. Version 2.0.0 redefines brokenstick class. New entries include call, formula, internal, sample, light, data, imp mod. Removed entries knots (renamed internal) draws (renamed imp). may omit newdata argument training data. Setting light = TRUE creates small version brokenstick object. Objects class brokenstick backwards compatible, one regenerate objects class brokenstick order use newer features 2.0.0. Version 2.0.0 conforms classic model fitting interface R. Renames new_data argument newdata conform predict.lm(). Methods plot() predict() longer require newdata argument. special cases predict() updated explained documentation examples. Version 2.0.0 adds methods coef(), fitted(), model.frame(), model.matrix(), print() summary() brokenstick object. Simplifies algorithmic control. Renames control_brokenstick() set_control() removes layer control list. Added support hide argument user-oriented functions. Automatic suppression last knot.","code":""},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"minor-changes","dir":"Articles","previous_headings":"Background","what":"Minor changes","title":"Help for old friends","text":"Stabilises rgamma() calls KR-algorithm edge cases. predict_brokenstick() can now work (internal) training (external) test data. Removes superfluous type argument predict.brokenstick() Adds function get_omega() extract variance-covariance matrix broken stick estimates Improves error messages edge cases test-brokenstick_edge.R Perform stricter tests arguments brokenstick() Introduces argument warn_splines make_basis() suppress uninteresting warns splines::bs() Removes superfluous knotnames argument make_basis() Argument x make_basis() now vector instead column vector Introduces new xname argument make_basis() set xname","code":""},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"install-legacy-version","dir":"Articles","previous_headings":"","what":"Install legacy version","title":"Help for old friends","text":"recommend changing code reflect changes run brokenstick 2.4.0 higher. needed, version 1.1.1 can installed ","code":"library(\"devtools\") install_github(\"growthcharts/brokenstick@9b969af\")"},{"path":[]},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"example-1-fit-model","dir":"Articles","previous_headings":"Examples","what":"Example 1: Fit model","title":"Help for old friends","text":"Fit model, brokenstick package version 0.75.0 - 1.1.1: Fit model, brokenstick package version 2.4.0:","code":"library(brokenstick) data <- brokenstick::smocc_200 # formula interface fit1 <- brokenstick(hgt.z ~ age | id, data) # XY interface - numeric vector # Deprecated in v2.0.0 fit2 <- with(data, brokenstick(age, hgt.z, id)) # XY interface - data.frame # Deprecated in v2.0.0 fit3 <- with(data, brokenstick(data.frame(age), hgt.z, id)) # XY interface - matrix # Deprecated in v2.0.0 tt <- as.matrix(data[, c(1, 2, 7)]) fit4 <- brokenstick(tt[, \"age\", drop = FALSE], tt[, \"hgt.z\", drop = FALSE], tt[, \"id\", drop = FALSE]) library(brokenstick) data <- brokenstick::smocc_200 # formula interface fit1 <- brokenstick(hgt_z ~ age | id, data)"},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"example-2-predict-model","dir":"Articles","previous_headings":"Examples","what":"Example 2: Predict model","title":"Help for old friends","text":"Predict model, brokenstick package version 0.75.0 - 1.1.1: Predict model, brokenstick package version 2.4.0:","code":"# predict at observed data p1 <- predict(fit1, data) # predict at knots p2 <- predict(fit1, data, x = \"knots\") # predict at both observed data and knots p3 <- predict(fit1, data, x = \"knots\", strip_data = FALSE) # predict knots, broad matrix p4 <- predict(fit1, data, x = \"knots\", shape = \"wide\") # predict at observed data p1 <- predict(fit1) # predict at knots p2 <- predict(fit1, x = \"knots\", include_data = FALSE) # predict at both observed data and knots p3 <- predict(fit1, x = \"knots\") # predict knots, broad matrix p4 <- predict(fit1, x = \"knots\", shape = \"wide\")"},{"path":"https://growthcharts.org/brokenstick/articles/oldfriends.html","id":"example-3-plot-model","dir":"Articles","previous_headings":"Examples","what":"Example 3: Plot model","title":"Help for old friends","text":"Plot trajectories, brokenstick package version 0.75.0 - 1.1.1: Plot trajectories, brokenstick package version 2.4.0:","code":"ids <- c(10001, 10005, 10022) plot(fit1, data, group = ids, what = \"all\") ids <- c(10001, 10005, 10022) plot(fit1, group = ids, hide = \"none\")"},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"objective","dir":"Articles","previous_headings":"","what":"Objective","title":"Check perfect model","text":"general, broken stick model smoothes observed growth trajectory. happens observations already aligned break ages? model perfectly represent data? covariance matrix random effects (\\(\\Omega)\\) equal covariance measurements? \\(\\sigma^2\\) equal zero?","code":""},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"data-generation","dir":"Articles","previous_headings":"","what":"Data generation","title":"Check perfect model","text":"adapt code http://www.davekleinschmidt.com/sst-mixed-effects-simulation/simulations_slides.pdf generate test data: choose perfect situation \\(\\sigma^2 = 0\\) noisy case \\(\\sigma^2 = 1\\) ages align perfectly. wish reproduce correlation matrix among \\(y\\)’s mixed model estimates. target correlation matrix :","code":"library(\"plyr\") library(\"mvtnorm\") make_data_generator <- function(resid_var = 1, ranef_covar = diag(c(1, 1)), n = 100 ) { ni <- nrow(ranef_covar) generate_data <- function() { # sample data set under mixed effects model with random slope/intercepts simulated_data <- rdply(n, { b <- t(rmvnorm(n = 1, sigma = ranef_covar)) epsilon <- rnorm(n = length(b), mean = 0, sd = sqrt(resid_var)) b + epsilon }) data.frame( subject = rep(1:n, each = ni), age = rep(1:ni, n), simulated_data) } } resid_var <- 0 resid_var <- 1 set.seed(77711) covar <- matrix(c(1, 0.7, 0.5, 0.3, 0.7, 1, 0.8, 0.5, 0.5, 0.8, 1, 0.6, 0.3, 0.5, 0.6, 1), nrow = 4) gen_dat <- make_data_generator(n = 10000, ranef_covar = covar, resid_var = resid_var) data <- gen_dat() head(data) ## subject age .n X1 ## 1 1 1 1 -0.9478 ## 2 1 2 1 -2.0837 ## 3 1 3 1 -2.6512 ## 4 1 4 1 -2.5526 ## 5 2 1 2 -0.0825 ## 6 2 2 2 -1.2707 library(\"tidyr\") library(\"dplyr\") ## ## Attaching package: 'dplyr' ## The following objects are masked from 'package:plyr': ## ## arrange, count, desc, failwith, id, mutate, rename, summarise, ## summarize ## The following objects are masked from 'package:stats': ## ## filter, lag ## The following objects are masked from 'package:base': ## ## intersect, setdiff, setequal, union d <- as_tibble(data[,-3]) broad <- t(spread(d, subject, X1))[-1,] cor(broad) ## [,1] [,2] [,3] [,4] ## [1,] 1.000 0.350 0.255 0.161 ## [2,] 0.350 1.000 0.406 0.246 ## [3,] 0.255 0.406 1.000 0.313 ## [4,] 0.161 0.246 0.313 1.000"},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"fit-model","dir":"Articles","previous_headings":"","what":"Fit model","title":"Check perfect model","text":"Fit broken stick model, knots specified ages 1:4.","code":"library(\"brokenstick\") knots <- 1:3 boundary <- c(1, 4) fit <- brokenstick(X1 ~ age | subject, data, knots = knots, boundary = boundary, method = \"lmer\") ## Warning: number of observations (=40000) <= number of random effects (=40000) ## for term (0 + age_1 + age_2 + age_3 + age_4 | subject); the random-effects ## parameters and the residual variance (or scale parameter) are probably ## unidentifiable ## Warning in checkConv(attr(opt, \"derivs\"), opt$par, ctrl = control$checkConv, : ## Model failed to converge with max|grad| = 0.0323545 (tol = 0.002, component 1) omega <- get_omega(fit, hide = \"no\") beta <- coef(fit, hide = \"no\") sigma2 <- fit$sigma2 round(beta, 2) ## age_1 age_2 age_3 age_4 ## -0.02 -0.02 0.01 0.01 round(sigma2, 4) ## [1] 0.818 # correlation random effects round(covar, 3) ## [,1] [,2] [,3] [,4] ## [1,] 1.0 0.7 0.5 0.3 ## [2,] 0.7 1.0 0.8 0.5 ## [3,] 0.5 0.8 1.0 0.6 ## [4,] 0.3 0.5 0.6 1.0 round(omega, 2) ## age_1 age_2 age_3 age_4 ## age_1 1.23 0.71 0.52 0.33 ## age_2 0.71 1.16 0.82 0.49 ## age_3 0.52 0.82 1.22 0.63 ## age_4 0.33 0.49 0.63 1.17 # covariances measured data round(omega + diag(sigma2, 4), 3) ## age_1 age_2 age_3 age_4 ## age_1 2.052 0.706 0.521 0.326 ## age_2 0.706 1.982 0.816 0.489 ## age_3 0.521 0.816 2.034 0.630 ## age_4 0.326 0.489 0.630 1.992 round(cov(broad), 3) ## [,1] [,2] [,3] [,4] ## [1,] 2.052 0.706 0.521 0.326 ## [2,] 0.706 1.982 0.816 0.489 ## [3,] 0.521 0.816 2.034 0.630 ## [4,] 0.326 0.489 0.630 1.992 # convert to time-to-time correlation matrix round(cov2cor(omega + diag(sigma2, 4)), 3) ## age_1 age_2 age_3 age_4 ## age_1 1.000 0.350 0.255 0.161 ## age_2 0.350 1.000 0.406 0.246 ## age_3 0.255 0.406 1.000 0.313 ## age_4 0.161 0.246 0.313 1.000 round(cor(broad), 3) ## [,1] [,2] [,3] [,4] ## [1,] 1.000 0.350 0.255 0.161 ## [2,] 0.350 1.000 0.406 0.246 ## [3,] 0.255 0.406 1.000 0.313 ## [4,] 0.161 0.246 0.313 1.000 z <- predict(fit, x = \"knots\", include_data = FALSE, shape = \"wide\")[, -1] # off-diagonal elements of covariance of broken stick estimates approach correlation # not enough variance in the diagonal because of smoothing cov(z) ## 1 2 3 ## 1 0.795 0.595 0.475 ## 2 0.595 0.791 0.681 ## 3 0.475 0.681 0.821 # correlations of broken stick estimates are inflated because of smoothing cor(z) ## 1 2 3 ## 1 1.000 0.750 0.587 ## 2 0.750 1.000 0.845 ## 3 0.587 0.845 1.000"},{"path":"https://growthcharts.org/brokenstick/articles/perfectmodel.html","id":"conclusions","dir":"Articles","previous_headings":"","what":"Conclusions","title":"Check perfect model","text":"\\(\\sigma^2=0\\), -diagonal elements \\(\\Omega\\) reproduce correlations among \\(y\\)’s. estimate \\(\\sigma^2\\) high (0.13 instead 0). \\(\\sigma^2 > 0\\), \\(\\hat C = \\Omega + \\hat\\sigma^2 (n_i)\\) reproduces sample covariance matrix \\(y\\)’s exactly. cov2cor(hatC) reproduces sample time--time correlation matrix. Conclusion: unbiased estimate time--time correlation matrix among (unobserved) measurements knots:","code":"cov <- get_omega(fit) chat <- cov + diag(fit$sigma2, nrow(cov)) r <- cov2cor(chat) r ## age_1 age_2 age_3 ## age_1 1.000 0.350 0.255 ## age_2 0.350 1.000 0.406 ## age_3 0.255 0.406 1.000"},{"path":"https://growthcharts.org/brokenstick/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Stef van Buuren. Author, maintainer.","code":""},{"path":"https://growthcharts.org/brokenstick/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"van Buuren S (2023). “Broken Stick Model Irregular Longitudinal Data.” Journal Statistical Software, 106(7), 1–51. doi:10.18637/jss.v106.i07.","code":"@Article{, title = {Broken Stick Model for Irregular Longitudinal Data}, author = {Stef {van Buuren}}, journal = {Journal of Statistical Software}, year = {2023}, volume = {106}, number = {7}, pages = {1--51}, doi = {10.18637/jss.v106.i07}, }"},{"path":"https://growthcharts.org/brokenstick/index.html","id":"brokenstick","dir":"","previous_headings":"","what":"Broken Stick Model for Irregular Longitudinal Data","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model describes set individual curves linear mixed model using second-order linear B-splines. main use model align irregularly observed data user-specified grid break ages. fitting can done Z-score scale, nonlinearities irregular data can treated separate problems. package contains functions fitting broken stick model data, exporting parameters model independent use outside package, predicting broken stick curves new data.","code":""},{"path":"https://growthcharts.org/brokenstick/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Install brokenstick package CRAN follows: latest version (revision branch) can installed GitHub follows:","code":"install.packages(\"brokenstick\") install.packages(\"remotes\") remotes::install_github(\"growthcharts/brokenstick\")"},{"path":"https://growthcharts.org/brokenstick/index.html","id":"overview","dir":"","previous_headings":"","what":"Overview","title":"Broken Stick Model for Irregular Longitudinal Data","text":"broken stick model describes set individual curves linear mixed model using linear B-splines. model can used smooth growth curves series connected straight lines; align irregularly observed curves common age grid; create synthetic curves user-specified set break ages; estimate time--time correlation matrix; predict future observations. user specifies set break ages straight lines connect. individual obtains estimate break age, set estimates individual form smoothed version observed trajectory. main assumptions broken stick model : trajectory break ages follows straight line, generally particular interest; Broken stick estimates follow common multivariate normal distribution; Missing data missing random (MAR); Individuals exchangeable uncorrelated. order conform assumption multivariate normality, user may fit broken stick model suitably transformed data yield standard normal (Z) scale. Unique feature broken stick model : Modular: Issues related non-linearity growth curves observed scale can treated separately, .e., outside broken stick model; Local: given data point contribute estimates corresponding closest break ages; Exportable: broken stick model can exported reused prediction new data alternative computing environments. brokenstick package contains functions Fitting broken stick model data, Plotting individual trajectories, Predicting broken stick estimates new data.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/index.html","id":"background","dir":"","previous_headings":"Resources","what":"Background","title":"Broken Stick Model for Irregular Longitudinal Data","text":"took name broken stick Ruppert, Wand, Carroll (2003), page 59-61, actually much older. far know, de Kroon et al. (2010) first publication uses broken stick model without intercept mixed modelling context. See Terneuzen birth cohort: BMI changes 2 6 years correlate strongest adult overweight. model formally defined extended Flexible Imputation Missing Data (second edition). See van Buuren (2018). evaluation Anderson et al. (2019) concluded: recommend use brokenstick model standardised Z‐score data. Aside accuracy fit, another key advantage brokenstick model easier fit provides easily interpretable estimates child growth trajectories.","code":""},{"path":"https://growthcharts.org/brokenstick/index.html","id":"instructive-materials","dir":"","previous_headings":"Resources","what":"Instructive materials","title":"Broken Stick Model for Irregular Longitudinal Data","text":"Companion site contains vignettes articles explain model use software; Publication: Broken Stick Model Irregular Longitudinal Data doi:10.18637/jss.v106.i07.","code":""},{"path":"https://growthcharts.org/brokenstick/index.html","id":"acknowledgment","dir":"","previous_headings":"Resources","what":"Acknowledgment","title":"Broken Stick Model for Irregular Longitudinal Data","text":"work supported Bill & Melinda Gates Foundation. contents sole responsibility authors may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":null,"dir":"Reference","previous_headings":"","what":"Empirical Bayes predictor for random effects — EB","title":"Empirical Bayes predictor for random effects — EB","text":"function can estimate random effect given set model estimates new user data. unit may new model. methods implements EB estimate (also known BLUP) described Skrondral Rabe-Hasketh, 2009, p. 683. function can also provide broken stick estimate given level, sum global (fixed) individual (random) effects. current implementation provide prediction errors.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Empirical Bayes predictor for random effects — EB","text":"","code":"EB(model, y, X, Z = X, BS = TRUE)"},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Empirical Bayes predictor for random effects — EB","text":"model object class brokenstick. y vector new measurements unit j, scaled metric fitted model. X nj * p matrix fixed effects unit j, typically produced bs(). Z nj * q matrix random effects unit j. default sets Z equal X. BS logical indicating whether broken stick estimates returned (BS = TRUE) random effects (BS = FALSE). default TRUE.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Empirical Bayes predictor for random effects — EB","text":"vector length q containing random effect broken stick estimates unit j.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Empirical Bayes predictor for random effects — EB","text":"Skrondal, ., Rabe-Hesketh, S. (2009). Prediction multilevel generalized linear models. J. R. Statist. Soc. , 172, 3, 659-687.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/EB.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Empirical Bayes predictor for random effects — EB","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":null,"dir":"Reference","previous_headings":"","what":"Class brokenstick — brokenstick-class","title":"Class brokenstick — brokenstick-class","text":"main fitting function brokenstick() returns object class brokenstick. object collects fitted broken stick model.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Class brokenstick — brokenstick-class","text":"package exports S3 methods brokenstick class following generic functions: coef(), fitted(), model.frame(), model.matrix(), plot(), predict(), print(), residuals() summary(). package exports following helper functions brokenstick objects: get_knots(), get_omega() get_r2(). brokenstick object list following named elements:","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"elements","dir":"Reference","previous_headings":"","what":"Elements","title":"Class brokenstick — brokenstick-class","text":"call Call created object names named list three elements (\"x\", \"y\", \"g\") providing variable name time, outcome subject, respectively. internal Numeric vector internal knots. boundary Numeric vector length 2 boundary knots. degree degree B-spline. See splines::bs(). Support values 0 (step model) 1 (broken stick model). method String, either \"kr\" \"lmer\", identifying fitting model. control List control options returned set_control() used set algorithmic details. beta Numeric vector fixed effect estimates. omega Numeric matrix variance-covariance estimates broken stick estimates. sigma2 Numeric scalar mean residual variance. sample numeric vector descriptives training data. light returned object lighter? light = TRUE returned object contain model settings parameter estimates store sigma2j, sample, data, imp mod elements. light object can used predict broken stick estimates new data, disclose training data small. hide output boundary knots hidden? Can \"right\", \"left\", \"boundary\", \"internal\" \"none\". default \"right\". sigma2j Numeric vector estimates residual variance per group. used method \"kr\". data training data used fit model. imp imputations generated missing outcome data. method = \"kr\". mod method = \"kr\": named list four components, class coda::mcmc. method = \"lmer\": object class lme4::merMod.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Class brokenstick — brokenstick-class","text":"doi:10.18637/jss.v106.i07","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-class.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Class brokenstick — brokenstick-class","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":null,"dir":"Reference","previous_headings":"","what":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"broken stick model describes set individual curves linear mixed model using second-order linear B-splines. main use model align irregularly observed data user-specified grid break ages.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"brokenstick package contains functions fitting broken stick model data, predicting broken stick curves new data, plotting results.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"work supported Bill & Melinda Gates Foundation. contents sole responsibility authors may necessarily represent official views Bill & Melinda Gates Foundation agencies may supported primary data studies used present study.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"brokenstick-functions","dir":"Reference","previous_headings":"","what":"brokenstick functions","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"main functions : following functions user-oriented helpers: following functions perform calculations:","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick-pkg.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"brokenstick: A package for irregular longitudinal data. — brokenstick-pkg","text":"van Buuren, S. (2023). Broken Stick Model Irregular Longitudinal Data. Journal Statistical Software, 106(7), 1--51. doi:10.18637/jss.v106.i07 van Buuren, S. (2018). Flexible Imputation Missing Data. Second Edition. Chapman & Hall/CRC. Chapter 11. https://stefvanbuuren.name/fimd/sec-rastering.html#sec:brokenstick","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Fit a brokenstick model to irregular data — brokenstick","title":"Fit a brokenstick model to irregular data — brokenstick","text":"brokenstick() function fits irregularly observed series measurements onto user-specified grid points (knots). model codes grid series linear B-splines. modelled trajectory consists straight lines join chosen knots look like broken stick. Differences observations expressed random effect per knot.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Fit a brokenstick model to irregular data — brokenstick","text":"","code":"brokenstick( formula, data, knots = NULL, boundary = NULL, k = 5L, degree = 1L, method = c(\"kr\", \"lmer\"), control = set_control(method = method, ...), na.action = na.exclude, light = FALSE, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), ... )"},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Fit a brokenstick model to irregular data — brokenstick","text":"formula formula specifying outcome, predictor group variable data. generic shape formula = y ~ x | group. left-hand side outcome, right-hand side predictor, name grouping variable occurs | sign. Formula treatment non-standard: 1) y x numeric, 2) one variable allowed model term (additional variables ignored). data data frame matrix containing outcome (numeric), predictor (numeric) group (numeric, factor, character) variable. knots Optional, recommended. Numerical vector locations internal knots placed values predictor. function sorts internal knots increasing order. boundary Optional, recommended. Numerical vector length 2 left right boundary knot. boundary setting passed splines::bs() Boundary.knots argument. specified, function determines boundary knots range(x). specified, boundary range internally expanded include least range(knots). k Optional, convenience parameter number internal knots. specified, k internal knots placed equidense quantiles predictor. example, specifying k = 1 puts knot 50th quantile (median), setting k = 3 puts knots 25th, 50th 75th quantiles, . user specifies k knots arguments knots takes precedence. default k = 5, user specify knots, boundary k, knots 16th, 33th, 50th, 66th 84th quantile predictor. degree degree spline. broken stick model requires linear splines, default degree = 1. Setting degree = 0 yields (crisp) dummy coding, one column less degree = 1. brokenstick package supports degree = 0 degree = 1. method Estimation method. Either \"kr\" (Kasim-Raudenbush sampler) \"lmer\" (lme4::lmer()). Version 1.1.1.9000 changed default method = \"kr\". control List control options returned set_control() used set algorithmic details. list parameters. specified, functions sets defaults method \"kr\" control_kr(), method \"lmer\" lme4::lmerControl(). ease use, user may set individual options \"kr\" (e.g. niter = 500) via ... arguments. na.action function indicates lme4::lmer() data contain NAs. Default set na.exclude. used method \"lmer\". light returned object lighter? light = TRUE returned object contain model settings parameter estimates store data, imp mod elements. light object can used predict broken stick estimates new data, disclose training data small (often <20 Kb). hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". ... Forwards arguments control_kr().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Fit a brokenstick model to irregular data — brokenstick","text":"object class brokenstick.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Fit a brokenstick model to irregular data — brokenstick","text":"choice method = \"kr\" method = \"lmer\" depends size data complexity model. general, setting method = \"lmer\" can require substantial calculation time complex models (say > 8 internal knots) may converge. Method \"kr\" less sensitive model complexity small samples, added benefit variance-covariance matrix random effects can constrained cormodel argument. hand, \"lmer\" better-researched method, efficient simpler models datasets many rows. default algorithm since version 2.0 Bayesian Kasim-Raudenbush sampler (method = \"kr\"). variance-covariance matrix broken stick estimates absorbs relations time. \"kr\" method allows enforcing simple structure variance-covariance matrix. Currently, three correlation models: \"none\" (default), \"argyle\" \"cole\". Specify seed argument reproducibility. See control_kr() details. alternative method = \"lmer\" fits broken stick model lme4::lmer(). method, variance-covariance matrix can unstructured. estimate may unstable number children small relative number specified knots. default setting lme4::lmerControl() check.nobs.vs.nRE= \"stop\". [set_control()] function changes check.nobs.vs.nRE= \"warning\" default, since otherwise many broken stick models run . method throws warnings estimates stable. can time models many internal knots. Despite warnings, results often look reasonable. Diagnostics coda lme4: function returns object class brokenstick. method = \"kr\" list component named \"mod\" contains list mcmc objects can analysed coda::acfplot(), coda::autocorr(), coda::crosscorr(), coda::cumuplot(), coda::densplot(), coda::effectiveSize(), coda::geweke.plot(), coda::raftery.diag(), coda::traceplot() usual plot() summary() functions. method = \"lmer\" list component named \"mod\" contains object class lme4::merMod. model objects omitted light brokenstick objects.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Fit a brokenstick model to irregular data — brokenstick","text":"Note automatic knot specification data-dependent, may reproduce data. Likewise, knots specified via k data-dependent transfer data sets. Fixing model requires specifying knots boundary.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/brokenstick.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Fit a brokenstick model to irregular data — brokenstick","text":"","code":"# \\donttest{ data <- smocc_200[1:1198, ] # using kr method, default f1 <- brokenstick(hgt_z ~ age | id, data, knots = 0:2, seed = 123) plot(f1, data, n_plot = 9) # study sampling behaviour of the sigma2 parameter with coda library(\"coda\") plot(f1$mod$sigma2) acfplot(f1$mod$sigma2) # using lmer method f2 <- brokenstick(hgt_z ~ age | id, data, knots = 0:2, method = \"lmer\") plot(f2, data, n_plot = 9) # drill down into merMod object with standard diagnostics in lme4 summary(f2$mod) #> Linear mixed model fit by REML ['lmerMod'] #> Formula: hgt_z ~ 0 + age_0 + age_1 + age_2 + age_2.6776 + (0 + age_0 + #> age_1 + age_2 + age_2.6776 | id) #> Data: data #> Control: control #> #> REML criterion at convergence: 2088.7 #> #> Scaled residuals: #> Min 1Q Median 3Q Max #> -3.8278 -0.5279 0.0025 0.5652 3.4227 #> #> Random effects: #> Groups Name Variance Std.Dev. Corr #> id age_0 1.2929 1.1370 #> age_1 0.6759 0.8221 0.47 #> age_2 0.7082 0.8415 0.45 0.94 #> age_2.6776 3.5673 1.8887 0.45 0.58 0.63 #> Residual 0.1783 0.4222 #> Number of obs: 1185, groups: id, 124 #> #> Fixed effects: #> Estimate Std. Error t value #> age_0 -0.02596 0.10452 -0.248 #> age_1 0.03550 0.07838 0.453 #> age_2 0.05766 0.08689 0.664 #> age_2.6776 0.56284 0.75759 0.743 #> #> Correlation of Fixed Effects: #> age_0 age_1 age_2 #> age_1 0.407 #> age_2 0.394 0.719 #> age_2.6776 0.089 0.167 -0.114 plot(f2$mod) # a model with more knots knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24, 36) / 12, 4) # method kr takes about 2 seconds f3 <- brokenstick(hgt_z ~ age | id, data, knots, seed = 222) plot(f3, data, n_plot = 9) # method lmer takes about 40 seconds f4 <- brokenstick(hgt_z ~ age | id, data, knots, method = \"lmer\") #> Warning: number of observations (=1185) <= number of random effects (=1364) for term (0 + age_0 + age_0.0833 + age_0.1667 + age_0.25 + age_0.5 + age_0.75 + age_1 + age_1.25 + age_1.5 + age_2 + age_3 | id); the random-effects parameters and the residual variance (or scale parameter) are probably unidentifiable #> boundary (singular) fit: see help('isSingular') plot(f4, data, n_plot = 9) # }"},{"path":"https://growthcharts.org/brokenstick/reference/coef.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","title":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","text":"Extract Model Coefficients brokenstick Object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/coef.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","text":"","code":"# S3 method for brokenstick coef( object, complete = TRUE, ..., hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\") )"},{"path":"https://growthcharts.org/brokenstick/reference/coef.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract Model Coefficients from brokenstick Object — coef.brokenstick","text":"object brokenstick object complete default (used lm, etc) aov methods: logical indicating full coefficient vector returned also case -determined system coefficients set NA, see also alias. Note default differs lm() aov() results. ... arguments. hide output boundary knots hidden print, summary plot functions? Can \"right\", \"left\", \"boundary\", \"internal\" \"none\". specified, read object$hide.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":null,"dir":"Reference","previous_headings":"","what":"Set controls for Kasim-Raudenbush sampler — control_kr","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"Set controls Kasim-Raudenbush sampler","code":""},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"","code":"control_kr( niter = 200L, nimp = 0L, start = 101L, thin = 1L, seed = NA_integer_, cormodel = c(\"none\", \"argyle\", \"cole\"), ... )"},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"niter Integer. Number samples posterior. Default: 200. nimp Integer. Number multiple imputations. Default: 0. start Integer. iteration number first observation thin Integer. thinning interval consecutive observations seed Integer. Seed number base::set.seed(). Use NA bypass seed setting. cormodel String indicating correlation model: \"none\" (default), \"argyle\" \"cole\" ... Allow dot parameters","code":""},{"path":"https://growthcharts.org/brokenstick/reference/control_kr.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set controls for Kasim-Raudenbush sampler — control_kr","text":"list eight components. function calculates parameters end (iteration number last iteration) thin_imp (thinning factor multiple imputations) inputs.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200.html","id":null,"dir":"Reference","previous_headings":"","what":"Broken stick model with nine lines for 200 children — fit_200","title":"Broken stick model with nine lines for 200 children — fit_200","text":"Object fit_200 class brokenstick contains fitted broken stick model, including training data diagnostics.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Broken stick model with nine lines for 200 children — fit_200","text":"object class brokenstick, fitted brokenstick().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Broken stick model with nine lines for 200 children — fit_200","text":"dataset constructed ","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit_200 <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = knots, seed = 1)"},{"path":"https://growthcharts.org/brokenstick/reference/fit_200_light.html","id":null,"dir":"Reference","previous_headings":"","what":"Broken stick model with nine lines for 200 children (light) — fit_200_light","title":"Broken stick model with nine lines for 200 children (light) — fit_200_light","text":"Object fit_200_light class brokenstick stores model settings parameter estimates.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200_light.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Broken stick model with nine lines for 200 children (light) — fit_200_light","text":"object class brokenstick, fitted brokenstick().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fit_200_light.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Broken stick model with nine lines for 200 children (light) — fit_200_light","text":"datasets constructed ","code":"knots <- round(c(0, 1, 2, 3, 6, 9, 12, 15, 18, 24)/12, 4) fit_200_light <- brokenstick(hgt_z ~ age | id, data = smocc_200, knots = knots, light = TRUE, seed = 1)"},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate fitted values — fitted.brokenstick","title":"Calculate fitted values — fitted.brokenstick","text":"Calculate fitted values","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate fitted values — fitted.brokenstick","text":"","code":"# S3 method for brokenstick fitted(object, newdata = NULL, ...)"},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate fitted values — fitted.brokenstick","text":"object brokenstick object. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... Additional arguments. Ignored.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/fitted.brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate fitted values — fitted.brokenstick","text":"numerical vector predictions. number elements equals number rows newdata. newdata specified, function looks training data object element named data.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":null,"dir":"Reference","previous_headings":"","what":"Obtain the knots from a broken stick model — get_knots","title":"Obtain the knots from a broken stick model — get_knots","text":"Obtain knots broken stick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Obtain the knots from a broken stick model — get_knots","text":"","code":"get_knots( object, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), whatknots = \"all\", what = \"all\" )"},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Obtain the knots from a broken stick model — get_knots","text":"object object class brokenstick hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". whatknots Deprecated. Use hide instead. Deprecated. Use hide instead.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Obtain the knots from a broken stick model — get_knots","text":"vector knot locations, either , internal boundary , depending hide. result NULL object proper class. Returns numeric(0) internal knots.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_knots.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Obtain the knots from a broken stick model — get_knots","text":"","code":"get_knots(fit_200, hide = \"bo\") #> [1] 0.0833 0.1667 0.2500 0.5000 0.7500 1.0000 1.2500 1.5000 2.0000"},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract Variance and Correlation Components — get_omega","title":"Extract Variance and Correlation Components — get_omega","text":"Extracts variance-covariance correlation matrix brokenstick object.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract Variance and Correlation Components — get_omega","text":"","code":"get_omega( x, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), cor = FALSE, whatknots = \"all\", what = \"cov\" )"},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract Variance and Correlation Components — get_omega","text":"x Object class brokenstick hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". cor Logical. function return correlation matrix instead covariance matrix? default FALSE. whatknots Deprecated. Deprecated.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract Variance and Correlation Components — get_omega","text":"numeric matrix, possibly zero rows columns names match","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_omega.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract Variance and Correlation Components — get_omega","text":"","code":"f1 <- brokenstick(hgt_z ~ age | id, smocc_200[1:1000, ], knots = 0:2, seed = 1) get_omega(f1, cor = TRUE, hide = \"boundary\") #> age_1 age_2 #> age_1 1.0000000 0.9173999 #> age_2 0.9173999 1.0000000"},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":null,"dir":"Reference","previous_headings":"","what":"Obtain proportion of explained variance from a broken stick model — get_r2","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"Obtain proportion explained variance broken stick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"","code":"get_r2(object, newdata = NULL)"},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"object object class brokenstick newdata Data r.squared must calculated","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"Proportion explained variance","code":""},{"path":"https://growthcharts.org/brokenstick/reference/get_r2.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Obtain proportion of explained variance from a broken stick model — get_r2","text":"","code":"get_r2(fit_200) #> [1] 0.9808152 get_r2(fit_200_light, newdata = smocc_200) #> [1] 0.9808152"},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":null,"dir":"Reference","previous_headings":"","what":"Kasim-Raudenbush sampler for two-level normal model — kr","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"Simulates posterior distributions parameters two-level normal model heterogeneous within-cluster variances (Kasim Raudenbush, 1998). Imputations can drawn extra step algorithm.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"","code":"kr(y, x, g, control = control_kr())"},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"y Vector outcome value x Matrix predictor value g Vector group values control list created control_kr() sets algorithmic options sampler correlation model.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"object class kr, basically list components: number rows imp equal number missing values outcome vector y. number columns equals nimp.","code":"* `beta` Fixed effects * `omega` Variance-covariance of random effects * `sigma2_j` Residual variance per group * `sigma2` Average residual variance * `sample` Descriptive statistics about the data * `imp` Numeric matrix with `nimp` multiple imputations. * `mod` A list of objects of class [coda::mcmc()]"},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"speed Kasim-Raudenbush sampler almost independent number random effect, foremost depends total number iterations. defaults start = 100, n = 200 thin = 1 provide 200 parameter draws reasonable approximation variance-covariance matrix random effects. closer approximations 200 draws set control = control_kr(thin = 10) (better) thin = 20 (best), expense linear increase calculation time. Drawing fewer 50 observations recommended, results best treated indicative. possible draw multiple imputations setting nimp parameter. example, draw five imputations missing outcome specify control = control_kr(nimp = 5).","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"Kasim RM, Raudenbush SW. (1998). Application Gibbs sampling nested variance components models heterogeneous within-group variance. Journal Educational Behavioral Statistics, 23(2), 93--116.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/kr.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Kasim-Raudenbush sampler for two-level normal model — kr","text":"Stef van Buuren, based mice::mice.impute.2l.norm()","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":null,"dir":"Reference","previous_headings":"","what":"Create linear splines basis — make_basis","title":"Create linear splines basis — make_basis","text":"function creates basis function second-order (linear) splines user-specific set break points.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create linear splines basis — make_basis","text":"","code":"make_basis( x, xname = \"x\", internal = NULL, boundary = range(x), degree = 1L, warn = TRUE )"},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create linear splines basis — make_basis","text":"x numeric vector xname predictor name. Default \"x\" internal vector internal knots, excluding boundary knots boundary vector external knots degree degree spline. broken stick model requires linear splines, default degree = 1. Setting degree = 0 yields (crisp) dummy coding, one column less degree = 1. warn logical indicating whether warnings splines::bs() given.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create linear splines basis — make_basis","text":"matrix length(x) rows length(breaks) columns, extra attributes described bs().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Create linear splines basis — make_basis","text":"version 0.54, standard practice knots array always included boundary[1L].","code":""},{"path":"https://growthcharts.org/brokenstick/reference/make_basis.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Create linear splines basis — make_basis","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":null,"dir":"Reference","previous_headings":"","what":"Parse formula for brokenstick model — parse_formula","title":"Parse formula for brokenstick model — parse_formula","text":"bare bones formula parser extract variables names formulas y ~ x | g. return name first variable mentioned formula component.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Parse formula for brokenstick model — parse_formula","text":"","code":"parse_formula(f)"},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Parse formula for brokenstick model — parse_formula","text":"f formula object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Parse formula for brokenstick model — parse_formula","text":"list elements x, y g. element length 1.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/parse_formula.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Parse formula for brokenstick model — parse_formula","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot observed and fitted trajectories by group — plot.brokenstick","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"plot method brokenstick object plots observed fitted trajectories one groups.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"","code":"# S3 method for brokenstick plot(x, newdata = NULL, ...)"},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"x object class brokenstick. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... Extra arguments passed predict.brokenstick() plot_trajectory().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"object class ggplot2::ggplot.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"default, plot(fit) plot observed fitted data first three groups data. default setting drops fitted value right boundary knot display.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"Stef van Buuren 2023","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot.brokenstick.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot observed and fitted trajectories by group — plot.brokenstick","text":"","code":"if (FALSE) { # fit model on raw hgt with knots at 0, 1, 2 and 3 years fit1 <- brokenstick(hgt ~ age | id, smocc_200, knots = 0:2) gp <- c(10001, 10005, 10022) plot(fit1, group = gp, xlab = \"Age (years)\", ylab = \"Length (cm)\") # fit model on standard deviation score fit2 <- brokenstick(hgt_z ~ age | id, smocc_200, knots = 0:2) plot(fit2, group = gp, xlab = \"Age (years)\", ylab = \"Length (SDS)\") # built-in model with 11 knots plot(fit_200, group = gp, xlab = \"Age (years)\", ylab = \"Length (SDS)\") # black and white version plot(fit_200, group = gp, xlab = \"Age (years)\", ylab = \"Length (SDS)\", color_y = rep(\"black\", 2), shape_y = 1, linetype_y = 3, color_yhat = rep(\"grey20\", 2), shape_yhat = NA) }"},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"Plot observed fitted trajectories fitted brokenstick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"","code":"plot_trajectory( x, newdata = NULL, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), .x = NULL, group = NULL, color_y = c(grDevices::hcl(240, 100, 40, 0.7), grDevices::hcl(240, 100, 40, 0.8)), size_y = 2, linetype_y = 1, shape_y = 19, color_yhat = c(grDevices::hcl(0, 100, 40, 0.7), grDevices::hcl(0, 100, 40, 0.8)), size_yhat = 2, linetype_yhat = 1, shape_yhat = 19, color_imp = c(\"grey80\", \"grey80\"), size_imp = 2, ncol = 3L, xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, show = c(TRUE, TRUE, FALSE), n_plot = 3L, scales = \"fixed\", theme = ggplot2::theme_light(), whatknots = \"droplast\", ... )"},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"x object class brokenstick. newdata data.frame matrix hide Character indicating knots .x x argument predict.brokenstick() function. group vector group identifications color_y character vector two elements specifying symbol line color measured data points size_y Dot size measured data points linetype_y Line type data points shape_y Symbol data points color_yhat character vector two elements specifying symbol line color predicted data points size_yhat Dot size predicted data points linetype_yhat Line type predicted data shape_yhat Symbol predicted data color_imp character vector two elements specifying symbol line color imputed data size_imp Dot size imputed data ncol Number columns plot xlab label x-axis ylab label y-axis xlim Vector length 2 range x-axis ylim Vector length 2 range y-axis show logical vector length 3. Element 1 specifies whether observed data plotted, element 2 specifies whether broken stick plotted, element 3 specifies whether imputations plotted. default c(TRUE, TRUE, FALSE). n_plot integer indicating number individual plots. default 3, plots trajectories first three groups. n_plot safety measure prevent unintended plots entire data set. scales Axis scaling, e.g. \"fixed\", \"free\", theme Plotting theme whatknots Deprecated. ... Extra arguments passed predict.brokenstick().","code":""},{"path":"https://growthcharts.org/brokenstick/reference/plot_trajectory.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot observed and fitted trajectories from fitted brokenstick model — plot_trajectory","text":"object class ggplot","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":null,"dir":"Reference","previous_headings":"","what":"Predict from a brokenstick model — predict.brokenstick","title":"Predict from a brokenstick model — predict.brokenstick","text":"predictions broken stick model coincide group-conditional means random effects. function takes object class brokenstick returns predictions one several formats. user can calculate predictions new persons, .e., persons part fitted model, x y arguments.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Predict from a brokenstick model — predict.brokenstick","text":"","code":"# S3 method for brokenstick predict( object, newdata = NULL, ..., x = NULL, y = NULL, group = NULL, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\"), shape = c(\"long\", \"wide\", \"vector\"), include_data = TRUE, strip_data = TRUE, whatknots = \"all\" )"},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Predict from a brokenstick model — predict.brokenstick","text":"object brokenstick object. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... used, required extensibility. x Optional. numeric vector values predictor. also special keyword x = \"knots\" replaces x positions knots. y Optional. numeric vector measurements. group vector group identifications hide output knots hidden get, print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". default \"right\". shape string: \"long\" (default), \"wide\" \"vector\" specifying shape return value. Note use \"wide\" many unique values x creates unwieldy, large sparse matrix. include_data logical indicating whether observed data object$data newdata included return value. default TRUE. Use include_data = FALSE keep added data points (e.g. knots observed data specified x y). Setting include_data = FALSE useful combination shape = \"wide\" avoid warning Values '.pred' uniquely identified. convenience, special case x = \"knots\" function overwrites include_data FALSE evade observed ages show wide matrix. strip_data Deprecated. Use include_data instead. whatknots Deprecated. Use hide instead.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Predict from a brokenstick model — predict.brokenstick","text":"shape == \"long\" long data.frame predictions. x, y group specified, number rows data frame guaranteed number rows newdata. shape == \"wide\" wide data.frame predictions, one record per group. Note format inefficient observations times vary subjects. shape == \"vector\" vector predicted values, x-values groups. function finds data, throws warnings returns NULL.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Predict from a brokenstick model — predict.brokenstick","text":"function predict() calculates predictions every row newdata. user specifies newdata argument, function sets newdata equal training data (object$data object$light FALSE). light object without newdata argument, function throws warning \"Argument 'newdata' required light brokenstick object.\" returns NULL. possible tailor behaviour predict() x, y group arguments. exactly happens depends arguments specified: user specifies x, y group, function returns - every group newdata - predictions specified x values. method use data newdata. user specifies x y group, function forms hypothetical new group x y values. method uses information newdata, also works light brokenstick object. user specifies group, x y, function searches relevant data newdata limits predictions groups. useful user needs prediction one groups. work light brokenstick object. user specifies x group, y, function create new values x group, search relevant data newdata provide predictions values x groups. user specifies x, y group, function assumes vectors contain additional data top already available newdata. lengths x, y group must match. light brokenstick object, case effectively becomes case 6. See . case 5, now without newdata available. data specified x, y group form data frame. Matching newdata attempted, long group id's different training sample effectively new cases made.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/predict.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Predict from a brokenstick model — predict.brokenstick","text":"","code":"library(\"dplyr\") #> #> Attaching package: ‘dplyr’ #> The following objects are masked from ‘package:stats’: #> #> filter, lag #> The following objects are masked from ‘package:base’: #> #> intersect, setdiff, setequal, union # -- Data train <- smocc_200[1:1198, ] test <- smocc_200[1199:1940, ] if (FALSE) { # -- Fit model fit <- brokenstick(hgt_z ~ age | id, data = train, knots = 0:2, seed = 1) fit_light <- brokenstick(hgt_z ~ age | id, data = train, knots = 0:2, light = TRUE, seed = 1 ) # -- Predict, standard cases # Use train data, return column with predictions pred <- predict(fit) identical(nrow(train), nrow(pred)) # Predict without newdata, not possible for light object predict(fit_light) # Use test data pred <- predict(fit, newdata = test) identical(nrow(test), nrow(pred)) # Predict, same but using newdata with the light object pred_light <- predict(fit_light, newdata = test) identical(pred, pred_light) # -- Predict, special cases # -- Case 1: x, -y, -group # Case 1: x as \"knots\", standard estimates, train sample (n = 124) z <- predict(fit, x = \"knots\", shape = \"wide\") head(z, 3) # Case 1: x as values, linearly interpolated, train sample (n = 124) z <- predict(fit, x = c(0.5, 1, 1.5), shape = \"wide\", include_data = FALSE) head(z, 3) # Case 1: x as values, linearly interpolated, test sample (n = 76) z <- predict(fit, test, x = c(0.5, 1, 1.5), shape = \"wide\", include_data = FALSE) head(z, 3) # Case 1: x, not possible for light object z <- predict(fit_light, x = \"knots\") # -- Case 2: x, y, -group # Case 2: form one new group with id = 0 predict(fit, x = \"knots\", y = c(1, 1, 0.5, 0), shape = \"wide\") # Case 2: works also for a light object predict(fit_light, x = \"knots\", y = c(1, 1, 0.5, 0), shape = \"wide\") # -- Case 3: -x, -y, group # Case 3: Predict at observed age for subset of groups, training sample pred <- predict(fit, group = c(10001, 10005, 10022)) head(pred, 3) # Case 3: Of course, we cannot do this for light objects pred_light <- predict(fit_light, group = c(10001, 10005, 10022)) # Case 3: We can use another sample. Note there is no child 999 pred <- predict(fit, test, group = c(11045, 11120, 999)) tail(pred, 3) # Case 3: Works also for a light object pred_light <- predict(fit_light, test, group = c(11045, 11120, 999)) identical(pred, pred_light) # -- Case 4: x, -y, group # Case 4: Predict at specified x, only in selected groups, train sample pred <- predict(fit, x = c(0.5, 1, 1.25), group = c(10001, 10005, 10022), include_data = FALSE) pred # Case 4: Same, but include observed data and sort pred_all <- predict(fit, x = c(0.5, 1, 1.25), group = c(10001, 10005, 10022)) %>% dplyr::arrange(id, age) # Case 4: Applies also to test sample pred <- predict(fit, test, x = c(0.5, 1, 1.25), group = c(11045, 11120, 999), include_data = FALSE) pred # Case 4: Works also with light object pred_light <- predict(fit_light, test, x = c(0.5, 1, 1.25), group = c(11045, 11120, 999), include_data = FALSE) identical(pred_light, pred) # -- Case 5: x, y, group # Case 5: Add new data to training sample, and refreshes broken stick # estimate at age x. # Note that novel child (not in train) 999 has one data point predict(fit, x = c(0.9, 0.9, 0.9), y = c(1, 1, 1), group = c(10001, 10005, 999), include_data = FALSE) # Case 5: Same, but now for test sample. Novel child 899 has two data points predict(fit, test, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899), include_data = FALSE) # Case 5: Also works for light object predict(fit_light, test, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899), include_data = FALSE) # -- Case 6: As Case 5, but without previous data # Case 6: Same call as last, but now without newdata = test # All children are de facto novel as they do not occur in the training # or test samples. # Note: Predictions for 11045 and 11120 differ from prediction in Case 5. predict(fit, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899)) # This also work for the light brokenstick object predict(fit_light, x = c(0.5, 0.9, 0.6, 0.9), y = c(0, 0.5, 0.5, 0.6), group = c(11045, 11120, 899, 899)) }"},{"path":"https://growthcharts.org/brokenstick/reference/print.html","id":null,"dir":"Reference","previous_headings":"","what":"Print brokenstick object — print.brokenstick","title":"Print brokenstick object — print.brokenstick","text":"Print brokenstick object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/print.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Print brokenstick object — print.brokenstick","text":"","code":"# S3 method for brokenstick print( x, digits = getOption(\"digits\"), ..., hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\") )"},{"path":"https://growthcharts.org/brokenstick/reference/print.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Print brokenstick object — print.brokenstick","text":"x brokenstick object digits minimal number significant digits, see print.default. ... arguments passed methods. hide output boundary knots hidden print, summary plot functions? Can \"right\", \"left\",\"boundary\", \"internal\" \"none\". specified, read field x$hide.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract residuals from brokenstick model — residuals.brokenstick","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"Extract residuals brokenstick model","code":""},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"","code":"# S3 method for brokenstick residuals(object, newdata = NULL, ...)"},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"object brokenstick object. newdata Optional. data frame look variables predict. training data used omitted object$light FALSE. ... Additional arguments. Ignored.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/residuals.brokenstick.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract residuals from brokenstick model — residuals.brokenstick","text":"numerical vector residuals number elements equals number rows newdata. newdata specified, function looks training data object element named data.","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":null,"dir":"Reference","previous_headings":"","what":"Set controls to steer calculations — set_control","title":"Set controls to steer calculations — set_control","text":"Set controls steer calculations","code":""},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set controls to steer calculations — set_control","text":"","code":"set_control( method = c(\"kr\", \"lmer\"), kr = control_kr(...), lmer = lmerControl(check.nobs.vs.nRE = \"warning\"), ... )"},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set controls to steer calculations — set_control","text":"method String indicating estimation method: \"kr\" \"lmer\" kr list generated control_kr. lmer list generated lme4::lmerControl. default set lmerControl(check.nobs.vs.nRE = \"warning\"), turns fatal errors respect number parameters warnings. Use lmerControl(check.nobs.vs.nRE = \"ignore\") silence lmer(). ... Forwards arguments control_kr()","code":""},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set controls to steer calculations — set_control","text":"method \"kr\", list returned control_kr(). method \"lmer\", object class lmerControl. methods, set_control() returns NULL.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/set_control.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set controls to steer calculations — set_control","text":"","code":"# defaults control <- set_control() control #> $niter #> [1] 200 #> #> $nimp #> [1] 0 #> #> $start #> [1] 101 #> #> $end #> [1] 301 #> #> $thin #> [1] 1 #> #> $thin_imp #> [1] Inf #> #> $seed #> [1] NA #> #> $cormodel #> [1] \"none\" #>"},{"path":"https://growthcharts.org/brokenstick/reference/smocc_200.html","id":null,"dir":"Reference","previous_headings":"","what":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","title":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","text":"Longitudinal height weight measurements ages 0-2 years representative sample 1933 Dutch children born 1988-1989. dataset smocc_200 sample size 200 full data.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/smocc_200.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","text":"tibble 1942 rows 7 columns: id ID, unique id child (numeric) age Decimal age, 0-2.68 years (numeric) sex Sex, \"male\" \"female\" (character) ga Gestational age, completed weeks (numeric) bw Birth weight grammes (numeric) hgt Height measurement cm (numeric) hgt_z Height SDS relative Fourth Dutch Growth Study 1997 (numeric)","code":""},{"path":"https://growthcharts.org/brokenstick/reference/smocc_200.html","id":"source","dir":"Reference","previous_headings":"","what":"Source","title":"Infant growth of 0-2 years, SMOCC data extract — smocc_200","text":"Herngreen WP, van Buuren S, van Wieringen JC, Reerink JD, Verloove-Vanhorick SP & Ruys JH (1994). Growth length weight birth 2 years representative sample Netherlands children (born 1988-89) related socio-economic status background characteristics. Annals Human Biology, 21, 449-463.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/summary.html","id":null,"dir":"Reference","previous_headings":"","what":"Create summary of brokenstick object — summary.brokenstick","title":"Create summary of brokenstick object — summary.brokenstick","text":"Create summary brokenstick object","code":""},{"path":"https://growthcharts.org/brokenstick/reference/summary.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create summary of brokenstick object — summary.brokenstick","text":"","code":"# S3 method for brokenstick summary( object, ..., cor = FALSE, lower = TRUE, hide = c(\"right\", \"left\", \"boundary\", \"internal\", \"none\") )"},{"path":"https://growthcharts.org/brokenstick/reference/summary.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create summary of brokenstick object — summary.brokenstick","text":"object brokenstick object ... additional arguments affecting summary produced. cor Logical. function return correlation matrix instead covariance matrix? default FALSE. lower Logical. Print lower triangle correlation/covariance matrix? hide output boundary knots hidden print, summary plot functions? Can \"left\", \"right\", \"boundary\", \"internal\" \"none\". specified, read field object$hide.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":null,"dir":"Reference","previous_headings":"","what":"Weight loss self-measurement data — weightloss","title":"Weight loss self-measurement data — weightloss","text":"Longitudinal weight measurements 12 individuals 63 daily measurement three conditions.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Weight loss self-measurement data — weightloss","text":"data.frame 695 rows 6 columns: subject ID, consecutive person number 1-12 (integer) day Measurement day, 0-62 (integer) sex Sex, 1 = male, 0 = female (integer) week Week number, 1-9 (integer) condition Condition (control, diet, activity) (factor) body_weight Body weight kg (numeric)","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":"source","dir":"Reference","previous_headings":"","what":"Source","title":"Weight loss self-measurement data — weightloss","text":"Krone T, Boessen R, Bijlsma S, van Stokkum R, Clabbers NDS, Pasman WJ (2020). possibilities use N--1 --trials nutritional research. PloS ONE, 15, 5, e0232680.","code":""},{"path":"https://growthcharts.org/brokenstick/reference/weightloss.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Weight loss self-measurement data — weightloss","text":"Constructed file pone.0232680.s001.csv. renumbered subject consecutive integers 1-2 (paper), corrected error condition variable subjects 4 12 match paper's Figure 4, filtered records ones woth observed body_weight variable.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-250","dir":"Changelog","previous_headings":"","what":"brokenstick 2.5.0","title":"brokenstick 2.5.0","text":"CRAN release: 2023-03-22 Updates manual vignette conform accepted JSS manuscript (March 2023) Updates documentation CRAN release Adds doi:10.18637/jss.v106.i07 forthcoming JSS paper DESCRIPTION documentation","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-240","dir":"Changelog","previous_headings":"","what":"brokenstick 2.4.0","title":"brokenstick 2.4.0","text":"CRAN release: 2022-10-30","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"major-changes-2-4-0","dir":"Changelog","previous_headings":"","what":"Major changes:","title":"brokenstick 2.4.0","text":"Update JSS manuscript version dated 30-10-2022 Hiding knots now convenient automatic setting hide entry brokenstick object. replaces whatknots argument.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"minor-changes-2-4-0","dir":"Changelog","previous_headings":"","what":"Minor changes:","title":"brokenstick 2.4.0","text":"Adds hide field brokenstick object Adds hide arguments coef.brokenstick(), summary.brokenstick(), plot(), get_knots() get_omega Adds cor lower arguments summary.brokenstick() Replaces argument get_omega() cor Deprecates whatknots argument plot(), get_knots() get_omega() Separates summary() print() functionality Updates smocc_200 fit_200 objects Updates roxygen 7.2.1 Replace hard-coded variable name hgt_z dynamic name (#8)","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-230","dir":"Changelog","previous_headings":"","what":"brokenstick 2.3.0","title":"brokenstick 2.3.0","text":"CRAN release: 2022-09-07 Replaces argument get_knots() whatknots Adds support whatknots get_omega() Extends capabilities plot_trajectory() shape linetype options Adds example plot.brokenstick() create decent black white figure trajectories Replaces knots = 0:3 knots = 0:2 examples Updates perfectmodel vignette","code":""},{"path":[]},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"major-changes-2-2-0","dir":"Changelog","previous_headings":"","what":"Major changes:","title":"brokenstick 2.2.0","text":"Changes default number knots brokenstick() 5. former default produced solution without internal knots. new default produces generally informative starting model user specify knots (using knots = c(..., ...)) number knots (using k = ...). Replaces strip_data argument predict() intuitive include_data argument. default, observed data now included predictions, similar predict.lm(). Turns error Argument 'newdata' required light brokenstick object. brokenstick() warning returns NULL. Updates vignette Broken Stick Model Irregular Longitudinal Data sync revision JSS.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"minor-changes-2-2-0","dir":"Changelog","previous_headings":"","what":"Minor changes:","title":"brokenstick 2.2.0","text":"Expression predict(fit_200_light, x = \"knots\") now produces warning message instead crashing Updates objects fit_200 fit_200_light use automatic boundary (2.68y) instead 3 yrs Automatically sorts user-specified values knots increasing order evade problems predict()","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-210","dir":"Changelog","previous_headings":"","what":"brokenstick 2.1.0","title":"brokenstick 2.1.0","text":"CRAN release: 2022-03-30","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"incorporate-changes-and-updates-required-by-jss-2-1-0","dir":"Changelog","previous_headings":"","what":"Incorporate changes and updates required by JSS","title":"brokenstick 2.1.0","text":"Reorganises vignettes Renames brokenstick-article.Rmd manual/manual.Rmd, include high-res version site take package save space Updates vignettes/bibliography.bib title case Removes superfluous navigation vigettes Defines model.frame.brokenstick() function adheres conventions Changes return values fitted() residuals() vectors Defines less verbose print.brokenstick() helper Make calls library() character argument Removes library(lme4) code evade changing search path","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-202","dir":"Changelog","previous_headings":"","what":"brokenstick 2.0.2","title":"brokenstick 2.0.2","text":"Shrinks size brokenstick object removing formula list element","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-201","dir":"Changelog","previous_headings":"","what":"brokenstick 2.0.1","title":"brokenstick 2.0.1","text":"Shrinks size light objects removing sigma2j vector light brokenstick class","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-200","dir":"Changelog","previous_headings":"","what":"brokenstick 2.0.0","title":"brokenstick 2.0.0","text":"CRAN release: 2021-11-11","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"main-changes-2-0-0","dir":"Changelog","previous_headings":"","what":"Main changes","title":"brokenstick 2.0.0","text":"Function brokenstick() version 2.0.0 sets Kasim-Raudenbush sampler default method. former method lme4::lmer() remains available setting method = \"lmer\" argument. Version 2.0.0 adopts variable names coda package (e.g., start, end, thin, niter, ) stores results Kasim-Raudenbush sampler objects class mcmc. method = \"kr\" one may now inspect solution sampler standard functions coda package. method = \"lmer\" can apply functions lme4 package merMod objects. Version 2.0.0 redefines brokenstick class. New entries include call, formula, internal, sample, light, data, imp mod. Removed entries knots (renamed internal) draws (renamed imp). may omit newdata argument training data. Setting light = TRUE creates small version brokenstick object. Objects class brokenstick backwards compatible, one regenerate objects class brokenstick order use newer features 2.0.0. Version 2.0.0 conforms classic model fitting interface R. Renames new_data argument newdata conform predict.lm(). Methods plot() predict() longer require newdata argument. special cases predict() updated explained documentation examples. Version 2.0.0 adds methods coef(), fitted(), model.frame(), model.matrix(), print() summary brokenstick object. Simplifies algorithmic control. Renames control_brokenstick() set_control() removes layer control list.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"minor-changes-2-0-0","dir":"Changelog","previous_headings":"","what":"Minor changes","title":"brokenstick 2.0.0","text":"Stabilises rgamma() calls KR-algorithm edge cases. predict_brokenstick() can now work (internal) training (external) test data. Removes superfluous type argument predict.brokenstick() Adds function get_omega() extract variance-covariance matrix broken stick estimates Adds choice \"dropfirst\" get_knots() Improves error messages edge cases test-brokenstick_edge.R Perform stricter tests arguments brokenstick() Introduces argument warn_splines make_basis() suppress uninteresting warns splines::bs() Removes superfluous knotnames argument make_basis() Argument x make_basis() now vector instead column vector Introduces new xname argument make_basis() set xname","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-111","dir":"Changelog","previous_headings":"","what":"brokenstick 1.1.1","title":"brokenstick 1.1.1","text":"Handles edge case crashed predict()","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-110","dir":"Changelog","previous_headings":"","what":"brokenstick 1.1.0","title":"brokenstick 1.1.0","text":"CRAN release: 2020-11-02 version adds couple minor alterations. Updates cran-comments Adds link JSS manuscript description field Removes unnecessary \\dontrun{} directives Exports parse_formula() remove ::: examples Sanitises chunk names removing : _ characters Corrects “first-order” mindo’s “second-order” Repairs plotting glitch oldfriends.Rmd Limits number printed rows predict.brokenstick() example","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-100","dir":"Changelog","previous_headings":"","what":"brokenstick 1.0.0","title":"brokenstick 1.0.0","text":"Ready CRAN –> Move version 1.0.0 package now hosted https://github.com/growthcharts/brokenstick/","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0780","dir":"Changelog","previous_headings":"","what":"brokenstick 0.78.0","title":"brokenstick 0.78.0","text":"Prepare package first CRAN submission","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0770","dir":"Changelog","previous_headings":"","what":"brokenstick 0.77.0","title":"brokenstick 0.77.0","text":"Add documentation brokenstick class object Add JSS manuscript vignette Remove prediction vignette dependencies Extend plot.brokenstick() ability plot imputed trajectories Add weightloss data Fail early user specifies degree > 1","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0760","dir":"Changelog","previous_headings":"","what":"brokenstick 0.76.0","title":"brokenstick 0.76.0","text":"Adds argument plot.brokenstick() Solves bug always yielded zero rows case 3 prediction Solves data combination problem predict() group variable factor Add better explanation boundary parameter Evades model.matrix() removes rows NA degree = 0","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0750","dir":"Changelog","previous_headings":"","what":"brokenstick 0.75.0","title":"brokenstick 0.75.0","text":"version trims package various ways Removes dependencies hardhat recipes Makes brokenstick object smaller since blueprints stored Removes recipe interface brokenstick() function Moves ggplot2 suggests Copies install..demand() function mice","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0721","dir":"Changelog","previous_headings":"","what":"brokenstick 0.72.1","title":"brokenstick 0.72.1","text":"Imports recipes::recipe() inform R package installation process","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0720","dir":"Changelog","previous_headings":"","what":"brokenstick 0.72.0","title":"brokenstick 0.72.0","text":"Adds badges, resources references README Updates license Updates CITATION","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0710","dir":"Changelog","previous_headings":"","what":"brokenstick 0.71.0","title":"brokenstick 0.71.0","text":"Removes dependency growthstandards Updates corrects plot examples Tries evade ggplot2 --range/missing messages better filtering","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0701","dir":"Changelog","previous_headings":"","what":"brokenstick 0.70.1","title":"brokenstick 0.70.1","text":"Adds support brokenstick model degree = 0","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0700","dir":"Changelog","previous_headings":"","what":"brokenstick 0.70.0","title":"brokenstick 0.70.0","text":"version jump illustrates big breaking changes: brokenstick adopted tidymodels philosophy, now includes dependency hardhat. now possible fit model using five different interfaces. need anymore hardcode variable names source data. version introduces new estimation method, Kasim-Raudenbush sampler. new method flexible faster lme4::lmer() number knots large. version introduces two simple correlation models may used smooth variance-covariance matrix random effects. definition brokenstick class changed. Objects class brokenstick longer store training data. brokenstick_export class retired. predict() function fully rewritten now new interface. Since brokenstick class store training data anymore, predict() function now obtains new_data argument. Syntax worked brokenstick package 0.70.0 work anymore updated. shape argument replaces output argument. plot() function rewritten, now requires new_data specification. Retired functions: brokenstick() replaces fit_brokenstick(), predict.brokenstick() replaces predict.brokenstick_export(), get_r2() replaces get_pev() Removed functions: get_data(), get_X(), export()","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0620","dir":"Changelog","previous_headings":"","what":"brokenstick 0.62.0","title":"brokenstick 0.62.0","text":"version simplifies plotting functions Renders ggplot objects sharper vignettes svglite Drops pkg argument plot.brokenstick() Lessens dependency rbokeh Replaces hbgd (longer developed) growthstandards package Replaces smocc_50/fit_50 smocc_200/fit_200 Added NEWS.md file track changes package","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0610","dir":"Changelog","previous_headings":"","what":"brokenstick 0.61.0","title":"brokenstick 0.61.0","text":"Added smocc_50 fit_50 demo data Removed smocc.hgtwgt, smocc_hgtwgt fit_206 datasets Adapt code vignettes reflect replacement demo data","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-0600","dir":"Changelog","previous_headings":"","what":"brokenstick 0.60.0","title":"brokenstick 0.60.0","text":"Adapted source R 4.0.0.","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-055","dir":"Changelog","previous_headings":"","what":"brokenstick 0.55","title":"brokenstick 0.55","text":"Added new utility function get_pev() proportion explained variance get_knots() gets argument Now using smarter defaults plot() Simplified arguments plot() Simplified vignette “Overview main functions”","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-054","dir":"Changelog","previous_headings":"","what":"brokenstick 0.54","title":"brokenstick 0.54","text":"Added Support ggplot2 Made ggplot2 plot default Changed default show_references flag FALSE","code":""},{"path":"https://growthcharts.org/brokenstick/news/index.html","id":"brokenstick-053","dir":"Changelog","previous_headings":"","what":"brokenstick 0.53","title":"brokenstick 0.53","text":"version announced invited lecture 7th Channel Network Conference, Hasselt, Belgium. abstract lecture: Broken stick model individual growth curves Stef van Buuren Netherlands Organization Applied Scientific Research TNO Utrecht University broken stick model describes set individual curves linear mixed model using second-order linear B-splines. model can used smooth growth curves series connected straight lines; align irregularly observed curves common age grid; create synthetic curves user-specified set break ages; estimate time--time correlation matrix; predict future observations. user specifies set break ages straight lines connect. individual obtains estimate break age, set estimates individual form smoothed version observed trajectory. main assumptions broken stick model development break ages follows straight line, broken stick estimates follow common multivariate normal distribution. order conform assumption multivariate normality, user may fit broken stick model suitably transformed data yield standard normal (Z-score) scale. lecture outlines model introduces brokenstick R package.","code":""}]