4  Visualization

MetaNet supports basic R plot and provides some interfaces for other software (Gephi, Cytoscape, ggplot2, networkD3) to visualize, while there are also a lot of layout methods for better display.

4.1 Basic plot

Set attributes

As we mentioned before, there are some internal attributes have been set when building network, which are related to the network visualization (Table 3.1). So we can use c_net_set() to custom these attributes fitting to our research needs.

Give the network various annotate tables and determine which columns use to set, we can give the columns name (one or more) to vertex_group, vertex_class, vertex_size, edge_type, edge_class, edge_width.

And the colors, linetypes, shapes and legends will be assigned automatically, just use plot() to get the basic metanet figure. For more details to customize the plot, refer to Table 4.1.

data("multi_test", package = "MetaNet")
data("c_net", package = "MetaNet")
# build a multi-network
multi1 <- multi_net_build(list(Microbiome = micro, Metabolome = metab, Transcriptome = transc))
# v_group is default, three different table

plot(multi1)

# set vertex_class
multi1_with_anno <- c_net_set(multi1, micro_g, metab_g, transc_g, vertex_class = c("Phylum", "kingdom", "type"))
# set vertex_size
multi1_with_anno <- c_net_set(multi1_with_anno,
  data.frame("Abundance1" = colSums(micro)),
  data.frame("Abundance2" = colSums(metab)),
  data.frame("Abundance3" = colSums(transc)),
  vertex_size = paste0("Abundance", 1:3)
)

plot(multi1_with_anno)
Figure 4.1: Basic network plot
Figure 4.2: Basic network plot

Plot setting

If you want to custom the network plot flexibility, use the c_net_plot() which contains many flexible arguments. The arguments of c_net_plot() are listed below:

Table 4.1: Description of c_net_plot() arguments.
Arguments Description
coors 1. cooridnates dataframe, 2. layout function (e.g. as_star(), as_tree(), in_circle(), nicely()... see help(c_net_lay))
vertex.color color of nodes, receive vector (1. length same to number of nodes; 2. length same to numbers of v_class; 3. named verctor like c(A="red",B="blue"))
vertex. shape shape of nodes, receive vector (1. length same to number of nodes; 2. length same to numbers of v_group; 3. named verctor like c(v_group1="circle",B="square"))shape list: none, circle, square, csquare, rectangle, crectangle, vrectangle, pie, raster, or sphere
vertex.size size of nodes, receive numerical vector (length same to number of nodes)please use mmscale to control vertex.size, don't be too large.
vertex_size_range the vertex size range, e.g. c(1,10)
labels_num show how many labels,>1 indicates number,
vertex.label the label of nodes, NA indicates no label
vertex.label.family label font family
vertex.label.font label font, 1 plain, 2 bold, 3 italic, 4 bold italic, 5 symbol
vertex.label.cex label size
vertex.label.dist distance from label to nodes
vertex.label.degree 0:right, pi: left, pi/2:below, -pi/2:above
vertex.frame.color color of nodes frame
plot_module use module as the v_class
mark_module logical, mark the modules?
mark_color mark color
mark_alpha mark fill alpha, default 0.3
module_label show module label?
module_label_cex module label cex
module_label_color module label color
module_label_just module label just, default c(0.5,0.5)
edge.color color of edges, receive vector (1. length same to number of edges; 2. length same to numbers of e_type; 3. named verctor like c(A="red",B="blue"))
edge.width width of edge, receive numerical vector (length same to number of edges)please use mmscale to control vertex.size, don't be too large.
edge_width_range the edge width range, e.g. c(1,10)
edge.lty linetype of edge, receive vector (1. length same to number of edges; 2. length same to numbers of e_class; 3. named verctor like c(A="red",B="blue"))
edge.arrow.size arrow size for directed network
edge.arrow.width arrow width for directed network
arrow.mode arrow mode, 0 no arrow, 1 back, 2 forward, 3 both
edge.label the label of edges, NA indicates no label
edge.label.family label font family
edge.label.font label font, 1 plain, 2 bold, 3 italic, 4 bold italic, 5 symbol
edge.label.cex label size
edge.label.x label x-axis
edge.label.y label y-axis
edge.label.color label color
edge.curved The curvature of the body, on a scale of 0-1, FALSE means 0, TRUE means 0.5
legend show any legend? FALSE means close all legends
legend_cex character expansion factor relative to current par('cex'), default: 1
legend_position legend_position, default: c(left_leg_x=-1.9,left_leg_y=1,right_leg_x=1.2,right_leg_y=1)
legend_number add numbers in legend? (v_class number, e_type number...)
lty_legend, lty_legend_title, lty_legend_order show lty_legend? and the title, the oreder of legend receives a vector
size_legend, size_legend_tiltle show size_legend? and the title
edge_legend, edge_legend_title, edge_legend_order show edge_legend? and the title, the order of legend receives a vector
width_legend, width_legend_title show width_legend? and the title
color_legend, color_legend_order show col_legend? and the title, the order of legend receives a vector
group_legend_title, group_legend_order the title of group, the order of legend receives a vector
margin margin, a vector whose length =4
rescale scale the coors to [-1,1], default T
asp y/x ratio
frame if T, add frame
main the main title of graph
sub subtitle
xlab x-axis label
ylab y-axis label
seed random seed, default:1234, make sure each plot is the same
params_list a list of parameters, e.g. list(edge_legend = TRUE, lty_legend = FALSE), when the parameter is duplicated, the format argument will be used rather than the argument in params_list

For example, we can use c_net_plot() to plot the network with annotation and set the color, size, width, legend, etc.

c_net_plot(multi1_with_anno,
  labels_num = 5, vertex.color = get_cols(11, "col1"), vertex_size_range = c(3, 10), vertex.label.color = "red",
  edge_width_range = c(0.5, 3), edge.color = c("orange", "green4"), edge.curved = 0.5,
  legend = T, legend_number = T, group_legend_order = c("Microbiome", "Metabolome", "Transcriptome"),
  group_legend_title = c("Phylum", "Metabolome", "Transcriptome"),
  edge_legend_title = "Correlation", edge_legend_order = c("positive", "negative"),
  size_legend = T, size_legend_title = "Abundance",
  width_legend = T, width_legend_title = "abs(r)",
  lty_legend = T, lty_legend_title = "Omics relationship"
)
Figure 4.3: Custom network plot

params_list is a special argument in c_net_plot(), it is a list contains parameters, it is very convenient to use it to plot a series of network with same attributes.

node_colors <- setNames(get_cols(9, "col1"), unique(V(multi1_with_anno)$v_class))

params_list <- list(
  labels_num = 5,
  vertex.color = node_colors, vertex_size_range = c(3, 10), vertex.label.color = "red",
  edge_width_range = c(0.5, 3), edge.color = c("orange", "green4"), edge.curved = 0.5,
  legend = T, legend_number = T, group_legend_order = c("Microbiome", "Metabolome", "Transcriptome"),
  group_legend_title = c("Phylum", "Metabolome", "Transcriptome"),
  edge_legend_title = "Correlation", edge_legend_order = c("positive", "negative"),
  size_legend = T, size_legend_title = "Abundance",
  width_legend = T, width_legend_title = "abs(r)",
  lty_legend = T, lty_legend_title = "Omics relationship"
)

c_net_plot(multi1_with_anno, params_list = params_list)

# build another multi-network
multi1_with_anno2 <- c_net_filter(multi1_with_anno, v_group %in% c("Microbiome", "Metabolome")) %>%
  c_net_filter(., e_class == "intra", mode = "e")
c_net_plot(multi1_with_anno2, params_list = params_list)
(a) plot1
(b) plot2
Figure 4.4: Plot a series of network using params_list

4.2 Layout

Layout is an important part of network visualization, a good layout will present information clearly.

So, in MetaNet, we always use a coors object to store the coordinates of a layout.

The coors is a list contains two elements: coors$coors and coors$curved. coors$coors is a three-columns data.frame contains “name”, “X”, “Y”. coors$curved is a three-columns data.frame contains “from”, “to”, “curved” or NULL.

Basic layout

Use c_net_layout() to get coordinates with specific layout methods.

c_net_layout(co_net2, method = in_circle()) -> coors
c_net_plot(co_net2, coors)

The method can be one of

  1. as_line(), as_arc(), as_polygon(), as_polyarc(), as_polycircle(), as_circle_tree().

  2. layouts in igraph: in_circle(), nicely(), on_grid(), on_sphere(), randomly(), with_dh(), with_fr(), with_gem(), with_graphopt(), with_kk(), with_lgl(), with_mds(), see igraph::layout_().

  3. layouts in ggraph: a character, “auto”, “backbone”, “centrality”, “circlepack”, “dendrogram”, “eigen”, “focus”, “hive”, “igraph”, “linear”, “manual”, “matrix”, “partition”, “pmds”, “stress”, “treemap”, “unrooted”. see ggraph::create_layout().

Code
go <- erdos.renyi.game(30, 0.25)
# get a metanet
go <- c_net_update(go)

layout_methods <- list(
  as_star(), as_tree(), in_circle(), nicely(),
  on_grid(), on_sphere(), randomly(), with_dh(),
  with_fr(), with_gem(), with_graphopt(), with_kk(),
  with_lgl(), with_mds(), as_line(), as_arc(),
  as_polygon(), as_polyarc(), as_polycircle(), as_circle_tree()
)
names(layout_methods) <- c(
  "as_star ", "as_tree ", "in_circle ", "nicely ",
  "on_grid ", "on_sphere ", "randomly ", "with_dh ",
  "with_fr ", "with_gem ", "with_graphopt ", "with_kk ",
  "with_lgl ", "with_mds", "as_line", "as_arc",
  "as_polygon", "as_polyarc", "as_polycircle", "as_circle_tree"
)

par(mfrow = c(5, 4))
for (i in names(layout_methods)) {
  plot(go, layout_methods[[i]], legend = F, main = i, labels_num = 0)
}
Figure 4.5: Layout methods for c_net_layout()

And for each method, you can add some arguments in it:

# get a metanet
go <- erdos.renyi.game(30, 0.25)
go <- c_net_update(go)

plot(go, coors = with_fr())
plot(go, coors = with_fr(niter = 99, grid = "nogrid"))

The as_polygon() is interesting: it can draw a network in a polygon shape, and you can change the edge numbers of the polygon.

Figure 4.6: Layout of as_polygon() in c_net_layout

Group layout

Beside the c_net_layout(), we provide an advanced layout method for a network with group variable: g_layout(). It is easy to use g_layout() to control each group position and layout of each group.

Note

g_layout() is a very useful function to layout a network with group variable when we have a multi-omics network (Chapter 7) or module network (Section 5.4).

  • First, assign a group variable.
  • Give a layout1 for group position, one of 1.a dataframe or matrix: rowname is group, two columns are X and Y 2.function: layout method for c_net_layout() default: in_circle()
  • Adjust the zoom1 of layout1.
  • Give a layout2 (layout method for c_net_layout()) for each group layout, or use a list contains functions match each group.
  • Adjust the zoom2 of layout2, you can use a vector to adjust each group zoom.
  • use show_big_layout = T to see the layout1 distribution.
par(mfrow = c(2, 1))
# set circle layout for each group
g_layout(multi1_with_anno,
  group = "v_group", layout1 = in_circle(),
  zoom1 = 10, layout2 = in_circle(), zoom2 = 5
) -> g_coors
plot(multi1_with_anno, coors = g_coors)
# set different layout for each group
g_layout(multi1_with_anno,
  group = "v_group", layout1 = in_circle(), zoom1 = 10,
  layout2 = list(in_circle(), with_fr(), as_polygon()), zoom2 = 3:5
) -> g_coors
plot(multi1_with_anno, coors = g_coors)
Figure 4.7: Simple usage of g_layout()

As layout1 also receive a matrix or data.frame, so we can use the group skeleton of network to adjust the layout1.

data("c_net", package = "MetaNet")
g_layout(co_net,
  group = "v_class", layout1 = in_circle(), zoom1 = 10,
  layout2 = in_circle(), zoom2 = c(1, 5, 2, 1, 3, 7)
) -> g_coors
plot(co_net, coors = g_coors)

# firstly get the skeleton plot
get_group_skeleton(co_net, "v_class") %>% clean_igraph() -> s_net

# then use tkplot to do manual adjustment.
x <- igraph::tkplot(s_net)
# Here: Move nodes within the tkplot window to a layout you like!
da <- igraph::tkplot.getcoords(x)
# close the window
igraph::tkplot.close(x)
# pass the `da` to layout1
g_layout(co_net,
  group = "v_class", layout1 = da, zoom1 = 20,
  layout2 = in_circle(), zoom2 = c(1, 4, 2, 1, 3, 5)
) -> g_coors
plot(co_net, coors = g_coors)
Figure 4.8: Use tkplot to adjust big layout.
Figure 4.9: Use tkplot to adjust big layout.

g_layout() provides a high degree of customization, you can adjust the layout according to different needs.

Besides, there are also some good default group layout methods: - g_layout_circlepack() - g_layout_treemap() - g_layout_backbone() - g_layout_stress() - g_layout_polyarc() - g_layout_polygon() - g_layout_polycircle()

E(co_net)$color <- rep("grey", length(E(co_net)))
plot(co_net,
  coors = g_layout_circlepack(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_circlepack"
)

plot(co_net,
  coors = g_layout_treemap(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_treemap"
)

plot(co_net,
  coors = g_layout_backbone(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_backbone"
)

plot(co_net,
  coors = g_layout_stress(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_stress"
)

plot(co_net,
  coors = g_layout_polyarc(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_polyarc"
)

plot(co_net,
  coors = g_layout_polygon(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_polygon"
)

plot(co_net,
  coors = g_layout_polycircle(co_net, group = "v_class"),
  legend = F, labels_num = 0, main = "g_layout_polycircle"
)
Figure 4.10: Usage of g_layout_*()
Figure 4.11: Usage of g_layout_*()
Figure 4.12: Usage of g_layout_*()
Figure 4.13: Usage of g_layout_*()
Figure 4.14: Usage of g_layout_*()
Figure 4.15: Usage of g_layout_*()
Figure 4.16: Usage of g_layout_*()

4.3 Other styles

It is also easy to transfer the basic plot to other styles, like ggplot2, Gephi, Cytoscape, and NetworkD3.

ggplot2

If you are more familiar with ggplot2, use the function as.ggig() transfer the basic R plot to ggplot2 style, so that you can use some convenient function like labs(), theme(), ggsave(), and cowplot::plot_grid() to make better figure.

as.ggig(multi1_with_anno) -> ggig
plot(ggig)
Figure 4.17: Plot a network in ggplot2 style

Gephi

If you are dealing with some big dataset, We recommend to use Gephi to make layout. We provide a interface to Gephi by graphml format file, you can use the algorithm in Gephi then export a graphml file.

plot(co_net)
c_net_save(co_net, filename = "test", format = "graphml")
# then input test.graphml to Gephi and do a layout

# and export a graphml file from Gephi: test2.graphml, So you can re-draw it in MetaNet
input_gephi("test2.graphml") -> gephi

c_net_plot(co_net, coors = gephi$coors, legend_number = T, group_legend_title = "Phylum")

Cytoscape

Cytoscape is also a pretty software for network visualization which contains lots of plugins.

Use the “data.frame” format to transfer network.

c_net_save(co_net, filename = "test", format = "data.frame")
# then input test_nodes.csv and test_edge.csv to Cytoscape.

NetworkD3

NetworkD3 can produce interactive network plot based on JavaScript, the output object is a htmlwidgets which are suitable for website.

netD3plot(multi1_with_anno)
Figure 4.18: Plot a network in NetworkD3 style

4.4 Intersting plot

There are some interesting plot in MetaNet, like venn_net, twocol_edgelist, df2net_tree, and olympic_rings_net.

  • Venn plot
data(otutab, package = "pcutils")
tab <- otutab[400:485, 1:3]
venn_net(tab) -> v_net
plot(v_net)
Figure 4.19: Venn plot in network style
  • Two columns edge list
twocol <- data.frame(
  "col1" = sample(letters, 30, replace = TRUE),
  "col2" = sample(c("A", "B"), 30, replace = TRUE)
)
twocol_net <- twocol_edgelist(twocol)
c_net_plot(twocol_net, g_layout_polygon(twocol_net))
Figure 4.20: Two columns edge list plot
  • Dataframe to network tree
data("otutab", package = "pcutils")
cbind(taxonomy, num = rowSums(otutab))[1:20, ] -> test
df2net_tree(test) -> ttt

par(mfrow = c(1, 2))
plot(ttt, edge_legend = F, main = "Tree network", legend_position = c(left_leg_x = -1.3))
plot(ttt, coors = as_circle_tree(), legend = F, main = "Circle tree network")
Figure 4.21: Dataframe to network tree plot
  • Olympic rings plot
olympic_rings_net()
Figure 4.22: Olympic rings plot