VizARM.AREtoGraph
Transforms a set of association rules into the VizARE typed graph, following:
Fernandez-Basso, C., Ruiz, M.D., Molina-Solana, M., Martin-Bautista, M.J. (2026). VizARE: An Intermediate Representation to Support the Visualization of Association Rules in Data Mining. Future Internet, 18(7), 374. See Citing ARMxtend.
Unlike a flat item-to-item graph (where an edge would join every antecedent item directly to
every consequent item, losing the rule's structure as soon as it has more than one item per
side), VizARE uses two node types -- item and rule -- connected by directed edges with an
explicit semantic role: antecedent (item -> rule) and consequent (rule -> item). A rule's
measures of interest (support, confidence, lift, ...) live as attributes of its own rule node,
not of an edge, and a rule with several antecedent/consequent items is simply a rule node with
several incoming/outgoing edges -- no ambiguity, no information lost.
Building the graph
AREtoGraph.from_dataframe(rules_df, rule_measures=("support", "confidence", "lift"))
The most convenient entry point: builds the graph directly from a rules pandas.DataFrame, in the
same format returned by ARM.association_rules or
FIM.FARE.fuzzy_association_rules (columns antecedents/consequents as
frozensets of items, plus one column per measure named in rule_measures).
from ARMxtend.ARM.association_rules import association_rules
from ARMxtend.VizARM import AREtoGraph
rules = association_rules(freq_itemsets_df, metric="confidence", min_threshold=0.5)
graph = AREtoGraph.from_dataframe(rules, rule_measures=("support", "confidence", "certainty_factor"))
Or build it rule by rule with add_rule(antecedent, consequent, measures) (Algorithm 1,
RulesToGraph, of the paper) -- useful when the rules don't come from a DataFrame:
graph = AREtoGraph()
graph.add_rule(["temperature_cold", "occupation_low"], ["hvac_off"],
measures={"support": 0.31, "confidence": 0.87})
Item nodes get a group attribute -- the attribute name of the item, used by the paper for
indexing/visualization -- inferred by default from the attribute_value naming convention already
used by preprocessing.FuzzyLib (e.g. "temperature_cold" ->
group "temperature"); pass your own item_group_fn(item) -> str to add_rule/from_dataframe
to override it.
Alternatively, AREtoGraph(path, MeasuresRules, MeasuresItems=None, SepRule=";", SepFI=";",
SepItems=",") loads rules from a CSV file with antecedents/consequents columns (items joined
by SepItems) plus one column per measure in MeasuresRules; load_item_measures(path) attaches
per-item measures (e.g. support) from a second CSV.
Rule summarization (optional)
graph.summarize(signature="antecedent_consequent", measures=("support", "confidence"))
Section 4.2 of the paper: when the rule set is large, inspecting one node per rule becomes
cluttered. summarize adds a summary node per group of rules sharing the same signature
("antecedent", "consequent", or "antecedent_consequent", the default), aggregating each
measure's min/max/mean/quantiles across the group and keeping a members list of the
original rule ids for drill-down. Summary nodes connect to the same item nodes, with the same
antecedent/consequent semantics as regular rule nodes, so a visualization tool can render
either the full rule-level graph or the summarized one:
for summaryId in graph.summarize(signature="consequent"):
data = graph.graph.nodes[summaryId]
print(data["rule_count"], "rules ->", data["members"])
Exporting
graph.exportGraph(type=0) # JGF (JSON Graph Format) -- the paper's proposed intermediate form
graph.exportGraph(type=1) # GraphML string (Gephi / Cytoscape / NetworkX)
graph.exportGraph(type=2) # DOT string (Graphviz)
graph.exportGraph(type=3) # the underlying networkx.DiGraph
JGF (also available directly as graph.to_jgf() / graph.to_jgf_dict()) is the format proposed by
the paper as an interoperability layer between rule-mining algorithms and visualization tools --
it can be stored as-is in a document database (MongoDB) or loaded into a graph database (Neo4j) for
querying, and is natively understood by graph-visualization libraries such as
D3.js, Bokeh, Gephi or
NetworkX:
graph = AREtoGraph.from_dataframe(rules)
print(graph.to_jgf())
# {
# "graph": {
# "directed": true,
# "type": "association-rules",
# "nodes": {
# "A": {"label": "A", "metadata": {"kind": "item", "group": "A"}},
# "rule::A=>C": {"label": "A -> C", "metadata": {"kind": "rule", "support": 0.4, "confidence": 0.8, ...}}
# },
# "edges": [
# {"source": "A", "target": "rule::A=>C", "relation": "antecedent", "metadata": {}},
# {"source": "rule::A=>C", "target": "C", "relation": "consequent", "metadata": {}}
# ]
# }
# }
Write the GraphML/DOT result to a .graphml/.dot file to open it in your graph visualization
tool of choice, or work with the networkx.DiGraph (type=3) directly for further analysis
(centrality, community detection, ...) using networkx.