From de5ace556328b8795e5be178dfd6c812f22479fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:38:57 +0000 Subject: [PATCH 01/17] Initial plan From 4a7f1511bc73ff147d46addc1a837dc40900eeb8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:43:39 +0000 Subject: [PATCH 02/17] Add ego_color_var, ego_color_palette, and ego_color_legend_label parameters Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 12 +++++ R/plot_ego_graph.R | 124 ++++++++++++++++++++++++++++++++++++++++----- R/plot_egor.R | 9 ++++ 3 files changed, 132 insertions(+), 13 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 6296a8e..914dc5a 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -101,6 +101,9 @@ plot_egograms <- function(x, vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, edge_color_var = NULL, @@ -140,6 +143,9 @@ plot_egograms <- function(x, vertex_color_var = vertex_color_var, vertex_color_palette = vertex_color_palette, vertex_color_legend_label = vertex_color_legend_label, + ego_color_var = ego_color_var, + ego_color_palette = ego_color_palette, + ego_color_legend_label = ego_color_legend_label, vertex_label_var = vertex_label_var, edge_width_var = edge_width_var, edge_color_var = edge_color_var, @@ -169,6 +175,9 @@ plot_egogram <- vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, edge_color_var = NULL, @@ -368,6 +377,9 @@ plot_egogram <- vertex_color_var = vertex_color_var, vertex_color_palette = vertex_color_palette, vertex_color_legend_label = vertex_color_legend_label, + ego_color_var = ego_color_var, + ego_color_palette = ego_color_palette, + ego_color_legend_label = ego_color_legend_label, vertex_label_var = vertex_label_var, edge_width_var = edge_width_var, edge_color_var = edge_color_var, diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index 9c4eff6..851b0ca 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -8,6 +8,9 @@ plot_ego_graphs <- function(x, vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, ego_alter_edge_width_var = @@ -44,6 +47,9 @@ plot_ego_graphs <- function(x, vertex_color_var = vertex_color_var, vertex_color_palette = vertex_color_palette, vertex_color_legend_label = vertex_color_legend_label, + ego_color_var = ego_color_var, + ego_color_palette = ego_color_palette, + ego_color_legend_label = ego_color_legend_label, vertex_label_var = vertex_label_var, edge_width_var = edge_width_var, ego_alter_edge_width_var = ego_alter_edge_width_var, @@ -70,6 +76,9 @@ plot_one_ego_graph <- function(x, vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, ego_alter_edge_width_var = edge_width_var, @@ -92,6 +101,9 @@ plot_one_ego_graph <- function(x, if (vertex_label_var %in% names(x$ego)) { ego_attrs <- c(ego_attrs, vertex_label_var) } + if (!is.null(ego_color_var) && ego_color_var %in% names(x$ego)) { + ego_attrs <- c(ego_attrs, ego_color_var) + } } gr <- as_igraph(x, @@ -149,6 +161,38 @@ plot_one_ego_graph <- function(x, clrs <- "coral" } + # Ego Color (if include_ego is TRUE and ego_color_var is specified) + if (include_ego && !is.null(ego_color_var)) { + # Check if ego_color_var differs from vertex_color_var + if (!identical(ego_color_var, vertex_color_var) || + !identical(ego_color_palette, vertex_color_palette)) { + # Get ego's color value + ego_color_value <- igraph::vertex_attr(gr, ego_color_var)[length(igraph::V(gr))] + + # If ego_color_var and vertex_color_var are the same variable but different palettes, + # or if they're different variables, we need to determine the ego color + if (identical(ego_color_var, vertex_color_var)) { + # Same variable, different palette - use the combined levels but apply ego_color_palette to ego + ego_colors_ <- egor_col_pal(ego_color_palette, + length(levels(vertex.color))) + clrs[length(clrs)] <- ego_colors_[vertex.color[length(vertex.color)]] + } else { + # Different variables - get all values for ego_color_var from both ego and alters + all_ego_color_values <- igraph::vertex_attr(gr, ego_color_var) + ego_color_factor <- factor(all_ego_color_values) + ego_colors_ <- egor_col_pal(ego_color_palette, + length(levels(ego_color_factor))) + # Apply ego color only to the last vertex (ego) + ego_color_mapped <- ego_colors_[ego_color_factor] + clrs[length(clrs)] <- ifelse(is.na(ego_color_mapped[length(ego_color_mapped)]), + "#ffffff", + ego_color_mapped[length(ego_color_mapped)]) + } + } + # If ego_color_var and vertex_color_var are identical (including palette), + # the ego color is already set correctly by the vertex color logic above + } + # Edge Width if (!is.null(edge_width_var)) { edge.width <- @@ -255,19 +299,73 @@ plot_one_ego_graph <- function(x, ifelse(vertex_color_legend_label == "", vertex_color_var, vertex_color_legend_label) - legend( - x = -1.9, - y = 1.1, - legend = levels(factor(color_var)), - pt.bg = colors_, - pt.cex = 1.5, - pch = 22, - bty = "n", - y.intersp = 1, - title = title_, - xpd = TRUE, - cex = font_size - ) + + # Determine if we need a separate ego legend + show_ego_legend <- include_ego && !is.null(ego_color_var) && + (!identical(ego_color_var, vertex_color_var) || + !identical(ego_color_palette, vertex_color_palette)) + + if (show_ego_legend && !identical(ego_color_var, vertex_color_var)) { + # Different variables: show two legends side by side or stacked + # First show alter/vertex legend + alter_color_var <- color_var[-length(color_var)] # Exclude ego + legend( + x = -1.9, + y = 1.1, + legend = levels(factor(alter_color_var)), + pt.bg = colors_, + pt.cex = 1.5, + pch = 22, + bty = "n", + y.intersp = 1, + title = paste0("Alter: ", title_), + xpd = TRUE, + cex = font_size + ) + + # Now show ego legend below + ego_color_var_values <- igraph::vertex_attr(gr, ego_color_var) + ego_color_factor <- factor(ego_color_var_values) + ego_colors_ <- egor_col_pal(ego_color_palette, + length(levels(ego_color_factor))) + ego_title_ <- + ifelse(ego_color_legend_label == "", + ego_color_var, + ego_color_legend_label) + + # Calculate y position for second legend + n_alter_levels <- length(levels(factor(alter_color_var))) + y_offset <- 1.1 - (n_alter_levels * 0.15) - 0.3 + + legend( + x = -1.9, + y = y_offset, + legend = levels(ego_color_factor), + pt.bg = ego_colors_, + pt.cex = 1.5, + pch = 22, + bty = "n", + y.intersp = 1, + title = paste0("Ego: ", ego_title_), + xpd = TRUE, + cex = font_size + ) + } else { + # Same variable or same variable with different palette: show single legend + legend( + x = -1.9, + y = 1.1, + legend = levels(factor(color_var)), + pt.bg = colors_, + pt.cex = 1.5, + pch = 22, + bty = "n", + y.intersp = 1, + title = title_, + xpd = TRUE, + cex = font_size + ) + } } par(mar = c(0.5, 0.5, 0.5, 0.5)) graphics::box(lty = 'solid', col = highlight_box_col, lwd = 5) diff --git a/R/plot_egor.R b/R/plot_egor.R index f1675d5..cbce77d 100644 --- a/R/plot_egor.R +++ b/R/plot_egor.R @@ -13,6 +13,9 @@ #' @param vertex_color_var Name (`character`) of alter column. #' @param vertex_color_palette Name (`character`) of color palette, see details for available color palettes. #' @param vertex_color_legend_label Character. +#' @param ego_color_var Name (`character`) of ego column to determine ego vertex color. Defaults to `vertex_color_var`. Used in combination with `include_ego = TRUE` to visualize ego-alter homophily. +#' @param ego_color_palette Name (`character`) of color palette for ego vertex. Defaults to `vertex_color_palette`. See details for available color palettes. +#' @param ego_color_legend_label Character. Legend label for ego color. Defaults to `ego_color_var`. #' @param vertex_label_var Name (`character`) of alter column. Set this to `NULL` to suppress labels. #' @param edge_width_var Name (`character`) of aatie column. #' @param ego_alter_edge_width_var Name (`character`) of alter column. @@ -41,6 +44,12 @@ #' on a map of (1) concentric circles with (2) subsections, that can be mapped to #' alter variables. #' +#' The `ego_color_var`, `ego_color_palette`, and `ego_color_legend_label` +#' parameters allow specifying ego's color separately from alters' colors +#' when `include_ego = TRUE`. This is helpful for visualizing ego-alter +#' homophily. When `ego_color_var` equals `vertex_color_var`, the same color +#' mapping is used to ensure consistency. +#' #' Available color palettes are: #' #' - Heat Colors From 8d430c0e557bda9d7792ce70198aceb648cf5f7f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:44:51 +0000 Subject: [PATCH 03/17] Add tests for ego_color_* parameters Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- tests/testthat/test-plot_egor.R | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/tests/testthat/test-plot_egor.R b/tests/testthat/test-plot_egor.R index eb0581b..44a1a04 100644 --- a/tests/testthat/test-plot_egor.R +++ b/tests/testthat/test-plot_egor.R @@ -561,4 +561,104 @@ test_that("plot_ego_graphs() displays ego names correctly #99", { edge.curved = FALSE), NA) }) +test_that("plot_egograms() supports separate ego_color_var parameter", { + expect_error({ + e <- make_egor(5, 12) + e$ego$ego_attr <- sample(c("A", "B", "C"), nrow(e$ego), replace = TRUE) + + # Test with same variable for ego and alters (default behavior) + plot_egograms( + x = e, + ego_no = 1, + venn_var = "sex", + pie_var = "country", + vertex_color_var = "sex", + include_ego = TRUE + ) + + # Test with different variable for ego + plot_egograms( + x = e, + ego_no = 1, + venn_var = "sex", + pie_var = "country", + vertex_color_var = "sex", + ego_color_var = "ego_attr", + include_ego = TRUE + ) + + # Test with same variable but different palette + plot_egograms( + x = e, + ego_no = 1, + venn_var = "sex", + pie_var = "country", + vertex_color_var = "sex", + vertex_color_palette = "Heat Colors", + ego_color_var = "sex", + ego_color_palette = "Greys", + include_ego = TRUE + ) + }, NA) +}) + +test_that("plot_ego_graphs() supports separate ego_color_var parameter", { + expect_error({ + e <- make_egor(5, 12) + e$ego$ego_attr <- sample(c("A", "B", "C"), nrow(e$ego), replace = TRUE) + + # Test with same variable for ego and alters (default behavior) + plot_ego_graphs( + x = e, + ego_no = 1, + vertex_color_var = "sex", + include_ego = TRUE + ) + + # Test with different variable for ego + plot_ego_graphs( + x = e, + ego_no = 1, + vertex_color_var = "sex", + ego_color_var = "ego_attr", + include_ego = TRUE + ) + + # Test with same variable but different palette + plot_ego_graphs( + x = e, + ego_no = 1, + vertex_color_var = "sex", + vertex_color_palette = "Heat Colors", + ego_color_var = "sex", + ego_color_palette = "Greys", + include_ego = TRUE + ) + }, NA) +}) + +test_that("ego_color parameters default to vertex_color parameters", { + # This test ensures backward compatibility + expect_error({ + e <- make_egor(5, 12) + + # Without specifying ego_color_*, should behave as before + plot_egograms( + x = e, + ego_no = 1, + venn_var = "sex", + pie_var = "country", + vertex_color_var = "sex", + include_ego = TRUE + ) + + plot_ego_graphs( + x = e, + ego_no = 1, + vertex_color_var = "sex", + include_ego = TRUE + ) + }, NA) +}) + dev.off() # Closing the NULL pdf device. \ No newline at end of file From 7104dae532413074eddfd6233bf17866054528cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:45:51 +0000 Subject: [PATCH 04/17] Fix ego color handling and add vertex_color_var to ego_attrs Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_graph.R | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index 851b0ca..c728850 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -101,7 +101,11 @@ plot_one_ego_graph <- function(x, if (vertex_label_var %in% names(x$ego)) { ego_attrs <- c(ego_attrs, vertex_label_var) } - if (!is.null(ego_color_var) && ego_color_var %in% names(x$ego)) { + if (!is.null(vertex_color_var) && vertex_color_var %in% names(x$ego)) { + ego_attrs <- c(ego_attrs, vertex_color_var) + } + if (!is.null(ego_color_var) && ego_color_var %in% names(x$ego) && + !identical(ego_color_var, vertex_color_var)) { ego_attrs <- c(ego_attrs, ego_color_var) } } @@ -166,27 +170,31 @@ plot_one_ego_graph <- function(x, # Check if ego_color_var differs from vertex_color_var if (!identical(ego_color_var, vertex_color_var) || !identical(ego_color_palette, vertex_color_palette)) { - # Get ego's color value - ego_color_value <- igraph::vertex_attr(gr, ego_color_var)[length(igraph::V(gr))] - # If ego_color_var and vertex_color_var are the same variable but different palettes, - # or if they're different variables, we need to determine the ego color + # If ego_color_var and vertex_color_var are the same variable but different palettes if (identical(ego_color_var, vertex_color_var)) { # Same variable, different palette - use the combined levels but apply ego_color_palette to ego ego_colors_ <- egor_col_pal(ego_color_palette, length(levels(vertex.color))) clrs[length(clrs)] <- ego_colors_[vertex.color[length(vertex.color)]] } else { - # Different variables - get all values for ego_color_var from both ego and alters - all_ego_color_values <- igraph::vertex_attr(gr, ego_color_var) - ego_color_factor <- factor(all_ego_color_values) - ego_colors_ <- egor_col_pal(ego_color_palette, - length(levels(ego_color_factor))) - # Apply ego color only to the last vertex (ego) - ego_color_mapped <- ego_colors_[ego_color_factor] - clrs[length(clrs)] <- ifelse(is.na(ego_color_mapped[length(ego_color_mapped)]), - "#ffffff", - ego_color_mapped[length(ego_color_mapped)]) + # Different variables - ego_color_var should be an ego-level attribute + # Check if the attribute exists in the graph (it should for the ego vertex) + if (ego_color_var %in% igraph::vertex_attr_names(gr)) { + ego_color_values <- igraph::vertex_attr(gr, ego_color_var) + # Get unique non-NA values to determine factor levels + unique_ego_values <- unique(ego_color_values[!is.na(ego_color_values)]) + ego_color_factor <- factor(ego_color_values, levels = unique_ego_values) + ego_colors_ <- egor_col_pal(ego_color_palette, + length(levels(ego_color_factor))) + # Apply ego color only to the last vertex (ego) + ego_idx <- length(clrs) + if (!is.na(ego_color_factor[ego_idx])) { + clrs[ego_idx] <- ego_colors_[ego_color_factor[ego_idx]] + } else { + clrs[ego_idx] <- "#ffffff" + } + } } } # If ego_color_var and vertex_color_var are identical (including palette), From bb6926a3b883b4f00b2ce805cf1c138a1db56649 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:48:57 +0000 Subject: [PATCH 05/17] Address code review feedback - improve readability and maintainability Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_graph.R | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index c728850..a9571b0 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -104,8 +104,11 @@ plot_one_ego_graph <- function(x, if (!is.null(vertex_color_var) && vertex_color_var %in% names(x$ego)) { ego_attrs <- c(ego_attrs, vertex_color_var) } - if (!is.null(ego_color_var) && ego_color_var %in% names(x$ego) && - !identical(ego_color_var, vertex_color_var)) { + # Add ego_color_var to ego_attrs if it's different from vertex_color_var + ego_needs_separate_color_var <- !is.null(ego_color_var) && + ego_color_var %in% names(x$ego) && + !identical(ego_color_var, vertex_color_var) + if (ego_needs_separate_color_var) { ego_attrs <- c(ego_attrs, ego_color_var) } } @@ -166,16 +169,19 @@ plot_one_ego_graph <- function(x, } # Ego Color (if include_ego is TRUE and ego_color_var is specified) + # Note: When include_ego=TRUE, the ego vertex is always added as the last vertex in the igraph if (include_ego && !is.null(ego_color_var)) { - # Check if ego_color_var differs from vertex_color_var - if (!identical(ego_color_var, vertex_color_var) || - !identical(ego_color_palette, vertex_color_palette)) { - + # Determine if ego needs separate coloring + ego_has_diff_color_config <- !identical(ego_color_var, vertex_color_var) || + !identical(ego_color_palette, vertex_color_palette) + + if (ego_has_diff_color_config) { # If ego_color_var and vertex_color_var are the same variable but different palettes if (identical(ego_color_var, vertex_color_var)) { # Same variable, different palette - use the combined levels but apply ego_color_palette to ego ego_colors_ <- egor_col_pal(ego_color_palette, length(levels(vertex.color))) + # The last vertex is always ego when include_ego=TRUE clrs[length(clrs)] <- ego_colors_[vertex.color[length(vertex.color)]] } else { # Different variables - ego_color_var should be an ego-level attribute @@ -309,13 +315,19 @@ plot_one_ego_graph <- function(x, vertex_color_legend_label) # Determine if we need a separate ego legend - show_ego_legend <- include_ego && !is.null(ego_color_var) && - (!identical(ego_color_var, vertex_color_var) || - !identical(ego_color_palette, vertex_color_palette)) + # Reuse the same condition as in ego color logic + ego_has_diff_color_config <- include_ego && !is.null(ego_color_var) && + (!identical(ego_color_var, vertex_color_var) || + !identical(ego_color_palette, vertex_color_palette)) - if (show_ego_legend && !identical(ego_color_var, vertex_color_var)) { - # Different variables: show two legends side by side or stacked + if (ego_has_diff_color_config && !identical(ego_color_var, vertex_color_var)) { + # Different variables: show two legends stacked + # Constants for legend spacing + LEGEND_ITEM_HEIGHT <- 0.15 + LEGEND_VERTICAL_GAP <- 0.3 + # First show alter/vertex legend + # Note: ego is always the last vertex when include_ego=TRUE alter_color_var <- color_var[-length(color_var)] # Exclude ego legend( x = -1.9, @@ -343,7 +355,7 @@ plot_one_ego_graph <- function(x, # Calculate y position for second legend n_alter_levels <- length(levels(factor(alter_color_var))) - y_offset <- 1.1 - (n_alter_levels * 0.15) - 0.3 + y_offset <- 1.1 - (n_alter_levels * LEGEND_ITEM_HEIGHT) - LEGEND_VERTICAL_GAP legend( x = -1.9, From 2ce1b82ff84f6547de899b79c535ecb6dc76286b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:08:05 +0000 Subject: [PATCH 06/17] Fix ego coloring when vertex_color_var is specified Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_graph.R | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index a9571b0..fa9595a 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -157,10 +157,7 @@ plot_one_ego_graph <- function(x, #vertex.color[is.na(vertex.color)] <- 0 vertex.color <- factor(vertex.color) colors_ <- egor_col_pal(vertex_color_palette, - length(levels( - factor(igraph::vertex_attr(gr, - vertex_color_var)) - ))) + length(levels(vertex.color))) clrs <- colors_[vertex.color] clrs[is.na(clrs)] <- "#ffffff" } else { From 7b5ab53b003bf0f988141b8df39294369e826a80 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:37:05 +0000 Subject: [PATCH 07/17] Move ego_color_* parameters after vertex_* parameters and add ego_label_var Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 28 ++++++++++++++++------------ R/plot_ego_graph.R | 39 ++++++++++++++++++++++++++++++--------- R/plot_egor.R | 16 +++++++++------- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 914dc5a..04c2b2d 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -101,9 +101,6 @@ plot_egograms <- function(x, vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, edge_color_var = NULL, @@ -118,6 +115,10 @@ plot_egograms <- function(x, venn_gradient_reverse = FALSE, show_venn_labels = TRUE, include_ego = FALSE, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, ...) { opar <- par(no.readonly = TRUE) on.exit(par(opar)) @@ -143,9 +144,6 @@ plot_egograms <- function(x, vertex_color_var = vertex_color_var, vertex_color_palette = vertex_color_palette, vertex_color_legend_label = vertex_color_legend_label, - ego_color_var = ego_color_var, - ego_color_palette = ego_color_palette, - ego_color_legend_label = ego_color_legend_label, vertex_label_var = vertex_label_var, edge_width_var = edge_width_var, edge_color_var = edge_color_var, @@ -159,6 +157,10 @@ plot_egograms <- function(x, font_size = font_size, show_venn_labels = show_venn_labels, include_ego = include_ego, + ego_color_var = ego_color_var, + ego_color_palette = ego_color_palette, + ego_color_legend_label = ego_color_legend_label, + ego_label_var = ego_label_var, ... ) } @@ -175,9 +177,6 @@ plot_egogram <- vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, edge_color_var = NULL, @@ -192,6 +191,10 @@ plot_egogram <- venn_gradient_reverse = FALSE, show_venn_labels = TRUE, include_ego = FALSE, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, ...) { if (!any(c(!is.null(pie_var), !is.null(venn_var)))) @@ -377,9 +380,6 @@ plot_egogram <- vertex_color_var = vertex_color_var, vertex_color_palette = vertex_color_palette, vertex_color_legend_label = vertex_color_legend_label, - ego_color_var = ego_color_var, - ego_color_palette = ego_color_palette, - ego_color_legend_label = ego_color_legend_label, vertex_label_var = vertex_label_var, edge_width_var = edge_width_var, edge_color_var = edge_color_var, @@ -392,6 +392,10 @@ plot_egogram <- edge.curved = igraph::E(g)$curved, include_ego = include_ego, font_size = font_size, + ego_color_var = ego_color_var, + ego_color_palette = ego_color_palette, + ego_color_legend_label = ego_color_legend_label, + ego_label_var = ego_label_var, ... ) } diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index fa9595a..0e2522b 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -8,9 +8,6 @@ plot_ego_graphs <- function(x, vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, ego_alter_edge_width_var = @@ -27,6 +24,10 @@ plot_ego_graphs <- function(x, font_size = 1, include_ego = FALSE, ego_attrs = NULL, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, ...) { require_igraph(paste(sQuote("egor"),"plotting ego graphs")) opar <- par(no.readonly = TRUE) @@ -47,9 +48,6 @@ plot_ego_graphs <- function(x, vertex_color_var = vertex_color_var, vertex_color_palette = vertex_color_palette, vertex_color_legend_label = vertex_color_legend_label, - ego_color_var = ego_color_var, - ego_color_palette = ego_color_palette, - ego_color_legend_label = ego_color_legend_label, vertex_label_var = vertex_label_var, edge_width_var = edge_width_var, ego_alter_edge_width_var = ego_alter_edge_width_var, @@ -63,6 +61,10 @@ plot_ego_graphs <- function(x, font_size = font_size, include_ego = include_ego, ego_attrs = ego_attrs, + ego_color_var = ego_color_var, + ego_color_palette = ego_color_palette, + ego_color_legend_label = ego_color_legend_label, + ego_label_var = ego_label_var, ... ) } @@ -76,9 +78,6 @@ plot_one_ego_graph <- function(x, vertex_color_var = NULL, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, vertex_label_var = "name", edge_width_var = NULL, ego_alter_edge_width_var = edge_width_var, @@ -93,6 +92,10 @@ plot_one_ego_graph <- function(x, include_ego = FALSE, ego_attrs = NULL, layout = NULL, + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, ...) { x <- slice.egor(activate(x, "ego"), ego_no) @@ -101,6 +104,12 @@ plot_one_ego_graph <- function(x, if (vertex_label_var %in% names(x$ego)) { ego_attrs <- c(ego_attrs, vertex_label_var) } + # Add ego_label_var to ego_attrs if it's different from vertex_label_var + if (!is.null(ego_label_var) && + ego_label_var %in% names(x$ego) && + !identical(ego_label_var, vertex_label_var)) { + ego_attrs <- c(ego_attrs, ego_label_var) + } if (!is.null(vertex_color_var) && vertex_color_var %in% names(x$ego)) { ego_attrs <- c(ego_attrs, vertex_color_var) } @@ -240,6 +249,18 @@ plot_one_ego_graph <- function(x, vertex.label <- "" } + # Ego Label (if include_ego is TRUE and ego_label_var is different) + if (include_ego && !is.null(ego_label_var) && !identical(ego_label_var, vertex_label_var)) { + # Check if the ego_label_var attribute exists in the graph + if (ego_label_var %in% igraph::vertex_attr_names(gr)) { + ego_label_value <- igraph::vertex_attr(gr, ego_label_var)[length(igraph::V(gr))] + # Only set if not NA + if (!is.na(ego_label_value)) { + vertex.label[length(vertex.label)] <- ego_label_value + } + } + } + par(mar = c(0.5, 0.5, 0.5, 0.5)) if (!is.null(vertex_color_var)) par(mar = c(0.5, 5, 0.5, 0.5)) diff --git a/R/plot_egor.R b/R/plot_egor.R index cbce77d..b12017f 100644 --- a/R/plot_egor.R +++ b/R/plot_egor.R @@ -13,9 +13,6 @@ #' @param vertex_color_var Name (`character`) of alter column. #' @param vertex_color_palette Name (`character`) of color palette, see details for available color palettes. #' @param vertex_color_legend_label Character. -#' @param ego_color_var Name (`character`) of ego column to determine ego vertex color. Defaults to `vertex_color_var`. Used in combination with `include_ego = TRUE` to visualize ego-alter homophily. -#' @param ego_color_palette Name (`character`) of color palette for ego vertex. Defaults to `vertex_color_palette`. See details for available color palettes. -#' @param ego_color_legend_label Character. Legend label for ego color. Defaults to `ego_color_var`. #' @param vertex_label_var Name (`character`) of alter column. Set this to `NULL` to suppress labels. #' @param edge_width_var Name (`character`) of aatie column. #' @param ego_alter_edge_width_var Name (`character`) of alter column. @@ -35,6 +32,10 @@ #' @param show_venn_labels Logical. #' @param include_ego Logical. #' @param ego_attrs `Character` vector naming ego variables to turn into ego vertex attributes. Used in combination with `include_ego = TRUE`. +#' @param ego_color_var Name (`character`) of ego column to determine ego vertex color. Defaults to `vertex_color_var`. Used in combination with `include_ego = TRUE` to visualize ego-alter homophily. +#' @param ego_color_palette Name (`character`) of color palette for ego vertex. Defaults to `vertex_color_palette`. See details for available color palettes. +#' @param ego_color_legend_label Character. Legend label for ego color. Defaults to `ego_color_var`. +#' @param ego_label_var Name (`character`) of ego column to determine ego vertex label. Defaults to `vertex_label_var`. Used in combination with `include_ego = TRUE`. #' @param type Character. Either "egograph" or "egogram". # @param layout `Matrix` of x and y coordinates for nodes. Defaults to # Fruchterman Rheingold layout algorithm. @@ -44,10 +45,11 @@ #' on a map of (1) concentric circles with (2) subsections, that can be mapped to #' alter variables. #' -#' The `ego_color_var`, `ego_color_palette`, and `ego_color_legend_label` -#' parameters allow specifying ego's color separately from alters' colors -#' when `include_ego = TRUE`. This is helpful for visualizing ego-alter -#' homophily. When `ego_color_var` equals `vertex_color_var`, the same color +#' The `ego_color_var`, `ego_color_palette`, `ego_color_legend_label`, and +#' `ego_label_var` parameters allow specifying ego's color and label separately +#' from alters' colors and labels when `include_ego = TRUE`. This is helpful +#' for visualizing ego-alter homophily. When `ego_color_var` equals `vertex_color_var`, +#' the same color #' mapping is used to ensure consistency. #' #' Available color palettes are: From 1756150ae5ad001801d0e71c20e151961b0468f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:49:04 +0000 Subject: [PATCH 08/17] Move ego_color_* and ego_label_var to immediately after vertex_label_var Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 16 ++++++++-------- R/plot_ego_graph.R | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 04c2b2d..437edcf 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -102,6 +102,10 @@ plot_egograms <- function(x, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, vertex_label_var = "name", + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, edge_width_var = NULL, edge_color_var = NULL, edge_color_palette = "Heat Colors", @@ -115,10 +119,6 @@ plot_egograms <- function(x, venn_gradient_reverse = FALSE, show_venn_labels = TRUE, include_ego = FALSE, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, - ego_label_var = vertex_label_var, ...) { opar <- par(no.readonly = TRUE) on.exit(par(opar)) @@ -178,6 +178,10 @@ plot_egogram <- vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, vertex_label_var = "name", + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, edge_width_var = NULL, edge_color_var = NULL, edge_color_palette = "Heat Colors", @@ -191,10 +195,6 @@ plot_egogram <- venn_gradient_reverse = FALSE, show_venn_labels = TRUE, include_ego = FALSE, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, - ego_label_var = vertex_label_var, ...) { if (!any(c(!is.null(pie_var), !is.null(venn_var)))) diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index 0e2522b..4f8be44 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -9,6 +9,10 @@ plot_ego_graphs <- function(x, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, vertex_label_var = "name", + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, edge_width_var = NULL, ego_alter_edge_width_var = if(!is.null(edge_width_var) & include_ego) edge_width_var, @@ -24,10 +28,6 @@ plot_ego_graphs <- function(x, font_size = 1, include_ego = FALSE, ego_attrs = NULL, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, - ego_label_var = vertex_label_var, ...) { require_igraph(paste(sQuote("egor"),"plotting ego graphs")) opar <- par(no.readonly = TRUE) @@ -79,6 +79,10 @@ plot_one_ego_graph <- function(x, vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, vertex_label_var = "name", + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, edge_width_var = NULL, ego_alter_edge_width_var = edge_width_var, edge_color_var = NULL, @@ -92,10 +96,6 @@ plot_one_ego_graph <- function(x, include_ego = FALSE, ego_attrs = NULL, layout = NULL, - ego_color_var = vertex_color_var, - ego_color_palette = vertex_color_palette, - ego_color_legend_label = ego_color_var, - ego_label_var = vertex_label_var, ...) { x <- slice.egor(activate(x, "ego"), ego_no) From 9693b768486e0d00e45a45686e81397f363eaf2e Mon Sep 17 00:00:00 2001 From: "Pavel N. Krivitsky" Date: Tue, 13 Jan 2026 15:54:15 -0300 Subject: [PATCH 09/17] Roxygenized. --- DESCRIPTION | 2 +- man/as_tibble.egor.Rd | 2 +- man/plot_egor.Rd | 23 +++++++++++++++++++++++ man/rowlist.Rd | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 3cd1209..0da0719 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -55,7 +55,7 @@ Suggests: network, haven VignetteBuilder: knitr -RoxygenNote: 7.3.3 +RoxygenNote: 7.3.3.9000 Roxygen: list(markdown = TRUE) LazyData: true Encoding: UTF-8 diff --git a/man/as_tibble.egor.Rd b/man/as_tibble.egor.Rd index 6d3c6b7..2bb2f32 100644 --- a/man/as_tibble.egor.Rd +++ b/man/as_tibble.egor.Rd @@ -46,7 +46,7 @@ are useful for advanced analysis procedures, e.g. multi-level regressions. \code{\link[tibble:as_tibble]{tibble::as_tibble()}} method for \code{egor} extracts the currently active component (\code{ego}, \code{alter}, or \code{aaties}) table, optionally joining it with the others, dropping any survey design information. -\code{\link[srvyr:as_survey]{srvyr::as_survey()}} method for \code{egor} instead returns a \code{srvyr} \code{\link[srvyr:tbl_svy]{srvyr::tbl_svy}} survey, taking into account any replication due to multiple alters or alter-alter ties incident on each ego. If no design is specified for the egos, then the default design (simple random sample with replacement) is assumed as the starting point. +\code{\link[srvyr:as_survey]{srvyr::as_survey()}} method for \code{egor} instead returns a \code{srvyr} \code{\link[srvyr:tbl_svy]{tbl_svy}} survey, taking into account any replication due to multiple alters or alter-alter ties incident on each ego. If no design is specified for the egos, then the default design (simple random sample with replacement) is assumed as the starting point. \code{as_egos_df()}, \code{as_alters_df()}, \code{as_aaties_df()}, \code{as_egos_survey()}, \code{as_alters_survey()}, and \code{as_aaties_survey()} are convenience functions for the \code{as_tibble()} and \code{as_survey()} methods, activating the corresponding component of the \code{egor} object. } diff --git a/man/plot_egor.Rd b/man/plot_egor.Rd index a2d70d8..f1b2c66 100644 --- a/man/plot_egor.Rd +++ b/man/plot_egor.Rd @@ -21,6 +21,10 @@ plot_egograms( vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, vertex_label_var = "name", + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, edge_width_var = NULL, edge_color_var = NULL, edge_color_palette = "Heat Colors", @@ -47,6 +51,10 @@ plot_ego_graphs( vertex_color_palette = "Heat Colors", vertex_color_legend_label = vertex_color_var, vertex_label_var = "name", + ego_color_var = vertex_color_var, + ego_color_palette = vertex_color_palette, + ego_color_legend_label = ego_color_var, + ego_label_var = vertex_label_var, edge_width_var = NULL, ego_alter_edge_width_var = if (!is.null(edge_width_var) & include_ego) edge_width_var, edge_color_var = NULL, @@ -99,6 +107,14 @@ plot_egor( \item{vertex_label_var}{Name (\code{character}) of alter column. Set this to \code{NULL} to suppress labels.} +\item{ego_color_var}{Name (\code{character}) of ego column to determine ego vertex color. Defaults to \code{vertex_color_var}. Used in combination with \code{include_ego = TRUE} to visualize ego-alter homophily.} + +\item{ego_color_palette}{Name (\code{character}) of color palette for ego vertex. Defaults to \code{vertex_color_palette}. See details for available color palettes.} + +\item{ego_color_legend_label}{Character. Legend label for ego color. Defaults to \code{ego_color_var}.} + +\item{ego_label_var}{Name (\code{character}) of ego column to determine ego vertex label. Defaults to \code{vertex_label_var}. Used in combination with \code{include_ego = TRUE}.} + \item{edge_width_var}{Name (\code{character}) of aatie column.} \item{edge_color_var}{Name (\code{character}) of aatie column.} @@ -147,6 +163,13 @@ plotting engine. "egogram" uses a special layout that places the nodes on a map of (1) concentric circles with (2) subsections, that can be mapped to alter variables. +The \code{ego_color_var}, \code{ego_color_palette}, \code{ego_color_legend_label}, and +\code{ego_label_var} parameters allow specifying ego's color and label separately +from alters' colors and labels when \code{include_ego = TRUE}. This is helpful +for visualizing ego-alter homophily. When \code{ego_color_var} equals \code{vertex_color_var}, +the same color +mapping is used to ensure consistency. + Available color palettes are: \itemize{ \item Heat Colors diff --git a/man/rowlist.Rd b/man/rowlist.Rd index 04d1c9e..0db27af 100644 --- a/man/rowlist.Rd +++ b/man/rowlist.Rd @@ -16,7 +16,7 @@ named \code{\link[=list]{list()}} containing the elements in the corresponding row. } \description{ -A convenience function converting a \code{\link[=data.frame]{data.frame()}} or a \code{\link[tibble:tibble]{tibble::tibble()}}. +A convenience function converting a \code{\link[=data.frame]{data.frame()}} or a \code{\link[tibble:tibble]{tibble()}}. } \examples{ From f14416225953dd31934626685959295f637e36a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 19:16:43 +0000 Subject: [PATCH 10/17] Fix error when data has no aaties and include_ego = TRUE Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 8 +++++++- tests/testthat/test-plot_egor.R | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 437edcf..0f44a61 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -366,7 +366,13 @@ plot_egogram <- # Set curvature of ego-alter ties to zero igraph::E(g)$curved[is.na(igraph::E(g)$curved)] <- 0 # Set ego-alter weights to a dummy value - igraph::E(g)$weight[is.na(igraph::E(g)$weight)] <- min(igraph::E(g)$weight, na.rm = TRUE) + if (any(!is.na(igraph::E(g)$weight))) { + # Set to min of other weights, so scale of weights is comparable + igraph::E(g)$weight[is.na(igraph::E(g)$weight)] <- min(igraph::E(g)$weight, na.rm = TRUE) + } else { + # If all weights are NA (no aaties), set them all to 1 + igraph::E(g)$weight <- 1 + } } # Plot diff --git a/tests/testthat/test-plot_egor.R b/tests/testthat/test-plot_egor.R index 44a1a04..685bb62 100644 --- a/tests/testthat/test-plot_egor.R +++ b/tests/testthat/test-plot_egor.R @@ -135,6 +135,19 @@ test_that("plot_egograms doesn't fail on empty alters or aaties", { show_venn_labels = TRUE ), NA) + + # Test with include_ego = TRUE and empty aaties + expect_error(plot_egograms( + x = e, + ego_no = 1, + venn_var = "sex", + pie_var = "country", + vertex_color_var = "age", + show_venn_labels = TRUE, + include_ego = TRUE + ), + NA) + e <- make_egor(5, 5) e$alter <- e$alter %>% From 46dffd8e327754862a4506bb60102df92bd85d97 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 19:46:05 +0000 Subject: [PATCH 11/17] Update test to use filter(FALSE) for completely empty aaties Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- tests/testthat/test-plot_egor.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-plot_egor.R b/tests/testthat/test-plot_egor.R index 685bb62..5b0c2ee 100644 --- a/tests/testthat/test-plot_egor.R +++ b/tests/testthat/test-plot_egor.R @@ -136,7 +136,11 @@ test_that("plot_egograms doesn't fail on empty alters or aaties", { ), NA) - # Test with include_ego = TRUE and empty aaties + # Test with include_ego = TRUE and NO aaties at all + e <- make_egor(5, 5) + e$aatie <- + e$aatie %>% + filter(FALSE) expect_error(plot_egograms( x = e, ego_no = 1, From b5714d17df30d6d0dc61018be1d5e2760d597413 Mon Sep 17 00:00:00 2001 From: "Pavel N. Krivitsky" Date: Tue, 13 Jan 2026 16:56:33 -0300 Subject: [PATCH 12/17] Make all plot_egograms() tests for empty aaties remove all aaties. --- tests/testthat/test-plot_egor.R | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/testthat/test-plot_egor.R b/tests/testthat/test-plot_egor.R index 5b0c2ee..dbea40a 100644 --- a/tests/testthat/test-plot_egor.R +++ b/tests/testthat/test-plot_egor.R @@ -127,7 +127,7 @@ test_that("plot_egograms doesn't fail on empty alters or aaties", { e <- make_egor(5, 5) e$aatie <- e$aatie %>% - filter(.egoID != 1) + filter(FALSE) expect_error(plot_egograms( x = e, venn_var = "sex", @@ -155,7 +155,7 @@ test_that("plot_egograms doesn't fail on empty alters or aaties", { e <- make_egor(5, 5) e$alter <- e$alter %>% - filter(.egoID != 1) + filter(FALSE) expect_error(plot_egograms( x = e, venn_var = "sex", @@ -169,7 +169,7 @@ test_that("plot_ego_graphs doesn't fail on empty alters or aaties", { e <- make_egor(5, 5) e$aatie <- e$aatie %>% - filter(.egoID != 1) + filter(FALSE) expect_error(plot_ego_graphs( e, ego_id=1, include_ego=F ), @@ -184,7 +184,7 @@ test_that("plot_ego_graphs doesn't fail on empty alters or aaties", { e <- make_egor(5, 5) e$alter <- e$alter %>% - filter(.egoID != 1) + filter(FALSE) expect_error(plot_ego_graphs( e, ego_id=1, include_ego=F @@ -678,4 +678,4 @@ test_that("ego_color parameters default to vertex_color parameters", { }, NA) }) -dev.off() # Closing the NULL pdf device. \ No newline at end of file +dev.off() # Closing the NULL pdf device. From 11c6fc55a7b98a7b40e81a315fb06315ba8c093b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 20:06:03 +0000 Subject: [PATCH 13/17] Fix plot functions to handle empty aaties and alters when include_ego=TRUE Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 43 ++++++++++++++++++++++++------------------- R/plot_ego_graph.R | 25 ++++++++++++++----------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 0f44a61..8c053d5 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -263,16 +263,18 @@ plot_egogram <- # Pieces of the pie plot.new() - pie_add( - rep(1, piece_n), - labels = levels(pie_var), - radius = 1, - clockwise = TRUE, - border = FALSE, - add = TRUE, - col = pie_colors, - cex = font_size - ) + if (piece_n > 0) { + pie_add( + rep(1, piece_n), + labels = levels(pie_var), + radius = 1, + clockwise = TRUE, + border = FALSE, + add = TRUE, + col = pie_colors, + cex = font_size + ) + } # Venns radi <- c(1:(venn_n + 1) / (venn_n + 1)) @@ -363,15 +365,18 @@ plot_egogram <- if(include_ego) { # Place ego in middle of plot lay <- rbind(lay, c(0, 0, 0)) - # Set curvature of ego-alter ties to zero - igraph::E(g)$curved[is.na(igraph::E(g)$curved)] <- 0 - # Set ego-alter weights to a dummy value - if (any(!is.na(igraph::E(g)$weight))) { - # Set to min of other weights, so scale of weights is comparable - igraph::E(g)$weight[is.na(igraph::E(g)$weight)] <- min(igraph::E(g)$weight, na.rm = TRUE) - } else { - # If all weights are NA (no aaties), set them all to 1 - igraph::E(g)$weight <- 1 + # Only set edge attributes if there are edges + if (igraph::ecount(g) > 0) { + # Set curvature of ego-alter ties to zero + igraph::E(g)$curved[is.na(igraph::E(g)$curved)] <- 0 + # Set ego-alter weights to a dummy value + if (any(!is.na(igraph::E(g)$weight))) { + # Set to min of other weights, so scale of weights is comparable + igraph::E(g)$weight[is.na(igraph::E(g)$weight)] <- min(igraph::E(g)$weight, na.rm = TRUE) + } else { + # If all weights are NA (no aaties), set them all to 1 + igraph::E(g)$weight <- 1 + } } } diff --git a/R/plot_ego_graph.R b/R/plot_ego_graph.R index 4f8be44..65d8ee3 100644 --- a/R/plot_ego_graph.R +++ b/R/plot_ego_graph.R @@ -276,17 +276,20 @@ plot_one_ego_graph <- function(x, # Set curvature of ego-alter ties to zero # igraph::E(gr)$curved[is.na(igraph::E(gr)$curved)] <- 0 # Set ego-alter weights to a dummy value - if (any(!is.na(igraph::E(gr)$weight))) { - # Set to min of other weights, so scale of weights is comparable - igraph::E(gr)$weight[is.na(igraph::E(gr)$weight)] <- min(igraph::E(gr)$weight, na.rm = TRUE) - } else { - # no other weights in the graph, so just set a hardwired dummy value - # if there is no weight variable at all, E(gr)$weight will be NULL rather than a vector, - # so the syntax igraph::E(gr)$weight[is.na(igraph::E(gr)$weight)] will fail. Since all weights - # are NULL or NA at this point, set them all to 1. This will change missing aatie weights to 1, - # which may not be desirable, but overwriting missing aatie weights is also the behavior of the - # code above when there is at least one nonmissing aatie weight - igraph::E(gr)$weight <- 1 + # Only set edge attributes if there are edges + if (igraph::ecount(gr) > 0) { + if (any(!is.na(igraph::E(gr)$weight))) { + # Set to min of other weights, so scale of weights is comparable + igraph::E(gr)$weight[is.na(igraph::E(gr)$weight)] <- min(igraph::E(gr)$weight, na.rm = TRUE) + } else { + # no other weights in the graph, so just set a hardwired dummy value + # if there is no weight variable at all, E(gr)$weight will be NULL rather than a vector, + # so the syntax igraph::E(gr)$weight[is.na(igraph::E(gr)$weight)] will fail. Since all weights + # are NULL or NA at this point, set them all to 1. This will change missing aatie weights to 1, + # which may not be desirable, but overwriting missing aatie weights is also the behavior of the + # code above when there is at least one nonmissing aatie weight + igraph::E(gr)$weight <- 1 + } } } From cffa56ba1f1dd708e6203899a261ad83c0842da3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:55:07 +0000 Subject: [PATCH 14/17] Fix plot_egograms to handle empty alters and avoid invalid venn colors - Added check to skip venn ring drawing when there are no alters (fixes invalid hex color error) - Fixed lay rbind to handle empty tibble when no alters and include_ego=TRUE - Prevents division by zero in color sequence generation - Addresses test failures in test-plot_egor.R lines 144 and 159 Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 8c053d5..463906f 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -276,12 +276,14 @@ plot_egogram <- ) } - # Venns - radi <- c(1:(venn_n + 1) / (venn_n + 1)) - cols <- paste0("#ffffff", format(as.hexmode(round(seq(0, 220, 220 / venn_n))))) - if(venn_gradient_reverse) cols <- rev(cols) - for(i in 1:venn_n) { - ring(0, 0, radi[i+1], radi[i], col = cols[i], border = "grey70") + # Venns - only draw if there are alters + if (nrow(ego_object$alter) > 0 && venn_n > 0) { + radi <- c(1:(venn_n + 1) / (venn_n + 1)) + cols <- paste0("#ffffff", format(as.hexmode(round(seq(0, 220, 220 / venn_n))))) + if(venn_gradient_reverse) cols <- rev(cols) + for(i in 1:venn_n) { + ring(0, 0, radi[i+1], radi[i], col = cols[i], border = "grey70") + } } # plotrix::draw.circle(0, 0, c(1:(venn_n + 1) / (venn_n + 1)), @@ -364,7 +366,13 @@ plot_egogram <- if(include_ego) { # Place ego in middle of plot - lay <- rbind(lay, c(0, 0, 0)) + if (nrow(lay) > 0) { + lay <- rbind(lay, c(0, 0, 0)) + } else { + # If no alters, create a layout with just the ego + lay <- tibble::tibble(.altID = character(0), x = numeric(0), y = numeric(0)) + lay <- rbind(lay, tibble::tibble(.altID = ".ego", x = 0, y = 0)) + } # Only set edge attributes if there are edges if (igraph::ecount(g) > 0) { # Set curvature of ego-alter ties to zero From edf7b24effd139500cd9a5650f7c5061bf1ada10 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:05:05 +0000 Subject: [PATCH 15/17] Fix rbind issue with factor column when adding ego to layout - Changed from rbind(lay, c(0, 0, 0)) to properly create tibble row with factor - Ensures .altID factor levels are compatible when combining rows - Prevents "invalid factor level, NA generated" warning - Addresses test failure at test-plot_egor.R:144 Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 463906f..856ff61 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -367,11 +367,13 @@ plot_egogram <- if(include_ego) { # Place ego in middle of plot if (nrow(lay) > 0) { - lay <- rbind(lay, c(0, 0, 0)) + # Add ego to layout using proper tibble row binding + ego_row <- tibble::tibble(.altID = factor(".ego", levels = c(levels(lay$.altID), ".ego")), + x = 0, y = 0) + lay <- rbind(lay, ego_row) } else { # If no alters, create a layout with just the ego - lay <- tibble::tibble(.altID = character(0), x = numeric(0), y = numeric(0)) - lay <- rbind(lay, tibble::tibble(.altID = ".ego", x = 0, y = 0)) + lay <- tibble::tibble(.altID = factor(".ego"), x = 0, y = 0) } # Only set edge attributes if there are edges if (igraph::ecount(g) > 0) { From 36b0a6bf9b990df9bbf14de00b6d8b9b62ec2a41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:28:12 +0000 Subject: [PATCH 16/17] Fix edge attribute assignment to avoid igraph subset assignment issues - Changed from subset assignment E(g)$curved[NA] <- 0 to full vector assignment - Extract attribute values, modify them, then assign back - Prevents "Length of new attribute value" error from igraph - Addresses test failure at test-plot_egor.R:144 Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index 856ff61..ea99b74 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -378,11 +378,19 @@ plot_egogram <- # Only set edge attributes if there are edges if (igraph::ecount(g) > 0) { # Set curvature of ego-alter ties to zero - igraph::E(g)$curved[is.na(igraph::E(g)$curved)] <- 0 + curved_vals <- igraph::E(g)$curved + if (is.null(curved_vals) || all(is.na(curved_vals))) { + igraph::E(g)$curved <- 0 + } else { + curved_vals[is.na(curved_vals)] <- 0 + igraph::E(g)$curved <- curved_vals + } # Set ego-alter weights to a dummy value if (any(!is.na(igraph::E(g)$weight))) { # Set to min of other weights, so scale of weights is comparable - igraph::E(g)$weight[is.na(igraph::E(g)$weight)] <- min(igraph::E(g)$weight, na.rm = TRUE) + weight_vals <- igraph::E(g)$weight + weight_vals[is.na(weight_vals)] <- min(weight_vals, na.rm = TRUE) + igraph::E(g)$weight <- weight_vals } else { # If all weights are NA (no aaties), set them all to 1 igraph::E(g)$weight <- 1 From 2a3b57eaaf5e77dff9de73e8cf852d6b2c9d0a99 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:40:56 +0000 Subject: [PATCH 17/17] Fix edge attribute assignment when attribute is missing or empty - Check for length(curved_vals) == 0 in addition to NULL and all NA - Use rep(0, igraph::ecount(g)) to create proper length vector - Ensures edge attributes are correctly assigned when attribute doesn't exist - Addresses test failures at test-plot_egor.R:144 and test-plot_egor.R:659 Co-authored-by: krivit <15682462+krivit@users.noreply.github.com> --- R/plot_ego_gram.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/plot_ego_gram.R b/R/plot_ego_gram.R index ea99b74..77e7aa9 100644 --- a/R/plot_ego_gram.R +++ b/R/plot_ego_gram.R @@ -379,8 +379,8 @@ plot_egogram <- if (igraph::ecount(g) > 0) { # Set curvature of ego-alter ties to zero curved_vals <- igraph::E(g)$curved - if (is.null(curved_vals) || all(is.na(curved_vals))) { - igraph::E(g)$curved <- 0 + if (is.null(curved_vals) || length(curved_vals) == 0 || all(is.na(curved_vals))) { + igraph::E(g)$curved <- rep(0, igraph::ecount(g)) } else { curved_vals[is.na(curved_vals)] <- 0 igraph::E(g)$curved <- curved_vals