Learn R Programming

qgraph (version 1.3.1)

qgraph: qgraph

Description

This is the main function of qgraph which automatically creates an appropriate network and sends it to the plotting method.

Usage

qgraph( input, ... )

Arguments

input
Can be either a weights matrix or an edgelist. Can also be an object of class "sem" (sem), "mod" (sem), "lavaan" (lavaan), "principal" (psych), "loadings" (stats), "factanal" (stats), "graphNEL" (Rgraphviz), "pcAlgo" (pcalg), "huge" (huge),
...
Any additional arguments described below. Also a list with class "qgraph" can be added that contains any of these arguments (this is returned invisibly by the function)

Value

  • qgraph returns (invisibly) a 'qgraph' object containing:
  • EdgelistA list containing for each edge the node of origin, node of destination, weight en wether the edge is directed and bidirectional.
  • ArgumentsA list containing the arguments used in the qgraph call.
  • plotOptionsA list containing numerous options used in the plotting method.
  • graphAttributesA list containing numerous attributes for nodes, edges and the entire graph
  • layoutA matrix containing the layout used in the plot
  • layout.origA matrix containing the original (unscaled) layout.

encoding

UTF8

Using qgraph to plot graphs

The first argument of qgraph(), 'input', is the input. This can be a number of objects but is mainly either a weights matrix or an edgelist. Here we will assume a graph is made of n nodes connected by m edges. qgraph is mainly aimed at visualizing (statistical) relationships between variables as weighted edges. In these edge weights a zero indicates no connection and negative values are comparable in strength to positive values. Many (standardized) statistics follow these rules, the most important example being correlations. In the special case where all edge weights are either 0 or 1 the weights matrix is interpreted as an adjacency matrix and an unweighted graph is made.

a weights matrix is a square n by n matrix in which each row and column represents a node. The element at row i and column j indicates the connection from node i to node j. If the weights matrix is symmetrical an undirected graph is made and if the matrix is asymmetrical a directed graph is made.

Alternatively an edgelist can be used. This is a m by 2 matrix (not a list!) in which each row indicates an edge. The first column indicates the number of the start of the edge and the second column indicates the number of the end of the edge. The number of each node is a unique integer between 1 and n. The total number of nodes will be estimated by taking the highest value of the edgelist. If this is incorrect (there are nodes with no edges beyond the ones already specified) the 'nNodes' argument can be used. If an integer between 1 and n is missing in the edgelist it is assumed to be a node with no edges. To create a weighted graph edge weights can be added as a third column in the edgelist. By default using an edgelist creates a directed graph, but this can be set with the 'directed' argument.

Interpreting graphs

In weighted graphs green edges indicate positive weights and red edges indicate negative weights. The color saturation and the width of the edges corresponds to the absolute weight and scale relative to the strongest weight in the graph. It is possible to set this strongest edge by using the 'maximum' argument. When 'maximum' is set to a value above any absolute weight in the graph that value is considered the strongest edge (this must be done to compare different graphs; a good value for correlations is 1). Edges with an absolute value under the 'minimum' argument are omitted (useful to keep filesizes from inflating in very large graphs).

In larger graphs the above edge settings can become hard to interpret. With the 'cut' argument a cutoff value can be set which splits scaling of color and width. This makes the graphs much easier to interpret as you can see important edges and general trends in the same picture. Edges with absolute weights under the cutoff score will have the smallest width and become more colorful as they approach the cutoff score, and edges with absolute weights over the cutoff score will be full red or green and become wider the stronger they are.

Specifying the layout

The placement of the nodes (i.e. the layout) is specified with the 'layout' argument. It can be manually specified by entering a matrix for this argument. The matrix must have a row for each node and two columns indicating its X and Y coordinate respectively. qgraph plots the nodes on a (-1:1)(-1:1) plane, and the given coordinates will be rescaled to fit this plane unless 'rescale' is FALSE (not recommended). Another option to manually specify the layout is by entering a matrix with more then two columns. This matrix must then consist of zeroes and a number (the order in the weights matrix) for each node indicating it's place. For example:

0 0 2 0 0

1 0 3 0 4

will place node 2 at the top in the center, node 1 at the bottom left corner, node 3 at the bottom in the center and node 4 at the bottom right corner. It is recommended however that one of the integrated layouts is used. 'layout' can be given a character as argument to accomplish that. layout="circular" will simply place all nodes in a circle if the groups argument is not used and in separate circles per group if the groups argument is used (see next section).

The circular layout is convenient to see how well the data conforms to a model, but to show how the data clusters another layout is more appropriate. By specifying layout="spring" the Fruchterman-reingold algorithm (Fruchterman & Reingold, 1991), which has been ported from the SNA package (Butts, 2010), can be used to create a force-directed layout. In principle, what this function does is that each node (connected and unconnected) repulse each other, and connected nodes also attract each other. Then after a number of iterations (500 by default) in which the maximum displacement of each node becomes smaller a layout is achieved in which the distance between nodes correspond very well to the absolute edge weight between those nodes.

A solution to use this function for weighted graphs has been taken from the igraph package (Csardi G & Nepusz T, 2006) in which the same function was ported from the SNA package. New in qgraph are the option to include constraints on the nodes by fixing a coordinate for nodes or reducing the maximum allowed displacement per node. This can be done with the 'layout.par' argument. For more information see qgraph.layout.fruchtermanreingold.

By default, 'layout' is set to "spring" for unweighted and directed graphs and "circular" otherwise.

Grouping nodes

Grouping nodes (e.g., according to a measurement model) can be specified with the 'groups' argument. This can be a factor or a list in which each element is a vector containing the numbers of nodes that belong together (numbers are taken from the order in the weights matrix). All numbers must be included. If a groups list is specified the "groups" layout can be used to place these nodes together, the nodes in each group will be given a color, and a legend can be plotted (by setting 'legend' to TRUE). The colors will be taken from the 'color' argument, or be generated with the rainbow function.

Output

By default qgraph will plot the graph in a new R window. However the graphs are optimized to be plotted in a PDF file. To easily create a pdf file set the 'filetype' argument to "pdf". 'filename' can be used to specify the filename and folder to output in. 'height' and 'width' can be used to specify the height and width of the image in inches. By default a new R window is opened if the current device is the NULL-device, otherwise the current device is used (note that when doing this 'width' and 'height' still optimize the image for those widths and heights, even though the output screen size isn't affected, this is especially important for directed graphs!).

Furthermore filetype can also be set to numerous other values. Alternatively any output device in R can be used by simply opening the device before calling qgraph and closing it with dev.off() after calling qgraph.

The graphs can also be outputted in an SVG file using the RSVGTipsDevice package (Plate, 2009). An SVG image can be opened in most browsers (firefox and chrome are recommended), and can be used to display tooltips. Each node can be given a tooltip with the 'tooltips' argument. The function qgraph.svg can be used to make a battery of svg pictures with hyperlinks to each other, working like a navigation menu (note, RSVGTipsDevice is a 32-bit only package, so SVG functionality is not available in 64bit versions of R).

Finally, the filetype 'tex' can be used. This uses the tikzDevice package to create a LaTeX file that can then be compiled in your LaTeX compiler to create a pdf file. The main benefit of this over plotting directly in a pdf file is that tooltips can be added which can be viewed in several PDF document readers (Adobe Reader is recommended for the best result).

IMPORTANT NOTE: graphs made in qgraph must be exported programatically using device functions such as pdf() and png(). Manually resizing a graph and using export functions such as the one built into RStudio will give UNSTABLE RESULTS.

Manual specification of color and width

In qgraph the widths and colors of each edge can also be manually controlled. To directly specify the width of each edge set the 'mode'' argument to "direct". This will then use the absolute edge weights as the width of each edge (negative values can still be used to make red edges). To manually set the color of each edge, set the 'edge.color' argument to a matrix with colors for each edge (when using a weights matrix) or a vector with a color for each edge (when using an edgelist).

Replotting graphs and reusing layouts

If the result of qgraph is stored, such as Graph <- qgraph(...), the plot can be recreated in two ways. qgraph(Graph, ...)) reruns qgraph with the same arguments used in the origina call except those restated in the dots. For example qgraph(Graph, shape = "square") will recreate the same plot but now use square nodes instead of circular. plot(Graph) will NOT rerun qgraph but simply plot the qgraph object. This means that now specific graph attributes can be changed before plotting.

More specific, qgraph(Graph) will base the new plot only on the Arguments element of the qgraph object and plot(qgraph) will base the new plot on the graphAttributes and plotOptions elements of the qgraph object.

To reuse a layout, use the layout element. e.g., to plot a new graph with the same layout use qgraph(..., layout = Graph$layout)

Additional information

By default, edges will be straight between two nodes unless there are two edges between two nodes. To overwrite this behavior the 'bidirectional' argument can be set to TRUE, which will turn two edges between two nodes into one bidirectional edge. 'bidirectional' can also be a vector with TRUE or FALSE for each edge.

To specify the strength of the curve the argument 'curve' can be used (but only in directional graphs). 'curve' must be given a numerical value that represent an offset from the middle of the straight edge through where the curved edge must be drawn. 0 indicates no curve, and any other value indicates a curve of that strength. A value of 0.3 is recommended for nice curves. This can be either one number or a vector with the curve of each edge.

Nodes and edges can be given labels with the 'labels' and the 'edge.labels' arguments. 'labels' can be set to FALSE to omit labels, TRUE (default) to set labels equal to the node number (order in the weights matrix) or it can be a vector with the label for each node. Edge labels can also be set to FALSE to be omitted (default). If 'edge.labels' is TRUE then the weight of each label is printed. Finally, 'edge.labels' can also be a vector with the label for each edge. If a label (both for edges and nodes) contain an asterisk then the asterisk is omitted and that label is printed in the symbol font (useful to print Greek letters).

A final two things to try: the 'scores' argument can be given a vector with the scores of a person on each variable, which will then be shown using colors of the nodes, And the 'bg' argument can be used to change the background of the graph to another color, or use bg=TRUE for a special background (do set transparency=TRUE when using background colors other then white).

Debugging

If this function crashes for any reason with the filetype argument specified, run:

dev.off()

To shut down the output device!

Details

Because of the amount of arguments the usage of the qgraph function has been reduced by using the ... method for clarity. This does mean that arguments need to be specified by using their exact name. For instance, to specify color="red" you can not use col="red".

Important to note is that qgraph needs to compute in many graphs where the border of nodes are in the plotting area. If the graph is manually rescaled (such as through the "zoom" option in RStudio) the plotting area is changed. This means that the computed location of the border of nodes is no longer valid if the nodes are to remain perfectly square or circular. To overcome this, the usePCH argument can be used. If this argument is set to FALSE nodes will be plotted as polygons meaning they will rescale with rescaling the graph (circles can become ovals) and not have perfect resolution in PDF files. If usePCH is set to TRUE a default plotting symbol is used meaning the graph can not be rescaled but the node will look good in PDF. By defaut, qgraph sets usePCH to TRUE if it detects the graph is stored in a file.

While the usePCH argument makes graphs rescalable it is not a perfect solution. It is highly recommended to NOT RESCALE PLOTTING AREAS when using qgraph, or to rerun qgraph after the plotting area is rescaled. This means using save graph option fro RStudio shoud be avoided in favor of the filetype argument in qgraph

References

Carter T. Butts (2010). sna: Tools for Social Network Analysis. R package version 2.2-0. http://CRAN.R-project.org/package=sna

Csardi G, Nepusz T (2006). The igraph software package for complex network research, InterJournal, Complex Systems 1695. http://igraph.sf.net

Sacha Epskamp, Angelique O. J. Cramer, Lourens J. Waldorp, Verena D. Schmittmann, Denny Borsboom (2012). qgraph: Network Visualizations of Relationships in Psychometric Data. Journal of Statistical Software, 48(4), 1-18. URL http://www.jstatsoft.org/v48/i04/.

Jerome Friedman, Trevor Hastie and Rob Tibshirani (2011). glasso: Graphical lasso-estimation of Gaussian graphical models. R package version 1.7. http://CRAN.R-project.org/package=glasso

Bernd Klaus and Korbinian Strimmer. (2014). fdrtool: Estimation of (Local) False Discovery Rates and Higher Criticism. R package version 1.2.12. http://CRAN.R-project.org/package=

Fruchterman, T. & Reingold, E. (1991). Graph drawing by force-directed placement. Software - Pract. Exp. 21, 1129-1164.

N. Kraemer, J. Schaefer. A.-L. Boulesteix (2009). Regularized Estimation of Large-Scale Gene Regulatory Networks using Gaussian Graphical Models BMC Bioinformatics 10:384

Plate, T. and based on RSvgDevice by T Jake Luciani (2009). RSVGTipsDevice: An R SVG graphics device with dynamic tips and hyperlinks. R package version 1.0-1.

Revelle, W. (2014) psych: Procedures for Personality and Psychological Research, Northwestern University, Evanston, Illinois, USA, http://CRAN.R-project.org/package=psych Version = 1.4.4.

See Also

cor_auto qgraph.animate qgraph.efa qgraph.pca qgraph.loadings

Examples

Run this code
### Correlations ###
# Load big5 dataset:
data(big5)
data(big5groups)

# Compute correlation matrix:
big5_cors <- cor_auto(big5, detectOrdinal = FALSE)

# Correlations:
big5Graph <- qgraph(cor(big5),minimum=0.25,groups=big5groups,
            legend=TRUE,borders=FALSE, title = "Big 5 correlations")


  # Same graph with spring layout:
  qgraph(big5Graph,layout="spring")
  
  # Same graph with different color scheme:
  qgraph(big5Graph,posCol="blue",negCol="purple")
 
  ### Network analysis ###
  ### Using bfi dataset from psych ###
  library("psych")
  data(bfi)
  
  # Compute correlations:
  CorMat <- cor_auto(bfi[,1:25])
  
  # Compute graph with tuning = 0 (BIC):
  BICgraph <- qgraph(CorMat, graph = "glasso", sampleSize = nrow(bfi),
            tuning = 0, layout = "spring", title = "BIC", details = TRUE)
  
  # Compute graph with tuning = 0.5 (EBIC)
  EBICgraph <- qgraph(CorMat, graph = "glasso", sampleSize = nrow(bfi),
            tuning = 0.5, layout = "spring", title = "BIC", details = TRUE)
  
  # Compare centrality and clustering:
  centralityPlot(list(BIC = BICgraph, EBIC = EBICgraph))
  clusteringPlot(list(BIC = BICgraph, EBIC = EBICgraph))

  # Compute centrality and clustering:
  centrality_auto(BICgraph)
  clustcoef_auto(BICgraph)
  
  ### Directed unweighted graphs ###
  set.seed(1)
  adj=matrix(sample(0:1,10^2,TRUE,prob=c(0.8,0.2)),nrow=10,ncol=10)
  qgraph(adj)
  title("Unweighted and directed graphs",line=2.5)
  
  # Save plot to nonsquare pdf file:
  qgraph(adj,filetype='pdf',height=5,width=10)
  
  #### EXAMPLES FOR EDGES UNDER DIFFERENT ARGUMENTS ###
  # Create edgelist:
  dat.3 <- matrix(c(1:15*2-1,1:15*2),,2)
  dat.3 <- cbind(dat.3,round(seq(-0.7,0.7,length=15),1))
  
  # Create grid layout:
  L.3 <- matrix(1:30,nrow=2)
  
  # Different esize:
  qgraph(dat.3,layout=L.3,directed=FALSE,edge.labels=TRUE,esize=14)
  
  # Different esize, strongest edges omitted (note how 0.4 edge is now 
  # just as wide as 0.7 edge in previous graph):
  qgraph(dat.3[-c(1:3,13:15),],layout=L.3,nNodes=30,directed=FALSE,
         edge.labels=TRUE,esize=14)
  
  # Different esize, with maximum:
  qgraph(dat.3,layout=L.3,directed=FALSE,edge.labels=TRUE,esize=14,maximum=1)
  title("maximum=1",line=2.5)
  
  qgraph(dat.3[-c(1:3,13:15),],layout=L.3,nNodes=30,directed=FALSE,edge.labels=TRUE,
         esize=14,maximum=1)
  title("maximum=1",line=2.5)
  
  # Different minimum
  qgraph(dat.3,layout=L.3,directed=FALSE,edge.labels=TRUE,esize=14,minimum=0.1)
  title("minimum=0.1",line=2.5)
  
  # With cutoff score:
  qgraph(dat.3,layout=L.3,directed=FALSE,edge.labels=TRUE,esize=14,cut=0.4)
  title("cut=0.4",line=2.5)
  
  # With details:
  qgraph(dat.3,layout=L.3,directed=FALSE,edge.labels=TRUE,esize=14,minimum=0.1,
         maximum=1,cut=0.4,details=TRUE)
  title("details=TRUE",line=2.5)
  
  
  # Trivial example of manually specifying edge color and widths:
  E <- as.matrix(data.frame(from=rep(1:3,each=3),to=rep(1:3,3),width=1:9))
  qgraph(E,mode="direct",edge.color=rainbow(9))
  
  
  ### Input based on other R objects ###
  
  ## Exploratory factor analysis:
  big5efa <- factanal(big5,factors=5,rotation="promax",scores="regression")
  qgraph(big5efa,groups=big5groups,layout="circle",minimum=0.2,
         cut=0.4,vsize=c(1.5,10),borders=FALSE,vTrans=200,title="Big 5 EFA")
  
  ## Principal component analysis:
  library("psych")
  big5pca <- principal(cor(big5),5,rotate="promax")
  qgraph(big5pca,groups=big5groups,layout="circle",rotation="promax",minimum=0.2,
         cut=0.4,vsize=c(1.5,10),borders=FALSE,vTrans=200,title="Big 5 PCA")
  
  ## pcalg
  # Example from pcalg vignette:
  library("pcalg")
  data(gmI)
  suffStat <- list(C = cor(gmI$x), n = nrow(gmI$x))
  pc.fit <- pc(suffStat, indepTest=gaussCItest,
               p = ncol(gmI$x), alpha = 0.01)
  
  qgraph(pc.fit)
  
  ## glasso:
  # Using bfi dataset from psych:
  library("psych")
  data(bfi)
  cor_bfi <- cor_auto(bfi[,1:25])
  
  # Run qgraph:
  library("glasso")
  bfi_glasso <- glasso(cor_bfi, 0.1)
  
  # Plot:
  qgraph(bfi_glasso, layout = "spring")
  
  
  ## Huge (glasso):
  library("huge")
  bfi_huge <- huge(huge.npn(bfi[,1:25]), method="glasso")
  
  # Auto select optimal and plot:
  qgraph(bfi_huge, layout = "spring")
  
  # Manual select and plot:
  sel <- huge.select(bfi_huge)
  qgraph(sel, layout = "spring")

Run the code above in your browser using DataLab