# Customizing the Hierarchy Diagram

`autoplot.ackwards()` exposes a large number of arguments for controlling the appearance of the hierarchy diagram. This vignette is a visual reference: each section demonstrates one group of arguments with rendered figures so you can see the effect before writing any code.

All options shown here are presentation-only — they do not change which factors were extracted or how the between-level correlations were computed. Options that change which nodes appear (`drop_pruned`, `compress_levels`) are specific to the Forbes pruning extension and are covered in `vignette("ackwards-forbes")`.

## Setup

    library(ackwards)

    bfi <- na.omit(bfi25)
    x <- ackwards(bfi, k_max = 5, cor = "polychoric")

The default diagram for reference:

    autoplot(x)

plot of chunk base

Factors are labeled `m{k}f{j}` (level k, factor j). Two edge aesthetics carry the between-level correlations, and each one comes with its own legend: arrow thickness encodes the magnitude |r|, and edge color encodes the direction (blue = positive, red–orange = negative). Level labels on the left count factors per level.

Primary-parent edges are always positive after sign alignment; a red (negative) edge is therefore a genuine secondary relationship, not an artifact.

## Encoding sign and magnitude

You choose which aesthetic carries which piece of information. `sign_by` picks the channel for direction and `magnitude_by` picks the channel for |r|. No aesthetic is ever mapped without a matching legend.

### `sign_by` — how direction is shown

`sign_by = "color"` (the default) uses `color_pos`/`color_neg`. `"linetype"` draws positive edges solid and negative edges dashed, freeing color for a single-hue figure. `"both"` uses color and linetype together — negatives get a distinct double-dash so they still read in greyscale — and merges the two into a single “Direction” legend. `"none"` drops sign encoding entirely.

    autoplot(x, sign_by = "linetype")

plot of chunk sign-by

    autoplot(x, sign_by = "both")

plot of chunk sign-by

### `magnitude_by` — how |r| is shown

By default `magnitude_by = "linewidth"` maps |r| to arrow thickness with a `|r|` legend. Set `magnitude_by = "none"` for uniform-width edges (see also `edge_linewidth`, below, to pin a specific width).

    autoplot(x, magnitude_by = "none")

plot of chunk magnitude-by

## Filtering edges

### `cut_show` — minimum |r| to display

Edges below `cut_show` are hidden entirely. Raising it produces a sparser diagram that emphasises only the strongest connections.

    # Default cut_show = 0.3 (already shown above)
    autoplot(x, cut_show = 0.5)

plot of chunk cut-show

## Edge colors

### `color_pos` / `color_neg` — custom direction colors

The default blue/red palette can be replaced with any colors recognised by R. British spellings (`colour_pos`, `colour_neg`) are accepted as aliases.

    autoplot(x, color_pos = "darkorchid", color_neg = "darkorange")

plot of chunk colours

When sign is not encoded by color (`sign_by = "linetype"` or `"none"`), all edges take the single `color_edge` (default black) — the basis for the Forbes (2023) publication style (see the worked example at the end of this vignette).

## Monochrome mode

### `mono = TRUE` — a black-and-white convenience wrapper

`mono = TRUE` is shorthand for `sign_by = "linetype"` with black edges: solid lines are positive correlations, dashed lines are negative. `magnitude_by` still applies, so `linewidth` continues to encode |r|.

    autoplot(x, mono = TRUE)

plot of chunk mono

`mono` suits black-and-white figures where the reader must distinguish positive from negative edges. To label the edges with their exact values as well, add `show_r = TRUE` (documented next).

## Correlation labels

### `show_r` / `r_digits` — annotate edges with r values

`show_r = TRUE` draws the rounded (signed) correlation at each edge midpoint. `r_digits` controls the number of decimal places (default 2).

    autoplot(x, show_r = TRUE)

plot of chunk show-r

    autoplot(x, show_r = TRUE, r_digits = 1)

plot of chunk show-r-digits

## Node labels

### `node_labels` — rename individual factors

`node_labels` is a named character vector mapping factor IDs to display strings. Unspecified factors keep any name attached with `set_factor_labels()`, falling back to their `m{k}f{j}` labels. If you have already labelled the object with `set_factor_labels()` (see `vignette("ackwards-interpret")`), those names appear on the diagram automatically and `node_labels` is only needed to override a particular node for this one plot.

    autoplot(x, node_labels = c(
      m5f1 = "Neuro.",
      m5f2 = "Extra.",
      m5f3 = "Consc.",
      m5f4 = "Agree.",
      m5f5 = "Open."
    ))

plot of chunk node-labels

Multi-line labels are supported via `\n`:

    autoplot(x, node_labels = c(
      m5f1 = "Neuro-\nticism",
      m5f2 = "Extra-\nversion"
    ))

plot of chunk node-labels-multiline

### `node_width` / `node_height` — size individual boxes to fit a label

A long substantive name may not fit the default box. `node_width` and `node_height` each accept a named vector keyed by factor ID, sizing those boxes individually; boxes you do not name keep the default. Increase `min_sep` to make room when a box grows wider than the spacing between siblings.

    autoplot(x,
      node_labels = c(m5f1 = "Neuroticism", m5f3 = "Conscientiousness"),
      node_width = c(m5f1 = 1.8, m5f3 = 2.2),
      min_sep = 2.4
    )

plot of chunk node-size

### `label_template()` — generate the scaffold

Typing out every factor ID is tedious for large objects. `label_template()` generates the full named vector in canonical diagram order and prints a copy-pasteable `c(...)` literal you can edit and pass back to `node_labels`. It also offers the Forbes (2023) letter convention (`"A1"`, `"B1"`, `"B2"`, …) as a built-in style:

    autoplot(x, node_labels = label_template(x, style = "forbes"))

plot of chunk label-template-forbes

For the full naming workflow — reading factors, the sign convention, and choosing labels across the hierarchy — see `vignette("ackwards-interpret")`.

## Item content

### `show_items` — list the items under the deepest-level factors

For a publication figure it helps to show what each most-granular factor is made of. `show_items = TRUE` lists the salient items beneath each deepest-level (`k_max`) box: the top `n_items` by `|loading|` at or above `item_cut`, using the same extraction as `top_items()` (variable labels appear when the data carried them into the fit; here `na.omit()` stripped `bfi25`’s label attributes, so the item IDs are shown — see `vignette("ackwards-interpret")` on keeping labels).

    autoplot(x, show_items = TRUE, n_items = 4)

plot of chunk show-items

## Structural simplifications

### `primary_only = TRUE` — show only primary-parent edges

Setting `primary_only = TRUE` keeps only the single strongest edge per factor (its primary parent), producing a clean tree. Because skip-level edges are never primary, this also suppresses curved arcs when `pairs = "all"` was used.

    autoplot(x, primary_only = TRUE)

plot of chunk primary-only

### `order` — arrange the deepest level by hand

The layout orders factors automatically to minimise edge crossings, but you may want a specific left-to-right arrangement — to match a paper, or to untangle a figure. `order` fixes the order of the deepest (`k_max`) level; supply that level’s factor IDs in the desired order. Every factor above stays centred over its primary children, so fixing the leaf order rearranges the whole tree coherently — any arrangement of the hierarchy is reachable this way.

    # Reverse the deepest level's left-to-right order
    deepest <- paste0("m5f", 5:1)
    autoplot(x, order = deepest)

plot of chunk manual-order

### `drop_pruned` + `show_secondary` — the pruned view and its hidden correlations

Pruning (see `vignette("ackwards-forbes")`) flags redundant factors; `drop_pruned = TRUE` then renders the reduced hierarchy, joining each retained factor to its single strongest surviving ancestor. That primary view hides every other between-level correlation. `show_secondary = TRUE` adds them back — each kept cross-level pair with `|r| >= cut_show` that is not a primary edge — drawn dimmed and thinner beneath the primary arrows, so the sign colors stay intact. These are a factor’s weaker second parents and direct skip-level correlations the primary path would otherwise obscure (a skip-level |r| is its own fact: correlation is not transitive, so it need not equal the product along the path).

    xp <- prune(x, "redundant")
    #> ℹ Redundancy pruning (direct criterion, |r| ≥ 0.9) flagged 6 nodes.
    #> ℹ Nodes are retained in the object; inspect with `x$prune$nodes` and
    #>   `x$prune$chains`.
    autoplot(xp, drop_pruned = TRUE) # primary view: one ancestor per factor

plot of chunk drop-pruned-secondary

    autoplot(xp, drop_pruned = TRUE, show_secondary = TRUE) # + secondary correlations

plot of chunk drop-pruned-secondary

## Level labels

### `show_level_labels` / `level_label_size`

Level labels (“1 factor”, “2 factors”, …) are shown by default on the left margin. They can be hidden or resized.

    autoplot(x, show_level_labels = FALSE)

plot of chunk level-labels-off

    autoplot(x, show_level_labels = TRUE, level_label_size = 4)

plot of chunk level-labels-size

## Arrowheads

### `show_arrows = FALSE` — plain line ends

By default, edges end with closed arrowheads. Setting `show_arrows = FALSE` draws plain line ends. This applies to both straight edges and curved skip-level arcs.

    autoplot(x, show_arrows = FALSE)

plot of chunk no-arrows

## Edge width

### `edge_linewidth` — uniform vs. |r|-scaled width

By default, edge width is proportional to |r| (via `magnitude_by`). A numeric `edge_linewidth` draws every edge at that constant width and removes the `|r|` legend — like `magnitude_by = "none"`, but at a width you choose.

    autoplot(x, edge_linewidth = 0.7)

plot of chunk edge-linewidth

## Layout orientation

### `direction = "horizontal"` — left-to-right layout

By default levels stack top-to-bottom (level 1 at top). `direction = "horizontal"` lays them out left-to-right (level 1 at left), which fits wide slides and posters; the level labels move to the bottom margin.

    autoplot(x, direction = "horizontal")

plot of chunk direction

## Legend

### `legend = FALSE` — suppress all guides

`legend = FALSE` removes all legends from the plot. Most useful when the diagram is self-explanatory or the legend duplicates information conveyed by labels.

    autoplot(x, legend = FALSE)

plot of chunk no-legend

## Worked example: publication-ready figure

The following call reproduces the visual style of Forbes (2023): black lines of uniform weight, plain line ends, correlation labels, and no legend. Setting both direction colors to black yields a single-hue figure, and `legend = FALSE` suppresses the now-redundant key.

    autoplot(x,
      color_pos      = "black",
      color_neg      = "black",
      edge_linewidth = 0.6,
      show_arrows    = FALSE,
      show_r         = TRUE,
      legend         = FALSE
    )

plot of chunk pub-figure

Combining with `node_labels` names the factors for the final figure:

    autoplot(x,
      color_pos = "black",
      color_neg = "black",
      edge_linewidth = 0.6,
      show_arrows = FALSE,
      show_r = TRUE,
      legend = FALSE,
      node_labels = c(
        m5f1 = "Neuro.",
        m5f2 = "Extra.",
        m5f3 = "Consc.",
        m5f4 = "Agree.",
        m5f5 = "Open."
      )
    )

plot of chunk pub-figure-labeled

For the pruned-factor variant of this figure (nodes omitted, spanning arrows) see `vignette("ackwards-forbes")`.

## Saving plots

`autoplot()` returns an ordinary `ggplot` object, so save it with `ggplot2::ggsave()`:

    p <- autoplot(x, direction = "horizontal")
    ggplot2::ggsave("hierarchy.png", p, width = 9, height = 5, dpi = 300)

`ackwards` does not re-export `ggsave()` — that would move `ggplot2` from Suggests into Imports — so call it from `ggplot2` directly.

## Diagnostic scree / criteria plot: `autoplot.suggest_k()`

`suggest_k()` also has its own `autoplot()` method, producing a multi-panel scree / parallel-analysis / VSS diagnostic. It is documented in depth in `vignette("ackwards-suggest-k")`; here we only note that the same `autoplot()` generic covers it.

    sk <- suggest_k(bfi, seed = 42)
    #> ℹ Running parallel analysis (20 iterations, PC + FA)...
    #> ✔ Running parallel analysis (20 iterations, PC + FA)... [168ms]
    #>
    #> ℹ Running MAP and VSS...
    #> ✔ Running MAP and VSS... [61ms]
    #>
    #> ℹ Running Comparison Data (CD)...
    #> ✔ Running Comparison Data (CD)... [6.8s]
    #>
    autoplot(sk)

plot of chunk suggest_k_plot

## References

Forbes, M. K. (2023). Improving hierarchical models of individual differences: An extension of Goldberg’s bass-ackward method. Psychological Methods. https://doi.org/10.1037/met0000546