Updated compatibility with ggrepel >= 0.9.7. geom_dag_label_repel2() now uses linewidth = 0 (instead of label.size = NA) to hide label borders, matching ggrepel's new linewidth aesthetic. The verbose parameter in repel functions now defaults to getOption("verbose", default = FALSE).
geom_dag() gains a label_geom parameter that allows users to specify which geom function to use for labels when use_labels = TRUE (#133). The default remains geom_dag_label_repel for backward compatibility, but users can now choose any label/text geom function such as geom_dag_label, geom_dag_text_repel, geom_dag_label_repel2, or geom_dag_text_repel2.
geom_dag_text_repel() and geom_dag_label_repel() now support all current ggrepel parameters (#172):
stat, position, min.segment.length, force_pull, max.time, max.overlaps, xlim, ylim, direction, seed, and verbose parameterssegment.alpha now defaults to 1 but can be overridden by userssegment.linetype, segment.curvature, segment.angle) now pass through correctly via ...point.size and point.colour can also be passed through ...ggrepel::position_nudge_repel() - users can now use either nudge_x/nudge_y parameters or position = position_nudge_repel()Added comprehensive set of is_*() functions for testing DAG properties:
is_acyclic(): Test if a DAG is acyclicis_adjustment_set(): Test if a set of variables is a valid adjustment setis_d_separated(), is_d_connected(): Test d-separation relationshipsis_exogenous(): Test if a variable has no parentsis_instrumental(): Test if a variable is instrumentalis_exposure(), is_outcome(), is_latent(): Test variable statusis_parent(), is_child(), is_ancestor(), is_descendant(): Test node relationshipsis_adjacent(): Test if two nodes are adjacentAdded edge_backdoor() function to classify edges as being on backdoor paths, direct causal paths, or both between exposure and outcome (#137)
Enhanced dag_paths() and query_paths() to include path_type column that classifies paths as "backdoor" or "direct" (#137)
Changed default aesthetic in ggdag_paths() from coloring by path status to coloring by path type (direct vs backdoor), providing more informative visualization of causal pathways
Introduced new query_*() API for direct analytical queries on DAGs (#185). These functions return tibbles with results rather than tidy DAG objects for plotting:
query_adjustment_sets(): Find adjustment sets to close backdoor pathsquery_paths(): Find and analyze paths between nodesquery_instrumental(): Identify instrumental variablesquery_dseparated()/query_dconnected(): Test d-separation relationshipsquery_colliders(): Identify collider nodesquery_exogenous(): Find exogenous variablesquery_parents(), query_children(), query_ancestors(), query_descendants(): Query node relationshipsquery_markov_blanket(): Find Markov blanketsAll error messages, warnings, and informational messages now use the cli package for better formatting and user experience. This change adds custom error classes (ggdag_error, ggdag_warning) that enable programmatic error handling (#191).
Fixed tidy_dagitty() error when processing DAGs with no edges (#159)
Fixed dag_paths() error when no open paths exist between nodes (#180)
Introduced new functions query_conditional_independence(), test_conditional_independence(), and ggdag_conditional_independence() for detecting, testing, and visualizing implied conditional independencies in a given DAG and dataset (#139)
Added sort parameter to ggdag_conditional_independence() with default TRUE to sort conditional independence tests by their estimates for improved readability (#170)
Introduced new functions aes_dag() and geom_dag() to simplify specification of ggplot code for most DAGs. Also refactored most quick plots to use these functions (#121)
Added new function geom_label_repel2() for more opinionated repelled labels that often look better on DAGs (#132)
Improved DAG data structure by removing unnecessary circular column when not needed. The column is now only included when using circular layouts. This simplifies the tidy DAG structure for most use cases (#119)
Edge geoms now support mapping color/colour aesthetics to edge_color/edge_colour for more intuitive usage, matching ggplot2 conventions (#166)
Fixed theme_dag() facet labels being clipped by adding margin to strip text (#173)
Added quick plot functions for the causal quartet: quartet_collider(), quartet_confounder(), quartet_mediator(), quartet_m_bias(), and quartet_time_collider(), along with their ggdag_* counterparts. These functions create DAGs representing the causal quartet from D'Agostino McGowan, Gerke, and Barrett (2023), demonstrating that statistical properties alone cannot determine causal relationships (#171)
time_ordered_coords() and layout (#115)geom_dag_label() to complement geom_dag_text() and the repel functions (#116)pull_dag() and pull_dag_data() to extract DAG components, update_dag() and update_dag_data() to update DAG components, and as_tidy_dagitty() to construct DAGs from data frames (#117). Thanks to @lorenzoFabbri for inspiring some of the data-to-dag code in #90.left_join() interface with dplyr 1.1.0 (#110)time_ordered_coords() for calculating time-ordered coordinates (#88)size is now deprecated for geom_dag_collider_edges() in favor of linewidth, related to #79.dag_adjustment_sets() when width option was low by extracting adjustment sets directly (#70)tidy_dagitty() that missed nodes with no edges attached. May cause minor breaking changes in randomized layouts. (#68)limit argument to dag_paths, ggdag_paths, and ggdag_paths_fan (see dagitty::paths) (#65).tidy_dagitty() no longer allows the dendogram layout type (#62)scale_adjusted() now correctly aligns legend types (#61)Depends, instead importing it internally (#57).activate_collider_paths() that causes an error where a collider had a high number of ancestors (#49)node_equivalent_dags() where extra columns did not get joined to new tidy DAG (#40).R file. (#27)dag_paths() and geom_dag_edges_fan() (#31)use_defaults() ggproto method in GeomDAGEdge (#33)ggplot2::expansion() instead of expand_scale() when ggplot2 version is at least 3.3.0 and removed local version of expand_scale() (#34)ggdag_collider() where the aesthetics were flipped for the colors but not the labels (issue #15, b72e34b)as.character.default() directly for working with characters to avoid dispatch error when the formula.tools package is attached (issue #17, 0f32bb4)strength parameter in curved geomsnode_equivalent_class() that didn't account for the way dagitty returns DAGs with no directionnode_equivalent_class() that didn't check to nodeis_false() to avoid dependency on R 3.5.0{} to adjustment set names to reflect conventionNEWS.md file to track changes to the package.