<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rense Nieuwenhuis &#187; ranef</title>
	<atom:link href="http://www.rensenieuwenhuis.nl/tag/ranef/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rensenieuwenhuis.nl</link>
	<description>&#34;The extra-ordinary lies within the curve of normality&#34;</description>
	<lastBuildDate>Thu, 12 Mar 2026 14:58:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.2.2</generator>
	<item>
		<title>R-Sessions 20: Plotting Multilevel Models</title>
		<link>http://www.rensenieuwenhuis.nl/r-sessions-20-plotting-multilevel-models/</link>
		<comments>http://www.rensenieuwenhuis.nl/r-sessions-20-plotting-multilevel-models/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 10:00:56 +0000</pubDate>
		<dc:creator><![CDATA[Rense Nieuwenhuis]]></dc:creator>
				<category><![CDATA[R-Project]]></category>
		<category><![CDATA[R-Sessions]]></category>
		<category><![CDATA[fixef]]></category>
		<category><![CDATA[multilevel]]></category>
		<category><![CDATA[plotting]]></category>
		<category><![CDATA[ranef]]></category>

		<guid isPermaLink="false">http://www.rensenieuwenhuis.nl/?p=573</guid>
		<description><![CDATA[<a href="http://www.rensenieuwenhuis.nl/archive/category/r-project/r-sessions/"><img src="http://www.rensenieuwenhuis.nl/wp-content/uploads/2008/07/r-sessions.jpg" " title="R-Sessions" width="470" /></a>

Plotting the results of a multilevel analysis, without use of the extension package 'Lattice' can be quite complicated while using R. Using only the basic packages, as well as the multilevel packages (nlme and lme4) there are no functions readily available for this task. So, this is a good point in this manual to put some of our programming skills to use. This makes exactly clear how the results of a multilevel analysis are stored in R as well.

]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.rensenieuwenhuis.nl/archive/category/r-project/r-sessions/"><img src="http://i0.wp.com/www.rensenieuwenhuis.nl/wp-content/uploads/2008/07/r-sessions.jpg?w=470" " title="R-Sessions" data-recalc-dims="1" /></a><br />
<!--adsense--></p>
<p>Plotting the results of a multilevel analysis, without use of the extension package &#8216;Lattice&#8217; can be quite complicated while using R. Using only the basic packages, as well as the multilevel packages (nlme and lme4) there are no functions readily available for this task. So, this is a good point in this manual to put some of our programming skills to use. This makes exactly clear how the results of a multilevel analysis are stored in R as well.</p>
<p>In order to be able to plot a multilevel model, we first need such a model. We will estimate a model here, which we have seen before. We want to estimate the effect that a standardized test at school-entry has on a specific exam students made. Students are, of course, nested withing shools, which is taken into account in our analysis, as well as the average score in the intake test for each of the schools. The effects the test at entry of the school has on the test result is allowed to vary by school. In other words: we are estimating a random intercept model with a random slope.<br />
<span id="more-573"></span><br />
In order to do so, we have to load the nlme package, as well as the mlmREV-package, which contains the data we will use. Then, for technical reasons, we have to get rid of the lme4-package. This is done by using the detach() function. This is what is done in the syntax below.</p>
<blockquote><p>
library(nlme)<br />
library(mlmRev)<br />
detach(&#8220;packages:lme4&#8243;)</p>
<p>model.01 <- lme(fixed = normexam ~ standLRT + schavg,<br />
			data = Exam,<br />
			random = ~ standLRT | school)</p>
<p>summary(model.01)
</p></blockquote>
<p>The requested output of the model.01 results in:</p>
<pre>
> summary(model.01)
Linear mixed-effects model fit by REML
 Data: Exam 
       AIC     BIC    logLik
  9337.885 9382.04 -4661.943

Random effects:
 Formula: ~standLRT | school
 Structure: General positive-definite, Log-Cholesky parametrization
            StdDev    Corr  
(Intercept) 0.2778443 (Intr)
standLRT    0.1237837 0.373 
Residual    0.7440440       

Fixed effects: normexam ~ standLRT + schavg 
                 Value  Std.Error   DF   t-value p-value
(Intercept) -0.0014224 0.03725472 3993 -0.038181  0.9695
standLRT     0.5522414 0.02035359 3993 27.132378  0.0000
schavg       0.2947588 0.10726821   63  2.747867  0.0078
 Correlation: 
         (Intr) stnLRT
standLRT  0.266       
schavg    0.089 -0.085

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-3.82942010 -0.63168683  0.03258589  0.68512318  3.43634584 

Number of Observations: 4059
Number of Groups: 65 
</pre>
<p>Probably the best way to visualize this model is to create a plot of the relationship on individual level between the score a student had on an standardized intake test (standLRT) and the result on an specific exam (normexam). We want these relationship to be shown for each school specifically. To do this, several steps are needed:</p>
<ul>
<li>A plot region has to be set</li>
<li>Coefficients for each school need to be extracted from the model</li>
<li>The minimum and maximum value on the x-axis for each school need to be extracted</li>
<li>Based on the model, the data actually needs to be plotted</li>
</ul>
<p>Each of the steps shall be described explicitly below. Since many steps need to be performed, they will be gathered in a function, which we&#8217;ll call visualize.lme(). It will have three parameters: the model we want to use, the predictor and the group-variable that will be taken into account.</p>
<blockquote><p>
visualize.lme <- function (model, coefficient, group, ...)<br />
{<br />
	r <- ranef(model)<br />
	f <- fixef(model)</p>
<p>	effects <- data.frame(r[,1]+f[1], r[,2]+f[2])</p>
<p>	number.lines <- nrow(effects)
</p></blockquote>
<p>Above, the first row defines the function visualize.lme(), an arbitrary name we chose ourselves. Between the brackets, four elements are placed. The three needed elements described above are named &#8216;model&#8217;, &#8216;coefficient&#8217;, and &#8216;group&#8217;. The fourth element ( &#8230; ) means that any other element can be added. These elements will be transfered to the plot() function that will be used to set the graphics device.<br />
Then, four variables are created within the function, to which data from the model is extracted. First, ranef() extracts the random coefficients from the model, while fixef() does the same for the fixed elements.<br />
The effects variable is created next. This will be a data.frame that contains information on the intercepts and the slopes that will be plotted. The number.lines variable contains the number of rows in the effects data.frame, that  is equal to the number of groups in the model.</p>
<blockquote><p>
	predictor.min <- tapply(model$data[[coefficient]], model$data[[group]], min)<br />
	predictor.max <- tapply(model$data[[coefficient]], model$data[[group]], max)</p>
<p>	outcome.min <- min(predict(model))<br />
	outcome.max <- max(predict(model))
</p></blockquote>
<p>Before the plotting area can be set up, we will need four coordinates. This is done above. First, the minimum and maximum value of the predictor is gathered. Next, the minimum and maximum of the predicted values are determined, using predict(). The predict() function takes the data from the model specified and uses the original data and the estimated model formula (which are stored inside) and returns a vector of predicted values on the outcome-variable. Using min() and max(), the minimum and maximum values are obtained.</p>
<blockquote><p>
	plot (c(min(predictor.min),max(predictor.max)),c(outcome.min,outcome.max), type=&#8221;n&#8221;, &#8230;)</p>
<p>	for (i in 1:number.lines)<br />
	{<br />
		expression <- function(x) {effects[i,1] + (effects[i,2] * x) }<br />
		curve(expression, from=predictor.min[i], to=predictor.max[i], add=TRUE)<br />
	}<br />
}
</p></blockquote>
<p>Finally, the plot is created above. First, the area in which to plot is set up. Using the four coordinates obtained before, a plot is created in such a way, that the lines the will be plotted next will fit in exactly. Specifying type=&#8221;n&#8221; results in setting up a plotting region on a graphics device, without an actual plot being made. Only the axes that are created can be seen. The &#8230; parameter in the specification of the plot() function transfers all the additional parameters that are given to the visualize.lme() we&#8217;re creating to the plot()-function that is used here. We can use it to give proper names to both axes, as well as to set a title for the plot.</p>
<p>Then, a loop is created using for(). For each of the groups, a line will be plotted. In order to do so, a function is created based on the intercept and the slopes extracted earlier. Then, this created function (called &#8216;expression&#8217;) is entered into the curve()-function. This curve()-function draws a graph based on a function (for instance, the one we just created) from a starting point to an end-point that both are specified. This process is repeated for every group in the model, resulting in a basic graph based on our multilevel, random intercept and random slope regression model.</p>
<p>Finnally, as well as for convenience, the complete syntax of this function will be shown below, as well as the result when used on the model we estimated at the start of this paragraph.</p>
<blockquote>
<p>visualize.lme <- function (model, coefficient, group, ...)<br />
{<br />
	r <- ranef(model)<br />
	f <- fixef(model)</p>
<p>	effects <- data.frame(r[,1]+f[1], r[,2]+f[2])</p>
<p>	number.lines <- nrow(effects)</p>
<p>	predictor.min <- tapply(model$data[[coefficient]], model$data[[group]], min)<br />
	predictor.max <- tapply(model$data[[coefficient]], model$data[[group]], max)</p>
<p>	outcome.min <- min(predict(model))<br />
	outcome.max <- max(predict(model))</p>
<p>	plot (c(min(predictor.min),max(predictor.max)),c(outcome.min,outcome.max), type="n", ...)</p>
<p>	for (i in 1:number.lines)<br />
	{<br />
		expression <- function(x) {effects[i,1] + (effects[i,2] * x) }<br />
		curve(expression, from=predictor.min[i], to=predictor.max[i], add=TRUE)<br />
	}<br />
}	</p>
<p>visualize.lme(model.01, "standLRT", "school", xlab="Student test at school-entry", ylab="Result on Exam", main="Exam results for 65 schools")
</p></blockquote>
<p><img src='http://i0.wp.com/www.rensenieuwenhuis.nl/wp-content/uploads/2007/06/multilevel-plot.gif?w=470' alt='Multilevel Plot' data-recalc-dims="1" /></p>
<p>&#8211; &#8211; &#8212; &#8212; &#8212;&#8211; &#8212;&#8212;&#8211;</p>
<ul>
<li><b><a href="http://www.rensenieuwenhuis.nl/R-forum/">Discuss this article and pose additional questions in the R-Sessions Forum</a></b></li>
<li><b><a href="http://www.rensenieuwenhuis.nl/r-project/manual/multilevel-analysis/plotting/">Find the original article embedded in the manual.</a></b></li>
</ul>
<p>&#8211; &#8211; &#8212; &#8212; &#8212;&#8211; &#8212;&#8212;&#8211;<br />
<a href="http://www.rensenieuwenhuis.nl/archive/category/r-project/r-sessions/">R-Sessions</a> is a collection of manual chapters for R-Project, which are maintained on <a href="www.rensenieuwenhuis.nl">Curving Normality</a>. All posts are linked to the chapters from the R-Project manual on this site. The manual is free to use, for it is paid by the advertisements, but please refer to it in your work inspired by it. Feedback and topic requests are highly appreciated.<br />
&#8212;&#8212;&#8211; &#8212;&#8211; &#8212; &#8212; &#8211; &#8211;<br />
</i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rensenieuwenhuis.nl/r-sessions-20-plotting-multilevel-models/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>R-Sessions 19: Extractor Functions</title>
		<link>http://www.rensenieuwenhuis.nl/r-sessions-19-extractor-functions/</link>
		<comments>http://www.rensenieuwenhuis.nl/r-sessions-19-extractor-functions/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 10:58:43 +0000</pubDate>
		<dc:creator><![CDATA[Rense Nieuwenhuis]]></dc:creator>
				<category><![CDATA[R-Project]]></category>
		<category><![CDATA[R-Sessions]]></category>
		<category><![CDATA[anova]]></category>
		<category><![CDATA[extractor functions]]></category>
		<category><![CDATA[fixef]]></category>
		<category><![CDATA[lme4]]></category>
		<category><![CDATA[multilevel]]></category>
		<category><![CDATA[ranef]]></category>

		<guid isPermaLink="false">http://www.rensenieuwenhuis.nl/?p=571</guid>
		<description><![CDATA[<a href="http://www.rensenieuwenhuis.nl/archive/category/r-project/r-sessions/"><img src="http://www.rensenieuwenhuis.nl/wp-content/uploads/2008/07/r-sessions.jpg" " title="R-Sessions" width="470" /></a>

Unlike most statistical software packages, R often stores the results of an analysis in an object. The advantage of this is that while not all output is shown in the screen ad once, it is neither necessary to estimate the statistical model again if different output is required.

This paragraph will show the kind of data that is stored in a multilevel model estimated by R-Project and introduce some functions that make use of this data.]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.rensenieuwenhuis.nl/archive/category/r-project/r-sessions/"><img src="http://i0.wp.com/www.rensenieuwenhuis.nl/wp-content/uploads/2008/07/r-sessions.jpg?w=470" " title="R-Sessions" data-recalc-dims="1" /></a><br />
<!--adsense--></p>
<p>Unlike most statistical software packages, R often stores the results of an analysis in an object. The advantage of this is that while not all output is shown in the screen ad once, it is neither necessary to estimate the statistical model again if different output is required.</p>
<p>This paragraph will show the kind of data that is stored in a multilevel model estimated by R-Project and introduce some functions that make use of this data.<br />
<span id="more-571"></span></p>
<h2>Inside the model</h2>
<p>Let&#8217;s first estimate a simple multilevel model, using the nlme-package. For this paragraph we will use a model we estimated earlier: the education model with a random intercept and a random slope. This time though, we will assign it to an object that we call model.01. It is estimated as follows:</p>
<blockquote><p>
require(nlme)<br />
require(mlmRev)</p>
<p>model.01 <- lme(fixed = normexam ~ standLRT, data = Exam,<br />
	random = ~ standLRT | school)
</p></blockquote>
<p>Basically, this results in no output at all, although the activation of the packages creates a little output. Basic results can be obtained by simply calling the object:</p>
<blockquote><p>
model.01
</p></blockquote>
<pre>
> model.01
Linear mixed-effects model fit by REML
  Data: Exam 
  Log-restricted-likelihood: -4663.8
  Fixed: normexam ~ standLRT 
(Intercept)    standLRT 
-0.01164834  0.55653379 

Random effects:
 Formula: ~standLRT | school
 Structure: General positive-definite, Log-Cholesky parametrization
            StdDev    Corr  
(Intercept) 0.3034980 (Intr)
standLRT    0.1223499 0.494 
Residual    0.7440699       

Number of Observations: 4059
Number of Groups: 65 
</pre>
<p>This gives a first impression of the estimated model. But, there is more. To obtain an idea of the elements that are actually stored inside the model, we use the names() functions, that gives us the names of all the elements of the model. </p>
<blockquote><p>
names(model.01)<br />
model.01$method<br />
model.01$logLik
</p></blockquote>
<p>The output below shows that our model.01 contains seventeen elements. For reasons of space, only some will be described. &#8216;Contrasts&#8217; contains information on the way categorical variables were handled, &#8216;coefficients&#8217; contains the model-parameters, in &#8216;call&#8217; the model formula is stored and in &#8216;data&#8217; even the original data is stored. </p>
<pre>
> names(model.01)
 [1] "modelStruct"  "dims"         "contrasts"    "coefficients"
 [5] "varFix"       "sigma"        "apVar"        "logLik"      
 [9] "numIter"      "groups"       "call"         "terms"       
[13] "method"       "fitted"       "residuals"    "fixDF"       
[17] "data"        
> model.01$method
[1] "REML"
> model.01$logLik
[1] -4663.8
</pre>
<p>In the syntax above two specific elements of the model were requested: the estimation method and the loglikelihood. This is done by sub-setting the model using the $-sign after which the desired element is placed. The output tells us that model.01 was estimated using Restricted Maximum Likelihood and that the loglikelihood is -4663.8 large.</p>
<h2>Summary</h2>
<p>All the information we could possibly want is stored inside the models, as we have seen. In order to receive synoptic results, many functions exist to extract some of the elements from the model and present them clearly. The most basic of these extractor-functions is probably summary():</p>
<blockquote><p>
summary(model.01)
</p></blockquote>
<pre>
> summary(model.01)
Linear mixed-effects model fit by REML
 Data: Exam 
     AIC     BIC  logLik
  9339.6 9377.45 -4663.8

Random effects:
 Formula: ~standLRT | school
 Structure: General positive-definite, Log-Cholesky parametrization
            StdDev    Corr  
(Intercept) 0.3034980 (Intr)
standLRT    0.1223499 0.494 
Residual    0.7440699       

Fixed effects: normexam ~ standLRT 
                 Value  Std.Error   DF   t-value p-value
(Intercept) -0.0116483 0.04010986 3993 -0.290411  0.7715
standLRT     0.5565338 0.02011497 3993 27.667639  0.0000
 Correlation: 
         (Intr)
standLRT 0.365 

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-3.8323045 -0.6316837  0.0339390  0.6834319  3.4562632 

Number of Observations: 4059
Number of Groups: 65 
</pre>
<h2>Anova</h2>
<p>The last extractor function that will be shown here is anova. This is a very general function that can be used for a great variety of models. When it is applied to a multilevel model, it results in a basic test for statistical significance of the model-parameters, as is showed below. </p>
<blockquote><p>
anova(model.01)</p>
<p>model.02 <- lme(fixed = normexam ~ standLRT, data = Exam,<br />
	random = ~ 1 | school)</p>
<p>anova(model.02,model.01)
</p></blockquote>
<p>In the syntax above an additional model is estimated that is very similar to our model.01, but does not have a random slope. It is stored in the object model.02. This is done to show that it is possible to test whether the random slope model fits better to the data than the fixed slope model. The output below shows that this is indeed the case.</p>
<pre>
> anova(model.01)
            numDF denDF  F-value p-value
(Intercept)     1  3993 124.3969  <.0001
standLRT        1  3993 765.4983  <.0001
> 
> model.02 <- lme(fixed = normexam ~ standLRT, data = Exam,
+ 	random = ~ 1 | school)
> 
> anova(model.02,model.01)
         Model df      AIC      BIC    logLik   Test  L.Ratio
model.02     1  4 9376.765 9401.998 -4684.383                
model.01     2  6 9339.600 9377.450 -4663.800 1 vs 2 41.16494
         p-value
model.02        
model.01  <.0001
</pre>
<p>- - -- --- ----- --------</p>
<ul>
<li><b><a href="http://www.rensenieuwenhuis.nl/R-forum/">Discuss this article and pose additional questions in the R-Sessions Forum</a></b></li>
<li><b><a href="http://www.rensenieuwenhuis.nl/r-project/manual/multilevel-analysis/extractor-functions/">Find the original article embedded in the manual.</a></b></li>
</ul>
<p>- - -- --- ----- --------<br />
<a href="http://www.rensenieuwenhuis.nl/archive/category/r-project/r-sessions/">R-Sessions</a> is a collection of manual chapters for R-Project, which are maintained on <a href="www.rensenieuwenhuis.nl">Curving Normality</a>. All posts are linked to the chapters from the R-Project manual on this site. The manual is free to use, for it is paid by the advertisements, but please refer to it in your work inspired by it. Feedback and topic requests are highly appreciated.<br />
-------- ----- --- -- - -<br />
</i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rensenieuwenhuis.nl/r-sessions-19-extractor-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
