Skip to content

Commit

Permalink
fixed some ggraph issues and reorganized code.
Browse files Browse the repository at this point in the history
  • Loading branch information
mhahsler committed Aug 2, 2021
1 parent 81500ea commit 60c8e40
Show file tree
Hide file tree
Showing 18 changed files with 610 additions and 475 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Imports: graphics,
Suggests: datasets,
graph,
Rgraphviz,
tidygraph,
shiny,
shinythemes,
htmlwidgets
Expand Down
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import("arules")
import("grid")
import("ggplot2")
#import("ggraph")
import("tibble")
import("tidyr")
# NOTE: dplyr has many NAMESPACE conflicts with arules so we use ::
Expand All @@ -10,6 +11,11 @@ importFrom("graphics", "par", "mtext", "text", "axis", "box")
importFrom("stats", "median")
importFrom("methods", "is", "as", "new")

# Otherwise we get: object 'guide_edge_colourbar' of mode 'function' was not found
# Note: has also an alias in man page plot
importFrom("ggraph", "guide_edge_colourbar")
export("guide_edge_colourbar")

importFrom("graphics", "plot")
S3method(plot, rules)
S3method(plot, itemsets)
Expand Down
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
* plot method "grouped matrix" gained parameter grouped to pass on a grouped matrix.
* associations2igraph gained parameter associationsAsNodes.
* plot method graph with engine vizNetwork can now display itemsets.
* plot gained parameter limit to print only the top limit rules.
* plot method graph with ggraph (ggplot2) gained parameters asEdges = TRUE to represent associations as edges instead of nodes.

## Changes
* we use now a better check for installed suggested packages.
* method graph uses not ggraph2.
* method graph uses not ggraph.

# arulesViz 1.5-0 (05/21/2021)

Expand Down
76 changes: 0 additions & 76 deletions R/ggplot2.R
Original file line number Diff line number Diff line change
Expand Up @@ -227,79 +227,3 @@ grouped_matrix_ggplot2 <- function(x,
p
}

graph_ggplot2 <- function(x,
measure = "support",
shading = "lift",
control = NULL,
...) {

if (!is.null(shading) && all(is.na(shading)))
shading <- NULL

# NULLify
label <- NULL

control <- c(control, list(...))
control <- .get_parameters(
control,
list(
#main = paste("Graph for", length(x), "rules"),
layout = 'stress',
circular = FALSE,
ggraphdots = NULL,

edges = ggraph::geom_edge_link(
### FIXME: dynamic length!
# aes_string(
# end_cap = paste0("circle(node2.", measure, ", unit = 'native')"),
# start_cap = paste0("circle(node1.", measure, ", unit = 'native')"),
# ),
# 3 mm is the radius for size 6 points
end_cap = ggraph::circle(3, "mm"),
start_cap = ggraph::circle(3, "mm"),
color = "black",
arrow = arrow(length = unit(2, "mm"), angle = 20, type = "closed"),
alpha = .2
),

nodes = if (!is.null(shading)) ggraph::geom_node_point(aes_string(size = measure, color = shading))
else ggraph::geom_node_point(aes_string(size = measure), color = default_colors(1), alpha = .3),
nodetext = ggraph::geom_node_text(aes_string(label = "label")),

colors = default_colors(2),
engine = "ggplot2",
max = 100
)
)

if (length(x) > control$max) {
warning(
"Too many rules supplied. Only plotting the best ",
control$max,
" rules using ",
shading,
" (change control parameter max if needed)",
call. = FALSE
)
x <- tail(x,
n = control$max,
by = shading,
decreasing = FALSE)
}

g <- associations2igraph(x)

# complains about missing values for points (na.rm = TRUE does not currently work)
do.call(ggraph::ggraph,
c(list(graph = g, layout = control$layout, circular = control$circular), control$ggraphdots)) +
#ggraph::ggraph(g, layout = control$layout, circular = control$circular) +
control$edges +
control$nodes +
control$nodetext +
scale_color_gradient(
low = control$colors[2],
high = control$colors[1],
na.value = 0) +
scale_size(range = c(3, 8)) +
ggraph::theme_graph(base_family = "") # base_family is a problem for latex
}
167 changes: 167 additions & 0 deletions R/ggraph.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#######################################################################
# arulesViz - Visualizing Association Rules and Frequent Itemsets
# Copyright (C) 2021 Michael Hahsler
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

graph_ggplot2 <- function(x,
measure = "support",
shading = "lift",
control = NULL, asEdges = NULL,
...) {
if (!is.null(asEdges) && asEdges)
graph_edges_ggplot2(x, measure, shading, control, ...)
else
graph_nodes_ggplot2(x, measure, shading, control, ...)
}

graph_nodes_ggplot2 <- function(x,
measure = "support",
shading = "lift",
control = NULL,
...) {

if (!is.null(shading) && (all(is.na(shading)) || is.null(quality(x)[[shading]])))
shading <- NULL

# NULLify
label <- NULL

control <- c(control, list(...))
control <- .get_parameters(
control,
list(
#main = paste("Graph for", length(x), "rules"),
layout = 'stress',
circular = FALSE,
ggraphdots = NULL,

edges = ggraph::geom_edge_link(
### FIXME: dynamic length!
# aes_string(
# end_cap = paste0("circle(node2.", measure, ", unit = 'native')"),
# start_cap = paste0("circle(node1.", measure, ", unit = 'native')"),
# ),
# 3 mm is the radius for size 6 points
end_cap = ggraph::circle(3, "mm"),
start_cap = ggraph::circle(3, "mm"),
color = "gray80",
arrow = arrow(length = unit(2, "mm"), angle = 20, type = "closed"),
alpha = .2
),

nodes = if (!is.null(shading))
ggraph::geom_node_point(aes_string(size = measure, color = shading, filter = "type == 2"))
else
ggraph::geom_node_point(aes_string(size = measure, filter = "type == 2"),
color = default_colors(1), alpha = .3),

nodetext = ggraph::geom_node_text(aes_string(label = "label", filter = "type == 1"), repel = TRUE),

colors = default_colors(2),
engine = "ggplot2",
max = 100
)
)

x <- limit(x, control$max, shading, measure)
g <- associations2igraph(x)

# complains about missing values for points (na.rm = TRUE does not currently work)
do.call(ggraph::ggraph,
c(list(graph = g, layout = control$layout, circular = control$circular), control$ggraphdots)) +
#ggraph::ggraph(g, layout = control$layout, circular = control$circular) +
control$edges +
control$nodes +
control$nodetext +
scale_color_gradient(
low = control$colors[2],
high = control$colors[1],
na.value = 0) +
# base_family is a problem for latex
ggraph::theme_graph(base_family = "") +
coord_cartesian(clip="off")
}

graph_edges_ggplot2 <- function(x,
measure = "support",
shading = "lift",
control = NULL,
...) {

if (!is.null(shading) && (all(is.na(shading)) || is.null(quality(x)[[shading]])))
shading <- NULL

# NULLify
label <- NULL

control <- c(control, list(...))
control <- .get_parameters(
control,
list(
#main = paste("Graph for", length(x), class(x)),
layout = 'linear',
circular = TRUE,
ggraphdots = NULL,

edges = ggraph::geom_edge_arc(
### FIXME: dynamic length!
# aes_string(
# end_cap = paste0("circle(node2.", measure, ", unit = 'native')"),
# start_cap = paste0("circle(node1.", measure, ", unit = 'native')"),
# ),
# 3 mm is the radius for size 6 points
aes_string(edge_colour = shading, edge_width = measure),
end_cap = ggraph::circle(3, "mm"),
start_cap = ggraph::circle(3, "mm"),
arrow = if (is(x, "rules"))
arrow(length = unit(2, "mm"), angle = 20, type = "closed")
else
NULL,
alpha = .7
),

nodes = NULL,
nodetext = if (!is.null(control$circular) && !control$circular)
ggraph::geom_node_text(aes_string(label = "label"), alpha = .8, angle = 45, hjust = 1)
else
ggraph::geom_node_text(aes_string(label = "label"), alpha = .8, repel = TRUE),
colors = default_colors(2),
engine = "ggplot2",
max = 100
)
)

x <- limit(x, control$max, shading, measure)
# FIXME: reduce overplotting when shading is used is not easy in igraph
g <- associations2igraph(x, associationsAsNodes = FALSE)

# complains about missing values for points (na.rm = TRUE does not currently work)
do.call(ggraph::ggraph,
c(list(graph = g, layout = control$layout, circular = control$circular), control$ggraphdots)) +
#ggraph::ggraph(g, layout = control$layout, circular = control$circular) +
control$edges +
control$nodes +
control$nodetext +
ggraph::scale_edge_width(range = c(0.5, 2)) +
ggraph::scale_edge_color_gradient(
low = control$colors[2],
high = control$colors[1],
na.value = 0) +
# base_family is a problem for latex
ggraph::theme_graph(base_family = "", plot_margin = margin(5, 5, 5, 5, unit = "mm")) +
# no cliping for labels
coord_cartesian(clip="off")
}
Loading

0 comments on commit 60c8e40

Please sign in to comment.