Paruelo and Lauenroth (1996) analyzed the geographic distribution and
the effects of climate variables on the relative abundance of a number
of plant functional types (PFTs) including shrubs, forbs, succulents
(e.g. cacti), C3 grasses and C4 grasses. There were 73 sites across
North America. The response variable we will focus on is the relative
abundance of C3 plants and there were six potential predictors: the
latitude in centesimal degrees (LAT), the longitude in centesimal
degrees (LONG), the mean annual precipitation in mm (MAP), the mean
annual temperature in °C (MAT), the proportion of MAP that fell in June,
July and August (JJAMAP) and the proportion of MAP that fell in
December, January and February (DJFMAP).
This is an example from the first edition; the data file is here
Paruelo, J. M. & Lauenroth, W. K. (1996). Relative abundance of
plant functional types in grasslands and shrublands of North America.
Ecological Applications, 6, 1212-24.
Preliminaries
First, load the required packages (car, lm.beta, reghelper, Rmisc and
rgl)
Import paruelo data file (paruelo.csv)
paruelo <- read.csv("../data/paruelo.csv")
head(paruelo,10)
Diagnostic checks
We will use the scatterplotMatrix function from the car package
scatterplotMatrix(~c3+lat+long+map+mat+jjamap+djfmap, data=paruelo, cex=0.33, regLine=FALSE, diagonal=list(method='boxplot'))
C3 positively skewed but not too bad; no obvious non-linearities
Now check for collinearity among all predictors - correlations and
VIFs
cor(paruelo[,c('lat','long','map','mat','jjamap','djfmap')])
lat long map mat jjamap djfmap
lat 1.0000 0.0966 -0.247 -0.83859 0.0742 -0.06512
long 0.0966 1.0000 -0.734 -0.21311 -0.4916 0.77074
map -0.2465 -0.7337 1.000 0.35509 0.1123 -0.40451
mat -0.8386 -0.2131 0.355 1.00000 -0.0808 0.00148
jjamap 0.0742 -0.4916 0.112 -0.08077 1.0000 -0.79154
djfmap -0.0651 0.7707 -0.405 0.00148 -0.7915 1.00000
vif(lm(c3~lat+long+map+mat+jjamap+djfmap, data=paruelo))
lat long map mat jjamap djfmap
3.50 5.27 2.80 3.74 3.16 5.71
Obvious collinearity with environmental variables tending to be
correlated strongly with lat or long, so we’ll split predictors into 2
groups, one with lat and long
First model c3 against lat and long and lat*long and check for
collinearity
vif(lm(c3~lat+long+lat*long, data=paruelo))
there are higher-order terms (interactions) in this model
consider setting type = 'predictor'; see ?vif
lat long lat:long
307.7 66.8 400.9
VIFs very high indicating obvious collinearity as expected with
interaction term
Run uncentred model
paruelo.lm <- lm(c3~lat+long+lat*long, data=paruelo)
Get regression diagnostics (residual plot and Cooks D)
plot(paruelo.lm)
augment(paruelo.lm)
Display results of model fitting
glance(paruelo.lm)
tidy(paruelo.lm, conf.int=TRUE)
Get standardized regression coefficients, use lm.beta function from
lm.beta package
lm.beta.paruelo <- lm.beta(paruelo.lm)
tidy(lm.beta.paruelo, conf.int=TRUE)
Centre predictors and refit model
paruelo$clat <- scale(paruelo$lat, center=TRUE, scale=FALSE)
paruelo$clong <- scale(paruelo$long, center=TRUE, scale=FALSE)
paruelo1.lm <- lm(c3~clat+clong+clat*clong, data=paruelo)
Recheck collinearity
vif(lm(c3~clat+clong+clat*clong, data=paruelo))
there are higher-order terms (interactions) in this model
consider setting type = 'predictor'; see ?vif
clat clong clat:clong
1.21 1.02 1.22
Regression diagnostics (residual plot and Cooks D)
plot(paruelo1.lm)
augment(paruelo1.lm)
Diagnostics look better now
Display results of model fitting
glance(paruelo1.lm)
tidy(paruelo1.lm, conf.int=TRUE)
Get standardized regression coefficients, use lm.beta function from
lm.beta package
lm.beta(paruelo1.lm)
Call:
lm(formula = c3 ~ clat + clong + clat * clong, data = paruelo)
Standardized Coefficients::
(Intercept) clat clong clat:clong
NA 0.770191 0.000703 0.249471
Standardise predictors and refit model
paruelo$slat <- scale(paruelo$lat, center=TRUE, scale=TRUE)
paruelo$slong <- scale(paruelo$long, center=TRUE, scale=TRUE)
paruelo2.lm <- lm(c3~slat+slong+slat*slong, data=paruelo)
Recheck collinearity
vif(lm(c3~slat+slong+slat*slong, data=paruelo))
there are higher-order terms (interactions) in this model
consider setting type = 'predictor'; see ?vif
slat slong slat:slong
1.21 1.02 1.22
Regression diagnostics (residual plot and Cooks D)
plot(paruelo2.lm)
augment(paruelo2.lm)
Display results of model fitting
glance(paruelo2.lm)
tidy(paruelo2.lm, conf.int=TRUE)
Get standardised regression coefficients, use lm.beta function from
lm.beta package
lm.beta(paruelo2.lm)
Call:
lm(formula = c3 ~ slat + slong + slat * slong, data = paruelo)
Standardized Coefficients::
(Intercept) slat slong slat:slong
NA 0.770191 0.000703 0.249471
3d scatterplot with smoothing surface
Note on mac OS - need xquartz installed. Graphic
opens in separate window in Mac/Xquartz; haven’t checked on other
operating systems.
Rotate the graph using the mouse or cursor keys
scatter3d(c3~lat+long, grid = FALSE, fit = "smooth", data=paruelo)
Examine simple slopes using reghelper package
simple_slopes(paruelo.lm)
lat long Test Estimate Std. Error t value df Pr(>|t|) Sig.
1 34.801242 sstest -0.010 0.005 -2.039 69 0.0453 *
2 40.104247 sstest 0.000 0.004 0.008 69 0.9935
3 45.407251 sstest 0.010 0.005 1.848 69 0.0689 .
4 sstest 99.96472 0.026 0.005 5.159 69 2.27e-06 ***
5 sstest 106.400137 0.038 0.005 8.198 69 8.69e-12 ***
6 sstest 112.835554 0.050 0.008 6.484 69 1.13e-08 ***
LS0tCnRpdGxlOiAiUUsgQm94IDguOCIKCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBmbGF0bHkKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKClBhcnVlbG8gYW5kIExhdWVucm90aCAoMTk5NikgYW5hbHl6ZWQgdGhlIGdlb2dyYXBoaWMgZGlzdHJpYnV0aW9uIGFuZCB0aGUgZWZmZWN0cyBvZiBjbGltYXRlIHZhcmlhYmxlcyBvbiB0aGUgcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIGEgbnVtYmVyIG9mIHBsYW50IGZ1bmN0aW9uYWwgdHlwZXMgKFBGVHMpIGluY2x1ZGluZyBzaHJ1YnMsIGZvcmJzLCBzdWNjdWxlbnRzIChlLmcuIGNhY3RpKSwgQzMgZ3Jhc3NlcyBhbmQgQzQgZ3Jhc3Nlcy4gVGhlcmUgd2VyZSA3MyBzaXRlcyBhY3Jvc3MgTm9ydGggQW1lcmljYS4gVGhlIHJlc3BvbnNlIHZhcmlhYmxlIHdlIHdpbGwgZm9jdXMgb24gaXMgdGhlIHJlbGF0aXZlIGFidW5kYW5jZSBvZiBDMyBwbGFudHMgYW5kIHRoZXJlIHdlcmUgc2l4IHBvdGVudGlhbCBwcmVkaWN0b3JzOiB0aGUgbGF0aXR1ZGUgaW4gY2VudGVzaW1hbCBkZWdyZWVzIChMQVQpLCB0aGUgbG9uZ2l0dWRlIGluIGNlbnRlc2ltYWwgZGVncmVlcyAoTE9ORyksIHRoZSBtZWFuIGFubnVhbCBwcmVjaXBpdGF0aW9uIGluIG1tIChNQVApLCB0aGUgbWVhbiBhbm51YWwgdGVtcGVyYXR1cmUgaW4gwrBDIChNQVQpLCB0aGUgcHJvcG9ydGlvbiBvZiBNQVAgdGhhdCBmZWxsIGluIEp1bmUsIEp1bHkgYW5kIEF1Z3VzdCAoSkpBTUFQKSBhbmQgdGhlIHByb3BvcnRpb24gb2YgTUFQIHRoYXQgZmVsbCBpbiBEZWNlbWJlciwgSmFudWFyeSBhbmQgRmVicnVhcnkgKERKRk1BUCkuCgpUaGlzIGlzIGFuIGV4YW1wbGUgZnJvbSB0aGUgZmlyc3QgZWRpdGlvbjsgdGhlIGRhdGEgZmlsZSBpcyBbaGVyZV0oZGF0YS9wYXJ1ZWxvLmNzdikKClBhcnVlbG8sIEouIE0uICYgTGF1ZW5yb3RoLCBXLiBLLiAoMTk5NikuIFJlbGF0aXZlIGFidW5kYW5jZSBvZiBwbGFudCBmdW5jdGlvbmFsIHR5cGVzIGluIGdyYXNzbGFuZHMgYW5kIHNocnVibGFuZHMgb2YgTm9ydGggQW1lcmljYS4gKkVjb2xvZ2ljYWwgQXBwbGljYXRpb25zKiwgNiwgMTIxMi0yNC4KCiMjIyBQcmVsaW1pbmFyaWVzCgpGaXJzdCwgbG9hZCB0aGUgcmVxdWlyZWQgcGFja2FnZXMgKGNhciwgbG0uYmV0YSwgcmVnaGVscGVyLCBSbWlzYyBhbmQgcmdsKQoKYGBge3IgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZScsIGVycm9yPVRSVUV9CnNvdXJjZSgiLi4vUi9saWJyYXJpZXMuUiIpICAgI1RoaXMgaXMgdGhlIGNvbW1vbiBsaWJyYXJ5CmxpYnJhcnkobG0uYmV0YSkKbGlicmFyeShyZWdoZWxwZXIpCmxpYnJhcnkocmdsKQpgYGAKCkltcG9ydCBwYXJ1ZWxvIGRhdGEgZmlsZSAocGFydWVsby5jc3YpCgpgYGB7cn0KcGFydWVsbyA8LSByZWFkLmNzdigiLi4vZGF0YS9wYXJ1ZWxvLmNzdiIpCmhlYWQocGFydWVsbywxMCkKYGBgCgojIyMgRGlhZ25vc3RpYyBjaGVja3MKCldlIHdpbGwgdXNlIHRoZSBzY2F0dGVycGxvdE1hdHJpeCBmdW5jdGlvbiBmcm9tIHRoZSBjYXIgcGFja2FnZQoKYGBge3IgfQpzY2F0dGVycGxvdE1hdHJpeCh+YzMrbGF0K2xvbmcrbWFwK21hdCtqamFtYXArZGpmbWFwLCBkYXRhPXBhcnVlbG8sIGNleD0wLjMzLCByZWdMaW5lPUZBTFNFLCBkaWFnb25hbD1saXN0KG1ldGhvZD0nYm94cGxvdCcpKQpgYGAKCkMzIHBvc2l0aXZlbHkgc2tld2VkIGJ1dCBub3QgdG9vIGJhZDsgbm8gb2J2aW91cyBub24tbGluZWFyaXRpZXMKCk5vdyBjaGVjayBmb3IgY29sbGluZWFyaXR5IGFtb25nIGFsbCBwcmVkaWN0b3JzIC0gY29ycmVsYXRpb25zIGFuZCBWSUZzCgpgYGB7ciB9CmNvcihwYXJ1ZWxvWyxjKCdsYXQnLCdsb25nJywnbWFwJywnbWF0JywnamphbWFwJywnZGpmbWFwJyldKQp2aWYobG0oYzN+bGF0K2xvbmcrbWFwK21hdCtqamFtYXArZGpmbWFwLCBkYXRhPXBhcnVlbG8pKQpgYGAKCk9idmlvdXMgY29sbGluZWFyaXR5IHdpdGggZW52aXJvbm1lbnRhbCB2YXJpYWJsZXMgdGVuZGluZyB0byBiZSBjb3JyZWxhdGVkIHN0cm9uZ2x5IHdpdGggbGF0IG9yIGxvbmcsIHNvIHdlJ2xsIHNwbGl0IHByZWRpY3RvcnMgaW50byAyIGdyb3Vwcywgb25lIHdpdGggbGF0IGFuZCBsb25nCgojIyBGaXJzdCBtb2RlbCBjMyBhZ2FpbnN0IGxhdCBhbmQgbG9uZyBhbmQgbGF0XCpsb25nIGFuZCBjaGVjayBmb3IgY29sbGluZWFyaXR5CgpgYGB7ciB9CnZpZihsbShjM35sYXQrbG9uZytsYXQqbG9uZywgZGF0YT1wYXJ1ZWxvKSkKYGBgCgpWSUZzIHZlcnkgaGlnaCBpbmRpY2F0aW5nIG9idmlvdXMgY29sbGluZWFyaXR5IGFzIGV4cGVjdGVkIHdpdGggaW50ZXJhY3Rpb24gdGVybQoKIyMjIFJ1biB1bmNlbnRyZWQgbW9kZWwKCmBgYHtyIH0KcGFydWVsby5sbSA8LSBsbShjM35sYXQrbG9uZytsYXQqbG9uZywgZGF0YT1wYXJ1ZWxvKQpgYGAKCkdldCByZWdyZXNzaW9uIGRpYWdub3N0aWNzIChyZXNpZHVhbCBwbG90IGFuZCBDb29rcyBEKQoKYGBge3IgfQpwbG90KHBhcnVlbG8ubG0pCmF1Z21lbnQocGFydWVsby5sbSkKYGBgCgojIyMjIERpc3BsYXkgcmVzdWx0cyBvZiBtb2RlbCBmaXR0aW5nCgpgYGB7ciB9CmdsYW5jZShwYXJ1ZWxvLmxtKQp0aWR5KHBhcnVlbG8ubG0sIGNvbmYuaW50PVRSVUUpCmBgYAoKR2V0IHN0YW5kYXJkaXplZCByZWdyZXNzaW9uIGNvZWZmaWNpZW50cywgdXNlIGxtLmJldGEgZnVuY3Rpb24gZnJvbSBsbS5iZXRhIHBhY2thZ2UKCmBgYHtyIH0KbG0uYmV0YS5wYXJ1ZWxvIDwtIGxtLmJldGEocGFydWVsby5sbSkKdGlkeShsbS5iZXRhLnBhcnVlbG8sIGNvbmYuaW50PVRSVUUpCmBgYAoKIyMjIENlbnRyZSBwcmVkaWN0b3JzIGFuZCByZWZpdCBtb2RlbAoKYGBge3IgfQpwYXJ1ZWxvJGNsYXQgPC0gc2NhbGUocGFydWVsbyRsYXQsIGNlbnRlcj1UUlVFLCBzY2FsZT1GQUxTRSkKcGFydWVsbyRjbG9uZyA8LSBzY2FsZShwYXJ1ZWxvJGxvbmcsIGNlbnRlcj1UUlVFLCBzY2FsZT1GQUxTRSkKcGFydWVsbzEubG0gPC0gbG0oYzN+Y2xhdCtjbG9uZytjbGF0KmNsb25nLCBkYXRhPXBhcnVlbG8pCmBgYAoKUmVjaGVjayBjb2xsaW5lYXJpdHkKCmBgYHtyIH0KdmlmKGxtKGMzfmNsYXQrY2xvbmcrY2xhdCpjbG9uZywgZGF0YT1wYXJ1ZWxvKSkKYGBgCgpSZWdyZXNzaW9uIGRpYWdub3N0aWNzIChyZXNpZHVhbCBwbG90IGFuZCBDb29rcyBEKQoKYGBge3IgfQpwbG90KHBhcnVlbG8xLmxtKQphdWdtZW50KHBhcnVlbG8xLmxtKQpgYGAKCkRpYWdub3N0aWNzIGxvb2sgYmV0dGVyIG5vdwoKIyMjIyBEaXNwbGF5IHJlc3VsdHMgb2YgbW9kZWwgZml0dGluZwoKYGBge3IgfQpnbGFuY2UocGFydWVsbzEubG0pCnRpZHkocGFydWVsbzEubG0sIGNvbmYuaW50PVRSVUUpCmBgYAoKR2V0IHN0YW5kYXJkaXplZCByZWdyZXNzaW9uIGNvZWZmaWNpZW50cywgdXNlIGxtLmJldGEgZnVuY3Rpb24gZnJvbSBsbS5iZXRhIHBhY2thZ2UKCmBgYHtyIH0KbG0uYmV0YShwYXJ1ZWxvMS5sbSkKYGBgCgojIyMgU3RhbmRhcmRpc2UgcHJlZGljdG9ycyBhbmQgcmVmaXQgbW9kZWwKCmBgYHtyIH0KcGFydWVsbyRzbGF0IDwtIHNjYWxlKHBhcnVlbG8kbGF0LCBjZW50ZXI9VFJVRSwgc2NhbGU9VFJVRSkKcGFydWVsbyRzbG9uZyA8LSBzY2FsZShwYXJ1ZWxvJGxvbmcsIGNlbnRlcj1UUlVFLCBzY2FsZT1UUlVFKQpwYXJ1ZWxvMi5sbSA8LSBsbShjM35zbGF0K3Nsb25nK3NsYXQqc2xvbmcsIGRhdGE9cGFydWVsbykKYGBgCgpSZWNoZWNrIGNvbGxpbmVhcml0eQoKYGBge3IgfQp2aWYobG0oYzN+c2xhdCtzbG9uZytzbGF0KnNsb25nLCBkYXRhPXBhcnVlbG8pKQpgYGAKClJlZ3Jlc3Npb24gZGlhZ25vc3RpY3MgKHJlc2lkdWFsIHBsb3QgYW5kIENvb2tzIEQpCgpgYGB7ciB9CnBsb3QocGFydWVsbzIubG0pCmF1Z21lbnQocGFydWVsbzIubG0pCmBgYAoKIyMjIyBEaXNwbGF5IHJlc3VsdHMgb2YgbW9kZWwgZml0dGluZwoKYGBge3IgfQpnbGFuY2UocGFydWVsbzIubG0pCnRpZHkocGFydWVsbzIubG0sIGNvbmYuaW50PVRSVUUpCmBgYAoKR2V0IHN0YW5kYXJkaXNlZCByZWdyZXNzaW9uIGNvZWZmaWNpZW50cywgdXNlIGxtLmJldGEgZnVuY3Rpb24gZnJvbSBsbS5iZXRhIHBhY2thZ2UKCmBgYHtyIH0KbG0uYmV0YShwYXJ1ZWxvMi5sbSkKYGBgCgojIyMgM2Qgc2NhdHRlcnBsb3Qgd2l0aCBzbW9vdGhpbmcgc3VyZmFjZQoKKipOb3RlIG9uIG1hYyBPUyAtIG5lZWQgeHF1YXJ0eiBpbnN0YWxsZWQuKiogR3JhcGhpYyBvcGVucyBpbiBzZXBhcmF0ZSB3aW5kb3cgaW4gTWFjL1hxdWFydHo7IGhhdmVuJ3QgY2hlY2tlZCBvbiBvdGhlciBvcGVyYXRpbmcgc3lzdGVtcy4KClJvdGF0ZSB0aGUgZ3JhcGggdXNpbmcgdGhlIG1vdXNlIG9yIGN1cnNvciBrZXlzCgpgYGB7ciBlcnJvcj1UUlVFfQpzY2F0dGVyM2QoYzN+bGF0K2xvbmcsIGdyaWQgPSBGQUxTRSwgZml0ID0gInNtb290aCIsIGRhdGE9cGFydWVsbykKYGBgCgojIyMgRXhhbWluZSBzaW1wbGUgc2xvcGVzIHVzaW5nIHJlZ2hlbHBlciBwYWNrYWdlCgpgYGB7ciB9CnNpbXBsZV9zbG9wZXMocGFydWVsby5sbSkKYGBgCg==