Skip to content

v1.7.1#124

Merged
jhollway merged 24 commits intomainfrom
develop
Feb 18, 2026
Merged

v1.7.1#124
jhollway merged 24 commits intomainfrom
develop

Conversation

@jhollway
Copy link
Collaborator

@jhollway jhollway commented Feb 17, 2026

Description

Patch release focused on multiplex network handling, projection improvements, and utility functions.

Package

  • Restructured website
  • Removed unnecessary global variables
  • Exporting expect_nodes() and expect_ties() for use in other packages

Making

  • Added net_name() for obtaining network name if available
  • Added net_node_names() and net_tie_names() for network element information
  • Fixed write_graphml() to coerce to igraph first

Modifying

  • Improved to_mode1() and to_mode2() to carry forward nodal and tie attributes during projection
  • Improved to_mode1() and to_mode2() to drop unnecessary nodal information
  • Improved to_uniplex() to handle multimodal multiplex filtering correctly and retain tie type information
  • Fixed Unable to write networkDynamic object to a graphML object using write_graphML function #123 by inserting NAs before converting networkDynamic to igraph
  • Fixed add_changes() to work with tbl_graph
  • Fixed filter_nodes() to use dplyr::all_of()
  • Added interpolate() helper for injecting missing data
  • Restructured modifying function documentation around transformations (e.g. direction)

Measuring

  • Split measure_attributes documentation into separate nodes and ties pages

Motifs

  • Fixed net_by_mixed() to work with multiplex networks

Data

  • Compiled ison_marvel_relationships and ison_marvel_teams into single multiplex fict_marvel dataset

Checklist:

  • Documentation
    • DESCRIPTION file version is bumped by the appropriate increment (major, minor, patch)
    • Date in DESCRIPTION is correct
    • Longer functions are commented inline or broken down into helper functions to help debugging
  • PR form
    • Title indicates expected version number
    • PR description above and the NEWS.md file are aligned
    • Description above itemizes changes under subsection titles, e.g. "## Data""
    • Closed, fixed, or related issues are referenced and explained in the description above, e.g. "Fixed #0 by adding A"

…rrectly and add info about the retained tie type
Copilot AI review requested due to automatic review settings February 17, 2026 20:15
@jhollway jhollway self-assigned this Feb 17, 2026
@jhollway
Copy link
Collaborator Author

@copilot, can you summarise the changes in this PR in the style of previous PR descriptions in this repository?

Copilot AI mentioned this pull request Feb 17, 2026
7 tasks
Copy link
Contributor

Copilot AI commented Feb 17, 2026

@jhollway I've opened a new pull request, #125, to work on those changes. Once the pull request is ready, I'll request review from you.

@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 76.52174% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.16%. Comparing base (44508be) to head (421eca9).
⚠️ Report is 34 commits behind head on main.

Files with missing lines Patch % Lines
R/manip_format.R 79.24% 11 Missing ⚠️
R/manip_nodes.R 25.00% 6 Missing ⚠️
R/manip_as.R 0.00% 5 Missing ⚠️
R/motif_census.R 40.00% 3 Missing ⚠️
R/make_read.R 0.00% 1 Missing ⚠️
R/measure_attributes.R 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #124      +/-   ##
==========================================
+ Coverage   56.74%   57.16%   +0.41%     
==========================================
  Files          45       45              
  Lines        5912     5955      +43     
==========================================
+ Hits         3355     3404      +49     
+ Misses       2557     2551       -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prepares the manynet v1.7.1 release by refactoring several API/documentation groupings (directionality + attribute helpers), updating examples/tests to use the new fict_marvel multiplex dataset, and adding a few new helpers and exports.

Changes:

  • Replace Marvel examples/tests/docs with fict_marvel and enhance net_by_mixed() to optionally accept a single multiplex input.
  • Split node vs tie attribute documentation (and add tie_is_twomode()), and add new network metadata helpers (net_name(), net_*_names()).
  • Refactor directionality “to_*” functions into a new manip_direction documentation group and update pkgdown reference indexing.

Reviewed changes

Copilot reviewed 70 out of 73 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
tests/testthat/test-motif_census.R Updates mixed census tests to use fict_marvel uniplex layers.
tests/testthat/test-motif_brokerage.R Updates brokerage tests to use fict_marvel affiliation layer.
tests/testthat/test-measure_heterogeneity.R Updates diversity test to use fict_marvel relationship layer.
tests/testthat/test-manip_transform.R Updates transform tests to use fict_marvel relationship layer.
tests/testthat/test-manip_split.R Updates components test to use fict_marvel relationship layer.
tests/testthat/test-manip_format.R Adds assertions for is_twomode() on fict_actually layers.
tests/testthat/test-manip_as.R Adds (commented) dynamic network conversion test scaffold.
pkgdown/_pkgdown.yml Reorganizes reference index entries (direction group + measure attributes listing).
man/motif_net.Rd Updates motif example to net_by_mixed(fict_marvel).
man/member_diffusion.Rd Updates “Other measures” links from measure_attributes to nodes/ties pages.
man/measure_properties.Rd Documents new net_name(), net_node_names(), net_tie_names() helpers.
man/measure_periods.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_holes.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_hierarchy.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_heterogeneity.Rd Updates examples/links to use fict_marvel + nodes/ties links.
man/measure_features.Rd Updates example to fict_marvel + nodes/ties links.
man/measure_diffusion_node.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_diffusion_net.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_diffusion_infection.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_cohesion.Rd Updates Marvel examples to fict_marvel + nodes/ties links.
man/measure_closure.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_central_eigen.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_central_degree.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_central_close.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_central_between.Rd Updates “Other measures” links to nodes/ties pages.
man/measure_attributes_nodes.Rd Renames/splits old measure_attributes help topic into nodes-focused page.
man/measure_attributes_ties.Rd New ties-focused attribute help topic (incl. tie_is_twomode()).
man/mark_triangles.Rd Updates example to fict_marvel relationship layer.
man/mark_ties.Rd Updates examples to use fict_marvel.
man/manip_ties.Rd Adds manip_direction to “Other modifications” cross-links.
man/manip_split.Rd Updates example + adds manip_direction to cross-links.
man/manip_scope.Rd Adds manip_direction to cross-links.
man/manip_reformat.Rd Removes direction-related aliases now documented under manip_direction.
man/manip_project.Rd Adds manip_direction to cross-links.
man/manip_preformat.Rd Removes to_directed() mention + adds manip_direction cross-link.
man/manip_permutation.Rd Adds manip_direction to cross-links.
man/manip_paths.Rd Adds manip_direction to cross-links.
man/manip_nodes.Rd Adds manip_direction to cross-links.
man/manip_miss.Rd Adds manip_direction to cross-links.
man/manip_levels.Rd Adds manip_direction to cross-links.
man/manip_from.Rd Adds manip_direction to cross-links.
man/manip_direction.Rd New documentation page for directionality formatting functions.
man/manip_deformat.Rd Removes to_undirected() alias + adds manip_direction cross-link.
man/manip_correlation.Rd Adds manip_direction to cross-links.
man/manip_as.Rd Adds manip_direction to cross-links.
man/fict_marvel.Rd Adds new multiplex Marvel dataset documentation.
man/expect.Rd Adds internal documentation for expect_nodes() / expect_ties().
data/fict_marvel.rda Adds the new multiplex Marvel dataset.
R/zzz.R Tweaks startup tip strings.
R/reexports_classes.R Exports expect_nodes()/expect_ties() and adds roxygen entry.
R/motif_census.R Enhances net_by_mixed() (multiplex single-arg support + auto-unsigned signed inputs).
R/measure_properties.R Adds net_name(), net_node_names(), net_tie_names() and exports them.
R/measure_heterogeneity.R Updates examples to use fict_marvel.
R/measure_features.R Updates examples to use fict_marvel.
R/measure_cohesion.R Updates examples to use fict_marvel.
R/measure_centrality.R Removes redundant roxygen import line.
R/measure_attributes.R Splits node vs tie attribute docs and adds tie_is_twomode().
R/mark_ties.R Switches missing-arg context checker to expect_ties() and updates examples.
R/manynet-utils.R Adds edges/type globals and introduces interpolate() helper.
R/manip_ties.R Removes local NSE “NULL bindings” (relying on globalVariables instead).
R/manip_split.R Updates example to fict_marvel.
R/manip_reformed.R Adjusts projection methods to carry over metadata and node attributes.
R/manip_nodes.R Changes filter_nodes() .by handling and updates add_changes() to use interpolate().
R/manip_format.R Adds new manip_direction family and refactors directionality functions/docs.
R/manip_as.R Makes as_igraph.networkDynamic() robust to missing active spells.
R/make_read.R Ensures write_graphml() writes an igraph via as_igraph().
R/data_fict.R Replaces Marvel dataset documentation target with fict_marvel.
R/class_networks.R Removes the old net_name() definition (moved to measure helpers).
NAMESPACE Exports new helpers (expect_*, net_name, net_*_names, tie_is_twomode) and imports igraph::graph_attr.
DESCRIPTION Bumps version/date to 1.7.1 / 2026-02-17.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +102 to +105
if(!is.null(net_name(.data))) out <- out %>%
add_info(name = net_name(.data, prefix = "Projection of"))
if(!is.null(net_tie_names(.data))) out <- out %>%
add_info(ties = paste0("co-", net_tie_names(.data)))
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!is.null(net_name(.data))) will always be TRUE because net_name() returns an empty string when no name exists (never NULL). This will add info like "Projection of " with a missing name. Consider having net_name() return NULL when unnamed, or change the condition to check for a non-empty string (e.g., nzchar(net_name(.data))).

Suggested change
if(!is.null(net_name(.data))) out <- out %>%
add_info(name = net_name(.data, prefix = "Projection of"))
if(!is.null(net_tie_names(.data))) out <- out %>%
add_info(ties = paste0("co-", net_tie_names(.data)))
if(!is.null(net_name(.data))) out <- out %>%
add_info(name = net_name(.data, prefix = "Projection of"))
tie_names <- net_tie_names(.data)
if(!is.null(tie_names) && nzchar(tie_names)) out <- out %>%
add_info(ties = paste0("co-", tie_names))

Copilot uses AI. Check for mistakes.
Comment on lines +124 to +126
net_node_names <- function(.data){
igraph::graph_attr(.data, "nodes")
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net_node_names() reads igraph::graph_attr(.data, "nodes") without coercing to igraph. This will fail for manynet-consistent inputs that aren't igraph/tbl_graph (e.g., matrices, edgelists, network). To match the rest of the net_*() helpers, consider using igraph::graph_attr(as_igraph(.data), "nodes") (and likewise for tie names).

Copilot uses AI. Check for mistakes.
#' net_tie_names(ison_algebra)
#' @export
net_tie_names <- function(.data){
igraph::graph_attr(.data, "ties")
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net_tie_names() reads igraph::graph_attr(.data, "ties") without coercing to igraph, so it will error for non-igraph inputs despite the package generally accepting multiple network classes. Consider igraph::graph_attr(as_igraph(.data), "ties") for consistency.

Suggested change
igraph::graph_attr(.data, "ties")
igraph::graph_attr(as_igraph(.data), "ties")

Copilot uses AI. Check for mistakes.
Comment on lines +458 to +463
if(is_twomode(out) && all(!tie_is_twomode(out))){ # if only one-mode left
retain <- node_is_mode(out)[igraph::as_edgelist(out, names = FALSE)[1,1]]
out <- tidygraph::activate(out, "nodes") %>%
filter_nodes(type == retain) %>%
mutate_nodes(type = NULL)
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_uniplex.tbl_graph() can error on empty results: when the filtered graph has 0 ties, tie_is_twomode(out) returns logical(0) and all(!tie_is_twomode(out)) is TRUE, so the code enters the branch and then indexes igraph::as_edgelist(out)[1,1], which fails. Add a guard like net_ties(out) > 0 (and/or validate that the requested tie exists) before accessing the first edge.

Copilot uses AI. Check for mistakes.
Comment on lines +449 to +450
object2 <- to_uniplex(.data, unique(manynet::tie_attribute(.data, "type"))[2])
.data <- to_uniplex(.data, unique(manynet::tie_attribute(.data, "type"))[1])
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The multiplex convenience branch chooses tie types using unique(tie_attribute(.data, "type"))[1:2], which depends on edge ordering and silently ignores cases with >2 tie types (or errors if there’s only 1). This can easily select the wrong pair (e.g., pick a two-mode layer as .data), causing confusing errors later. Consider explicitly validating the number of tie types and selecting the one-mode vs two-mode layers by checking is_twomode(to_uniplex(.data, type)) (and erroring with a clear message when the multiplex structure isn't supported).

Suggested change
object2 <- to_uniplex(.data, unique(manynet::tie_attribute(.data, "type"))[2])
.data <- to_uniplex(.data, unique(manynet::tie_attribute(.data, "type"))[1])
tie_types <- unique(manynet::tie_attribute(.data, "type"))
if (length(tie_types) != 2L) {
snet_abort("When .data is multiplex and object2 is missing, the network must have exactly two tie types (one one-mode and one two-mode layer).")
}
uniplex_nets <- lapply(tie_types, function(t) manynet::to_uniplex(.data, t))
is_twomode_flags <- vapply(uniplex_nets, manynet::is_twomode, logical(1))
if (sum(is_twomode_flags) != 1L) {
snet_abort("Multiplex network must contain exactly one two-mode layer and one one-mode layer to infer object2 automatically.")
}
object2 <- uniplex_nets[[which(is_twomode_flags)]]
.data <- uniplex_nets[[which(!is_twomode_flags)]]

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +44
existname <- ""
if(!is.null(igraph::graph_attr(.data, "name"))) {
existname <- igraph::graph_attr(.data, 'name')
} else if(is_grand(.data) &&
!is.null(igraph::graph_attr(.data, "grand")$name)){
existname <- igraph::graph_attr(.data, 'grand')$name
}
if(existname != "" && !is.null(prefix)) existname <- paste(prefix, existname)
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net_name() calls igraph::graph_attr() on .data directly and always returns a string ("" when missing). For non-igraph inputs (matrix, data.frame, network) this will error, and the return type makes is.null(net_name(...)) checks ineffective elsewhere. Consider coercing via as_igraph(.data) and returning NULL when no name attribute exists (or document that it only supports igraph/tbl_graph).

Suggested change
existname <- ""
if(!is.null(igraph::graph_attr(.data, "name"))) {
existname <- igraph::graph_attr(.data, 'name')
} else if(is_grand(.data) &&
!is.null(igraph::graph_attr(.data, "grand")$name)){
existname <- igraph::graph_attr(.data, 'grand')$name
}
if(existname != "" && !is.null(prefix)) existname <- paste(prefix, existname)
g <- as_igraph(.data)
existname <- igraph::graph_attr(g, "name")
if (is.null(existname) && is_grand(.data)) {
grand_attr <- igraph::graph_attr(g, "grand")
if (!is.null(grand_attr) && !is.null(grand_attr$name)) {
existname <- grand_attr$name
}
}
if (is.null(existname) || !nzchar(existname)) {
return(NULL)
}
if (!is.null(prefix)) {
existname <- paste(prefix, existname)
}

Copilot uses AI. Check for mistakes.
Comment on lines +117 to +123
tie_is_twomode <- function(.data){
if(is_twomode(.data)){
el <- igraph::as_edgelist(.data, names = FALSE)
el[,1] <- node_is_mode(.data)[el[,1]]
el[,2] <- node_is_mode(.data)[el[,2]]
out <- el[,1] != el[,2]
} else out <- rep(FALSE, net_ties(.data))
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tie_is_twomode() calls igraph::as_edgelist(.data, ...) on .data directly. This will error for non-igraph inputs (e.g., matrix, edgelist data.frame, network) even though the function is documented for manynet-consistent classes. Coerce once via g <- as_igraph(.data) and work with g for the edgelist and tie count.

Copilot uses AI. Check for mistakes.
Title: Many Ways to Make, Modify, Mark, and Measure Myriad Networks
Version: 1.7.0
Date: 2025-11-19
Version: 1.7.1
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version/date are bumped for a 1.7.1 release, but there is no corresponding 1.7.1 entry in NEWS.md. If this PR is intended to cut v1.7.1, NEWS.md should be updated to summarize user-visible changes so the package changelog stays consistent with the release metadata.

Suggested change
Version: 1.7.1
Version: 1.7.0

Copilot uses AI. Check for mistakes.
Comment on lines +448 to +451
if(missing(object2) && manynet::is_multiplex(.data)) {
object2 <- to_uniplex(.data, unique(manynet::tie_attribute(.data, "type"))[2])
.data <- to_uniplex(.data, unique(manynet::tie_attribute(.data, "type"))[1])
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net_by_mixed() now supports being called with a single multiplex object (auto-splitting into one-mode and two-mode layers), but the test suite only covers the two-argument form. Add a test that calls net_by_mixed(fict_marvel) (or another multiplex example) and asserts it returns the expected motif counts so this new code path stays covered.

Copilot uses AI. Check for mistakes.
Comment on lines +118 to +123
if(is_twomode(.data)){
el <- igraph::as_edgelist(.data, names = FALSE)
el[,1] <- node_is_mode(.data)[el[,1]]
el[,2] <- node_is_mode(.data)[el[,2]]
out <- el[,1] != el[,2]
} else out <- rep(FALSE, net_ties(.data))
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tie_is_twomode() is a new exported helper with non-trivial logic (mode detection + per-edge classification), but there are no tests covering it. Consider adding tests (similar to existing tie attribute tests) that verify it returns all TRUE for a known two-mode network and all FALSE for a one-mode network, plus a mixed-edge case if supported.

Suggested change
if(is_twomode(.data)){
el <- igraph::as_edgelist(.data, names = FALSE)
el[,1] <- node_is_mode(.data)[el[,1]]
el[,2] <- node_is_mode(.data)[el[,2]]
out <- el[,1] != el[,2]
} else out <- rep(FALSE, net_ties(.data))
.data <- as_igraph(.data)
if(is_twomode(.data)){
el <- igraph::as_edgelist(.data, names = FALSE)
modes <- node_is_mode(.data)
out <- modes[el[,1]] != modes[el[,2]]
} else {
out <- rep(FALSE, net_ties(.data))
}

Copilot uses AI. Check for mistakes.
@jhollway jhollway merged commit dae28a5 into main Feb 18, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to write networkDynamic object to a graphML object using write_graphML function

3 participants