Making graphs in R
Using the qgraph package
Sacha Epskamp
University of Amsterdam
Department of Psychological Methods
15-10-2013
All codes in these slides were run using R version 3.1.0
(2014-04-10) and qgraph version 1.2.5 and were made on
Windows 7 x64 x86-64 build 9200.
Get the latest version of R from www.r-project.org and the latest
version of qgraph from CRAN:
install.packages("qgraph",dep=TRUE)
Make sure you can load qgraph:
library("qgraph")
And that you have version 1.2.3 or higher:
packageDescription('qgraph')$Version
## [1] "1.2.5"
If this fails, make sure you have the latest (2.15) version of R
and that all depended/imported/suggested packages are
installed (see CRAN).
Defaults
Note that the following defaults are set for this presentation:
options(
qgraph = list(
border.width = 2,
asize = 8,
unCol = "black",
vsize = 10,
esize = 3)
)
So the codes can create different looking graphs on your
screen!
Help on R
Do it yourself. . .
I For basic understanding of R: Read through a R manual!
I
I
I
I
I
Help on how to use a function: Use the ? function (e.g.
?matrix)
I
I
I
How do I make a matrix?
How do I index an object?
What is a list?
Try a short one first! (R for beginners)
How do I define a matrix by row?
How do I set mean() to omit NA’s?
Find a certain function: Use the ?? function
I
What is a function to reduce a string to a certain amount of
characters?
I
I
??trim
Or use google!
Help on R
. . . or ask for help!
I
Stackoverflow websites (see next slide)
I
For problems concerning specific packages: Mail the
maintainer
I
For short questions, you can use Twitter or Google+ with
hashtag #rstats
Stackexchange
Stackexchange is a series of free question and answer
websites on many different topics. Two are very useful for
whenever you get stuck in R:
For programming technical questions regarding R see:
http://stackoverflow.com/
For statistical questions regarding R see:
http://crossvalidated.com/
In both of these make sure you use the tag r and include a
reproducible example:
http://stackoverflow.com/q/5963269/567015
Graphs
I
A graph is a network that consists of n nodes (or vertices)
that are connected with m edges.
I
Each edge can have a weight indicating the strength of
that connection
I
An edge can be directed (have an arrow) or undirected
Undirected
Directed
●
●
2
2
●
●
Unweighted
8
8
●
●
6
●
●
●
6
●
●
7
10
7
10
●
9
9
●
●
1
●
1
●
3
3
●
●
4
4
●
●
5
5
●
●
2
2
●
●
8
8
●
●
Weighted
6
●
●
●
6
●
●
7
10
7
10
●
9
9
●
●
1
●
1
●
3
3
●
4
●
4
●
5
●
5
Undirected
Directed
●
●
2
2
●
●
Unweighted
8
8
●
●
6
●
●
●
6
●
●
7
10
7
10
●
9
9
●
●
1
●
1
●
3
3
●
●
4
4
●
●
5
5
●
●
2
2
●
●
8
8
●
●
Weighted
6
●
●
●
6
●
●
7
10
7
10
●
9
9
●
●
1
●
1
●
3
3
●
4
●
4
●
5
●
5
The qgraph() function
I
The main function in qgraph is qgraph()
I
Most other functions are either wrapping functions using
qgraph() or functions used in qgraph()
I
The qgraph() function requires only one argument
(input)
I
A lot of other arguments can be specified, but these are all
optional
Usage:
qgraph( input, ... )
Weights matrices
I
The input argument is the input. This can be a weights
matrix
I
A weights matrix is a square n by n matrix in which each
element indicates the relationship between two variables
Any relationship can be used as long as:
I
I
I
I
A 0 indicates no relationship
Absolute negative values are similar in strength to positive
values
We will first look at unweighted graphs, in which case the
weights matrix is the same as an adjacency matrix
I
I
I
I
I
I
A 1 indicates a connection
A 0 indicates a connection
Rows indicate the node of origin
Columns indicate the node of destination
By default the diagonal is omitted
By default, a symetrical weights matrix is interpreted as an
unweighted graph
Weights matrices
qgraph(input)
input <- matrix(c(
0,1,1,
0,0,1,
0,0,0),3,3,byrow=TRUE)
print(input)
1
##
[,1] [,2] [,3]
## [1,]
0
1
1
## [2,]
0
0
1
## [3,]
0
0
0
3
2
Weights matrices
Exercise: Create this graph
6
5
7
4
8
3
1
2
The layout should be right automatically, only use one
argument in qgraph()
Weights matrices
To make this graph, we need this matrix:
##
##
##
##
##
##
##
##
##
[1,]
[2,]
[3,]
[4,]
[5,]
[6,]
[7,]
[8,]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
Weights matrices
These matrices become quite large, so manually defining the
matrix is not effective. So some tricks are needed to make the
matrix:
input <- matrix(0,8,8)
input[1,2] <- 1
input[2,3] <- 1
input[3,4] <- 1
input[4,5] <- 1
input[5,6] <- 1
input[6,7] <- 1
input[7,8] <- 1
input[8,1] <- 1
Weights matrices
print(input)
##
##
##
##
##
##
##
##
##
[1,]
[2,]
[3,]
[4,]
[5,]
[6,]
[7,]
[8,]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
Weights matrices
You can also change matrices manually (doesn’t work in
RStudio):
input <- matrix(0,8,8)
fix(input)
Or read the matrix from a text file!
Weights matrices
First make the matrix in a spreadsheet program (here
LibreOffice)
Weights matrices
Next save as or export
Weights matrices
Save as CSV (comma delimited text file) or tab delimited:
Weights matrices
Read in R (for tab delimited use read.table():
input <- read.csv("adj.csv",header=FALSE)
print(input)
##
##
##
##
##
##
##
##
##
1
2
3
4
5
6
7
8
V1 V2 V3 V4 V5 V6 V7 V8
0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0
Weights matrices
These methods are not reproducible. Scripts should not
depend on manual input. An easy way to change this is to first
define a matrix. then run dput() on the object and use that
result in your script:
dput(input)
##
##
##
##
structure(c(0, 0, 0,
1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0), .Dim
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
= c(8L, 8L))
Weights matrices
input2 <- structure(c(0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0), .Dim = c(8L, 8L))
print(input2)
##
##
##
##
##
##
##
##
##
[1,]
[2,]
[3,]
[4,]
[5,]
[6,]
[7,]
[8,]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
Weights matrices
Exercise: Create this graph
3
7
6
8
1
2
4
5
Weights matrices
##
##
##
##
##
##
##
##
##
[1,]
[2,]
[3,]
[4,]
[5,]
[6,]
[7,]
[8,]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
The directed argument
I
The directed argument can be used to force a directed
(TRUE) or undirected (FALSE) graph
I
This can also be specified per edge in a matrix
The directed argument
qgraph(input)
1
input<- matrix(1,3,3)
print(input)
##
[,1] [,2] [,3]
## [1,]
1
1
1
## [2,]
1
1
1
## [3,]
1
1
1
3
2
The directed argument
qgraph(input,directed=TRUE)
2
print(input)
1
##
[,1] [,2] [,3]
## [1,]
1
1
1
## [2,]
1
1
1
## [3,]
1
1
1
3
The directed argument
print(input)
##
[,1] [,2] [,3]
## [1,]
1
1
1
## [2,]
1
1
1
## [3,]
1
1
1
qgraph(input,directed=dir)
3
2
dir <- matrix(c(
FALSE,TRUE,FALSE,
TRUE,FALSE,FALSE,
FALSE,FALSE,FALSE)
,3,3,byrow=TRUE)
print(dir)
##
[,1] [,2] [,3]
## [1,] FALSE TRUE FALSE
## [2,] TRUE FALSE FALSE
## [3,] FALSE FALSE FALSE
1
The bidirectional argument
I
Multiple directed edges between two nodes are curved
I
To change this behavior, bidirectional can be set to
TRUE
I
Can also be a matrix
The bidirectional argument
qgraph(input,
directed=TRUE,
bidirectional=TRUE)
print(input)
2
1
##
[,1] [,2] [,3]
## [1,]
1
1
1
## [2,]
1
1
1
## [3,]
1
1
1
3
The bidirectional argument
print(input)
##
[,1] [,2] [,3]
## [1,]
1
1
1
## [2,]
1
1
1
## [3,]
1
1
1
qgraph(input,
directed=TRUE,
bidirectional=bidir)
2
bidir <- matrix(c(
FALSE,TRUE,FALSE,
TRUE,FALSE,FALSE,
FALSE,FALSE,FALSE)
,3,3,byrow=TRUE)
print(bidir)
##
[,1] [,2] [,3]
## [1,] FALSE TRUE FALSE
## [2,] TRUE FALSE FALSE
## [3,] FALSE FALSE FALSE
1
3
Arguments for directed graphs
I
Two other arguments can be used this way:
I
I
I
curve to curve each edge
lty to create dashed lines (not yet in matrix form)
And finally a few other arguments:
Arguments for directed graphs
input<-matrix(c(
0,1,1,
1,0,1,
0,0,0),3,3,byrow=TRUE)
print(input)
qgraph(input,
asize=10,
arrows=2,
open=TRUE,
curvePivot=TRUE)
3
2
##
[,1] [,2] [,3]
## [1,]
0
1
1
## [2,]
1
0
1
## [3,]
0
0
0
1
Weighted graphs
I
Specify edge weights to make a graph weighted
I
In a weights matrix: simply specify other values than only
zeros and ones
I
An edge weigth of 0 indicates no connection
I
Positive and negative edge weights must be comparable in
strength
The “length” of an edge is defined as the inverse of the
weight.
I
I
I
Stronger connected nodes are closer together
An edge weight of 0 indicates infinite length
Weighted graphs
qgraph(input)
input<-matrix(c(
0,1,2,
0,0,3,
0,0,0),3,3,byrow=TRUE)
print(input)
3
2
##
[,1] [,2] [,3]
## [1,]
0
1
2
## [2,]
0
0
3
## [3,]
0
0
0
1
Layout modes
I
The placement of the nodes is specified with the layout
argument in qgraph()
I
This can be a n by 2 matrix indicating the x and y position
of each node
layout can also be given a character indicating one of the
two default layouts
I
I
I
I
If layout="circular" the nodes are placed in circles
per group (if the groups list is specified)
If layout="spring" the Fruchterman Reingold algorithm
is used for the placement
And a final option is to specify a grid-like layout
Layout matrix
qgraph(input,layout=L)
input <- matrix(1,3,3)
L <- matrix(c(
0,1,
1,1,
0.5,0),
ncol=2,byrow=TRUE)
print(L)
1
2
##
[,1] [,2]
## [1,] 0.0
1
## [2,] 1.0
1
## [3,] 0.5
0
3
Layout matrix
qgraph(input,layout=L)
L <- matrix(c(
0,1,
1,1,
0,0),ncol=2,byrow=TRUE)
print(L)
1
##
[,1] [,2]
## [1,]
0
1
## [2,]
1
1
## [3,]
0
0
3
2
Layout matrix
I
With the layout matrix the actual layout can be specified
I
The scale is not relevant
I
qgraph() returns a list containing everything needed to
make the graph
I
This can be used to force another graph based on the
layout of the first
Q <- qgraph(input)
qgraph(input2,layout=Q$layout)
Grid layout
qgraph(input,layout=L)
input <- matrix(1, 3, 3)
L <- matrix(c(
1,0,2,
0,0,0,
0,3,0),
nrow=3,byrow=TRUE)
print(L)
1
2
##
[,1] [,2] [,3]
## [1,]
1
0
2
## [2,]
0
0
0
## [3,]
0
3
0
3
Grid layout
qgraph(input,layout=L)
input <- matrix(1,3,3)
L <- matrix(c(
1,0,2,
0,0,0,
3,0,0),nrow=3,byrow=TRUE)
print(L)
1
##
[,1] [,2] [,3]
## [1,]
1
0
2
## [2,]
0
0
0
## [3,]
3
0
0
3
2
Fruchterman-Reingold layout
I
layout="spring" uses a force-embedded algorithm
(the Fruchterman-Reingold algorithm)
I
This is an iterative algorithm.
I
The initial layout is a circle
Then in each iteration:
I
I
I
I
Each node is repulsed by all other nodes
Connected nodes are also attracted to each other
The maximum displacement weakens each iteration
I
After this process the layout is rescaled to fit the −1 to 1
xy -plane
I
The unscaled layout is returned as layout.orig
Big 5
Load the big 5 dataset:
data(big5)
str(big5)
##
##
##
##
num [1:500, 1:240] 2 3 4 4 5 2 2 1 4 2 ...
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:240] "N1" "E2" "O3" "A4" ...
Big 5
qgraph(cor(big5),minimum=0.25)
A239C24 N1 E2 O3 A4 C5 N6
O238
E237
N236
C235
E7 O8
A234
A9 C10N11
O233
E232
N231
C230
E12
A229
O13
O228
A14
E227
C15
N226
N16
C225
E17
A224
O18
A19
O223
E222
C20
N221
N21
C220
E22
A219
O23
O218
A24
E217
C25
N216
N26
C215
E27
A214
O28
A29
O213
E212
C30
N31
N211
E32
C210
A209
O33
A34
O208
E207
C35
N206
N36
E37
C205
A204
O38
A39
O203
E202
C40
N201
N41
C200
E42
A199
O43
O198
E197
A44
C45
N196
N46
C195
E47
A194
O48
A49
O193
E192
C50
N191
N51
E52
C190
A189
O53
O188
A54
E187
C55
N186
N56
C185
E57
A184
O58
A59
O183
E182
C60
N181
N61
E62
C180
A179
O63
O178
A64
E177
C65
N176
N66
C175
E67
A174
O68
A69
O173
E172
C70
N171
N71
C170
E72
A169
O73
O168
A74
E167
C75
N166
C165
A164
N76
E77
O78
A79
O163
E162
C80
N161
N81
E82
C160
A159
O83
A84
O158
E157
C85
N156
N86
E87
C155
A154
O88
A89
O153
E152
C90
N151
N91
E92
C150
A149
O93
A94
O148
E147
C95
N146
N96
E97
C145
A144
O98
A99
O143
E142
C100
N101
N141
E102
C140
A139
O103
A104
O138
E137
C105
N136
N106
E107
C135
A134
O108
A109
O133
E132
C110
N131
N111
C130
E112
A129
O113
O128
A114
E127
C115
N126
N116
C125
E117
A124
O118
A119
O123
E122
C120
N121
The groups argument
I
I
The groups indicates which nodes belong together
Nodes belonging together are...
I
I
placed in smaller circles (with circular layout)
colored in the same color (either rainbow or defined with
color)
I
Names in the groups can be used as legend
I
groups can even be used to perform a oneline CFA with
qgraph.cfa()
Either use a factor (a vector with characters) or a list in which
each element is a vector containing the number of nodes that
belong together
The groups argument
# List:
groups <- list(A = c(1,2,3,4,5),
B = c(6,7,8,9,10))
# Factor:
groups <- c("A","A","A","A","A",
"B","B","B","B","B")
# Result:
qgraph(matrix(1,10,10),groups=groups)
10
8
5
1
2
A
B
3
6
4
9
7
Big 5
data(big5groups)
big5graph <- qgraph(cor(big5),minimum=0.25,groups=big5groups)
N236 N1 N6
N231
N11
N226
N16
N221
N21
N216
N26
N31
N211
N206
N36
N201
N41
N196
N46
N191
N51
N186
N56
N181
N61
N176
N66
N171
N71
N166
N76
N161
N81
N156
N151
C24 C5 C10
C235
C15
C230
C20
C225
C25
C220
C30
C215
N91
E237 E2 E7
E232
E12
E227
E17
E222
E22
E217
E27
N146
N96
N101
N141
N136
N106
N131
N126N121N116N111
C35
C210
N86
C200
C60
E187
C185
C65
E182
C180
C70
E177
C75
E87
E152
E92
E97
E147
E102
E142
E137
E107
E132
E112
E127E122E117
A239 A4 A9
A234
A14
A229
A19
A224
A24
A219
A29
O238 O3 O8
O233
O13
O228
O18
O223
O23
O218
O28
A34
A209
O213
A39
A204
A199
A54
A59
O188
A184
A64
O183
A69
O178
A174
A74
A169
A79
A164
A84
A159
A89
A94
A149
A99
A104
A144
A139
A109
A134
A129A124A119A114
O43
O198
O48
O193
A189
A179
O38
O203
A49
A194
O33
O208
A44
A154
E82
E157
C95
C150
C100
C145
C105
C140
C110
C135
C115
C130C125C120
A214
E62
E67
E77
E162
C90
C155
E57
E72
E167
C85
C160
E52
E172
C80
C165
E47
E192
C55
C170
E42
E197
C50
C190
C175
E37
E202
C45
C195
E32
E212
E207
C40
C205
O53
O58
O63
O68
O173
O73
O168
O78
O163
O83
O158
O88
O153
O93
O148
O98
O143
O103
O138
O108
O133
O113
O128O123O118
Neuroticism
Extraversion
Openness
Agreeableness
Conscientiousness
Big 5
qgraph(big5graph,layout="spring")
148
78
190
18
105
172
153
143
238
173
120
111
75
100
33
21
197
60
3
218
53
228
70
213
113
83
40
81
183
165
240
239
108
82
112
88
63
90
220
230
93
23
233
180
201
171
38
123
168
46
200
22
150
203
125
235
98
5
195
50
55
128
73
141
110
202
158
210
215
69
15
51
145
223
8
49
118
95
138
225
28
170
48
229
101
35
207
24
13
85
208
68
160
36
135
25
132
163
57
199
45
175
157
54
140
185
20
103
142
47
133
43
159
119
206
231
76
14
192
9
178
66
137
236
211
189
31
59
12
194
152
156
4
19
89
174
16
61
99
122
62
127
74
92
124
6
71
114
134
177
136
91
121
204
234
126
161
191
106
1
149
27
217
182
41
151
209
44
219
164
187
107
216
146
117
224
181
129
193
84
144
221
222
26
196
102
72
227
155
86
226
39
104
56
130
176
116
Neuroticism
Extraversion
Openness
Agreeableness
Conscientiousness
232
198
10
30
115
205
77
58
188
65
80
167
212
11
147
96
169
37
184
179
237
42
87
17
97
214
7
64
154
94
186
131
32
162
166
79
67
2
52
139
109
34
29
output
qgraph graphs can not be manually rescaled, and hence the
RStudio Export function can not be used to save qgraph
graphs.
For the best result, save graphs in a PDF device!
Export to PDF
# Open a pdf device:
pdf("nameoffile.pdf")
# Plot stuff:
qgraph(1)
# Close pdf device:
dev.off()
## pdf
##
2
(If you get faulty output, make sure to run dev.off() enough
times untill R returns Null Device)
Export to PNG
# Open a pdf device:
png("nameoffile.png")
# Plot stuff:
qgraph(1)
# Close pdf device:
dev.off()
## pdf
##
2
(If you get faulty output, make sure to run dev.off() enough
times untill R returns Null Device)
Important qgraph arguments
minimum Omits edge weights with absolute values under
this argument
maximum Sets the strongest edge to scale to
cut Splits scaling of color and width
vsize Sets the size of nodes
esize Sets the size of edges
asize Sets the size of arrows
filetype Type of file to save the plot to
filename Name of the file to save the plot to
Contribute to qgraph
The devellopmental version of qgraph can be found on GitHub
(https://github.com/SachaEpskamp/qgraph) and can be
installed using devtools
library("devtools")
install_github("qgraph","sachaepskamp")
If you have any ideas on concepts to implement in qgraph or
encounter any bugs please post them on GitHub!
© Copyright 2026 Paperzz