library(psych)
library(psychTools)
Graphic displays are among the most useful tools in R. Some of the
basic graphic tools have been used in the psych
package for
displays of factor/cluster structures, models of linear regressions,
etc. These all take advantage of some basic graphic tools.
The most basic function is plot
which creates a graphic
window with certain parameters (arguments).
Arguments to be passed to methods, such as graphical parameters (see par). Many methods will accept the following arguments:
type what type of plot should be drawn. Possible types are
“p” for points,
“l” for lines,
“b” for both,
“c” for the lines part alone of “b”,
“o” for both ‘overplotted’,
“h” for ‘histogram’ like (or ‘high-density’) vertical lines,
“s” for stair steps,
“S” for other steps,
see ‘Details’ below,
“n” for no plotting.
All other types give a warning or an error; using, e.g., type = “punkte” being equivalent to type = “p” for S compatibility.
Note that some methods, e.g. plot.factor, do not accept this.
Other parameters passed to plot
xlim The size of the x axis ylim The size of the y axis
xlab The label for the x axis ylab The label for the y axis
main A title for the figure
axes Show the axes (defaults to TRUE)
frame.plot Show the frame (defaults to TRUE)
cex The size of the characters
pch Which plot character to use for data points
plot(0, type="n")
plot(x=1:10,y=10:1, xlab="X variable" , ylab= "Y variable", main="A title for this plot")
plot(x=1:10,y=10:1, xlab="X variable" , ylab= "Y variable", main="A title for this plot")
text(2,4,"some text")
text(8,6, "more informative text")
# Psych graphics use core R graphics
tidyverse
makes use of ggplot
which is more
powerful.
psych
has two broad classes of graphics: those that draw
diagrams and those that plot data.
We will examine the code behind the various diagram functions.
fa.diagram
, iclust.diagram
,
lmDiagram
call the primitive functions in the diagram.
These primitives dia.rect
, dia.ellipse
,
dia.arrow
, dia.curved.arrow
may be combined to
make complex diagrams.
To use these functions, we first must initialize the plot function with margins.
xlim=c(-2,10); ylim=c(0,10)
#initiate plot
plot(NA,xlim=xlim,ylim=ylim,main="Demonstration of diagram functions", axes=FALSE, xlab="", ylab="")
That just creates an empty page. We do this again, with some shapes. We
specify where on the page we want the shapes.
#first set up the margins and initiate the plot
xlim=c(-2,10); ylim=c(0,10)
plot(NA,xlim=xlim,ylim=ylim,main="Demonstration of diagram functions",
axes=FALSE,xlab="",ylab="")
#place and name the objects
ul <- dia.rect(1,9,labels="upper left",xlim=xlim,ylim=ylim)
ml <- dia.rect(1,6,"middle left",xlim=xlim,ylim=ylim)
ll <- dia.rect(1,3,labels="lower left",xlim=xlim,ylim=ylim)
bl <- dia.rect(1,1,"bottom left",xlim=xlim,ylim=ylim)
lr <- dia.ellipse(7,3,"lower right",xlim=xlim,ylim=ylim,e.size=.07)
ur <- dia.ellipse(7,9,"upper right",xlim=xlim,ylim=ylim,e.size=.07)
mr <- dia.ellipse(7,6,"middle right",xlim=xlim,ylim=ylim,e.size=.07)
lm <- dia.triangle(4,1,"Lower Middle",xlim=xlim,ylim=ylim)
br <- dia.rect(9,1,"bottom right",xlim=xlim,ylim=ylim)
Now, we want to connect these objects with curves and arrows.
#first set up the margins and initiate the plot
xlim=c(-2,10); ylim=c(0,10)
plot(NA,xlim=xlim,ylim=ylim,main="Demonstration of diagram functions",
axes=FALSE,xlab="",ylab="")
#place and name the objects
ul <- dia.rect(1,9,labels="upper left",xlim=xlim,ylim=ylim)
ml <- dia.rect(1,6,"middle left",xlim=xlim,ylim=ylim)
ll <- dia.rect(1,3,labels="lower left",xlim=xlim,ylim=ylim)
bl <- dia.rect(1,1,"bottom left",xlim=xlim,ylim=ylim)
lr <- dia.ellipse(7,3,"lower right",xlim=xlim,ylim=ylim,e.size=.07)
ur <- dia.ellipse(7,9,"upper right",xlim=xlim,ylim=ylim,e.size=.07)
mr <- dia.ellipse(7,6,"middle right",xlim=xlim,ylim=ylim,e.size=.07)
lm <- dia.triangle(4,1,"Lower Middle",xlim=xlim,ylim=ylim)
br <- dia.rect(9,1,"bottom right",xlim=xlim,ylim=ylim)
#connect them
dia.curve(from=ul$left,to=bl$left,"double headed",scale=-1)
dia.arrow(from=lr,to=ul$right,labels="right to left")
dia.arrow(from=ul,to=ur,labels="left to right")
dia.curved.arrow(from=lr,to=ll,labels ="right to left")
## NULL
dia.curved.arrow(to=ur,from=ul,labels ="left to right")
## NULL
dia.curve(ll$top,ul$bottom,"right",pos=4) #for rectangles, specify where to point
dia.arrow(from=lm, to= lr, "lower middle to lower right")
dia.curve(ur$right,lr$right,"top down",scale =2) #scale is size and curvature
dia.curve(ur$right,mr$right,"top down",scale =1) #scale is size and curvature
That is better, but lets clean it up a bit by changing the size, as well
as fixing some of the text.
#first set up the margins and initiate the plot
xlim=c(-1,10); ylim=c(1,10)
plot(NA,xlim=xlim,ylim=ylim,main="Demonstration of diagram functions",
axes=FALSE,xlab="",ylab="")
#place and name the objects
ul <- dia.rect(1,9,labels="upper left",xlim=xlim,ylim=ylim)
ml <- dia.rect(1,6,"middle left",xlim=xlim,ylim=ylim)
ll <- dia.rect(1,3,labels="lower left",xlim=xlim,ylim=ylim)
bl <- dia.rect(1,1,"bottom left",xlim=xlim,ylim=ylim)
lr <- dia.ellipse(7,3,"lower right",xlim=xlim,ylim=ylim,e.size=.09)
ur <- dia.ellipse(7,9,"upper right",xlim=xlim,ylim=ylim,e.size=.08)
mr <- dia.ellipse(7,6,"middle right",xlim=xlim,ylim=ylim,e.size=.07) #too small
lm <- dia.triangle(4,1,"Lower Middle",xlim=xlim,ylim=ylim)
br <- dia.rect(9,1,"bottom right",xlim=xlim,ylim=ylim)
#now connect the shapes
dia.curve(from=ul$left,to=bl$left,"double\nheaded",scale=-.8)
dia.arrow(from=lr,to=ul$right,labels="right to left")
dia.arrow(from=ul,to=ur,labels="left to\n right",gap.size=.25)
dia.curved.arrow(from=lr,to=ll,labels ="right to\n left")
## NULL
dia.curved.arrow(to=ur,from=ul,labels ="left to right")
## NULL
dia.curve(ll$top,ul$bottom,"right",pos=4) #for rectangles, specify where to point
dia.arrow(from=lm, to= lr, "lower middle to \nlower right")#use \n for new line
dia.curve(ur$right,lr$right,"top down",scale =2) #scale is size and curvature
dia.curve(ur$right,mr$right,"top down",scale =1) #scale is size and curvature
This figure is a bit squased. Can we increase the y dimension.
#first set up the margins and initiate the plot
xlim=c(-1,10); ylim=c(0,10)
plot(NA,xlim=xlim,ylim=ylim,main="Demonstration of diagram functions",
axes=FALSE,xlab="",ylab="")
#place and name the objects
ul <- dia.rect(1,9,labels="upper left",xlim=xlim,ylim=ylim)
ml <- dia.rect(1,6,"middle left",xlim=xlim,ylim=ylim)
ll <- dia.rect(1,3,labels="lower left",xlim=xlim,ylim=ylim)
bl <- dia.rect(1,1,"bottom left",xlim=xlim,ylim=ylim)
lr <- dia.ellipse(7,3,"lower right",xlim=xlim,ylim=ylim,e.size=.09)
ur <- dia.ellipse(7,9,"upper right",xlim=xlim,ylim=ylim,e.size=.08)
mr <- dia.ellipse(7,6,"middle right",xlim=xlim,ylim=ylim,e.size=.07) #too small
lm <- dia.triangle(4,1,"Lower Middle",xlim=xlim,ylim=ylim)
br <- dia.rect(9,1,"bottom right",xlim=xlim,ylim=ylim)
#now connect the shapes
dia.curve(from=ul$left,to=bl$left,"double\nheaded",scale=-.8)
dia.arrow(from=lr,to=ul$right,labels="right to left")
dia.arrow(from=ul,to=ur,labels="left to\n right",gap.size=.25)
dia.curved.arrow(from=lr,to=ll,labels ="right to\n left")
## NULL
dia.curved.arrow(to=ur,from=ul,labels ="left to right")
## NULL
dia.curve(ll$top,ul$bottom,"right",pos=4) #for rectangles, specify where to point
dia.arrow(from=lm, to= lr, "lower middle to \nlower right")#use \n for new line
dia.curve(ur$right,lr$right,"top down",scale =2) #scale is size and curvature
dia.curve(ur$right,mr$right,"top down",scale =1) #scale is size and curvature
This is not pretty. It looks better if we don’t run this in R studio.
Take examples from the help pages and modify them.
Consider the help page for `layout’. This discusses how to create multiple sub windows in one window.
We use their example and their example data:
def.par <- par(no.readonly = TRUE) # save default, for resetting...
##-- Create a scatterplot with marginal histograms -----
x <- pmin(3, pmax(-3, stats::rnorm(50)))
y <- pmin(3, pmax(-3, stats::rnorm(50)))
xhist <- hist(x, breaks = seq(-3,3,0.5), plot = FALSE)
yhist <- hist(y, breaks = seq(-3,3,0.5), plot = FALSE)
top <- max(c(xhist$counts, yhist$counts))
xrange <- c(-3, 3)
yrange <- c(-3, 3)
nf <- layout(matrix(c(2,0,1,3),2,2,byrow = TRUE), c(3,1), c(1,3), TRUE)
layout.show(nf)
par(mar = c(3,3,1,1))
plot(x, y, xlim = xrange, ylim = yrange, xlab = "", ylab = "")
par(mar = c(0,3,1,1))
barplot(xhist$counts, axes = FALSE, ylim = c(0, top), space = 0)
par(mar = c(3,0,1,1))
barplot(yhist$counts, axes = FALSE, xlim = c(0, top), space = 0, horiz = TRUE)
par(def.par) #- reset to default
Use those same x and y data, and draw it again, with
scatterHist
from psych
.
scatterHist
took the basic concepts from layout, and then
added some bells and whistles.
scatterHist(x,y, main="data from layout example")
pairs
to pairs.panels
Learn to read the help
pages for each function. Then Try
the examples.
The pairs
function in core R has a very helpful help
menu with examples.
pairs(iris[1:4], main = "Anderson's Iris Data -- 3 species",
pch = 21, bg = c("red", "green3", "blue")[unclass(iris$Species)])
To see the code for particular functions, you can try just typing the
name of the function. If it is a method
then you can ask
for the various versions of that method.
pairs #either show the code or show that it is a method
## function (x, ...)
## UseMethod("pairs")
## <bytecode: 0x140207448>
## <environment: namespace:graphics>
methods(pairs) #show all the methods using `pairs`
## [1] pairs.compareFits* pairs.default* pairs.formula* pairs.lme* pairs.lmList*
## [6] pairs.panels*
## see '?methods' for accessing help and source code
We can then examine the code for any of those methods by calling
getAnywhere
with the name of the method. e.g.
getAnywhere(pairs.default)
(not run)
This was done to create pairs.panels
function.
From help menu:
The various examples from the help page for pairs
can be
incorporated in one function pairs.panels
for psych.’
Shamelessly adapted from the pairs help page. Uses panel.cor, panel.cor.scale, and panel.hist, all taken from the help pages for pairs. Also adapts the ellipse function from John Fox’s car package.
pairs.panels is most useful when the number of variables to plot is less than about 6-10. It is particularly useful for an initial overview of the data.
To show different groups with different colors, use a plot character (pch) between 21 and 25 and then set the background color to vary by group. (See the second example).
pairs.panels(iris[1:4],bg=c("red","yellow","blue")[iris$Species],
pch=21+as.numeric(iris$Species),main="Fisher Iris data by Species",hist.col="red")