diff --git a/.github/workflows/pushrelease.yml b/.github/workflows/pushrelease.yml index 9e92356b..cee4b41a 100644 --- a/.github/workflows/pushrelease.yml +++ b/.github/workflows/pushrelease.yml @@ -61,18 +61,20 @@ jobs: path: build/ - name: Calculate code coverage + if: runner.os == 'macOS-latest' run: Rscript -e "covr::codecov()" release: name: Bump version and release if: ${{ always() }} needs: build + if: github.event.pull_request.merged == true runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout one - uses: actions/checkout@master + uses: actions/checkout@v4 with: fetch-depth: '0' - name: Bump version and push tag @@ -84,24 +86,16 @@ jobs: DEFAULT_BUMP: patch RELEASE_BRANCHES: main - name: Checkout two - uses: actions/checkout@v2 - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ steps.newtag.outputs.tag }} - release_name: Release ${{ steps.newtag.outputs.tag }} - draft: false - prerelease: false + uses: actions/checkout@v4 + + - name: Extract version + run: | + echo "PACKAGE_VERSION=$(grep '^Version' DESCRIPTION | sed 's/.*: *//')" >> $GITHUB_ENV + echo "PACKAGE_NAME=$(grep '^Package' DESCRIPTION | sed 's/.*: *//')" >> $GITHUB_ENV - name: Download binaries uses: actions/download-artifact@v4 - - name: Display structure of downloaded files - run: ls -R - - name: Rename binaries release shell: bash run: | @@ -111,9 +105,9 @@ jobs: cp ./winOS/${{ env.PACKAGE_NAME }}_${{ env.PACKAGE_VERSION }}*.zip . echo "Renamed files" ls manynet_* - + - name: Create Release and Upload Assets - id: upload_release + id: create_release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.newtag.outputs.tag }} @@ -127,7 +121,7 @@ jobs: manynet_*.tar.gz manynet_*.zip env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} pkgdown: name: Build and deploy website diff --git a/DESCRIPTION b/DESCRIPTION index 73d420e7..b17a0e9f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: manynet Title: Many Ways to Make, Modify, Map, Mark, and Measure Myriad Networks -Version: 1.1.0 -Date: 2024-09-12 +Version: 1.2.0 +Date: 2024-09-28 Description: Many tools for making, modifying, mapping, marking, measuring, and motifs and memberships of many different types of networks. All functions operate with matrices, edge lists, and 'igraph', 'network', and 'tidygraph' objects, @@ -41,7 +41,6 @@ Suggests: methods, multiplex, netdiffuseR, - oaqc, patchwork, readxl, rmarkdown, diff --git a/NAMESPACE b/NAMESPACE index 9671e0bb..bb376eaf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -138,8 +138,10 @@ S3method(plot,diffs_model) S3method(plot,learn_model) S3method(plot,matrix) S3method(plot,network_measures) +S3method(plot,network_motif) S3method(plot,node_measure) S3method(plot,node_member) +S3method(plot,node_motif) S3method(plot,tie_measure) S3method(print,diff_model) S3method(print,diffs_model) @@ -296,6 +298,7 @@ export("%>%") export(.E) export(.G) export(.N) +export(add_info) export(add_node_attribute) export(add_nodes) export(add_tie_attribute) @@ -321,10 +324,12 @@ export(cluster_hierarchical) export(create_components) export(create_core) export(create_degree) +export(create_ego) export(create_empty) export(create_explicit) export(create_filled) export(create_lattice) +export(create_motifs) export(create_ring) export(create_star) export(create_tree) @@ -406,6 +411,7 @@ export(net_betweenness) export(net_by_brokerage) export(net_by_dyad) export(net_by_mixed) +export(net_by_quad) export(net_by_triad) export(net_change) export(net_closeness) @@ -509,6 +515,7 @@ export(network_upperbound) export(node_adoption_time) export(node_alpha) export(node_attribute) +export(node_authority) export(node_automorphic_equivalence) export(node_betweenness) export(node_bridges) @@ -517,6 +524,7 @@ export(node_brokering) export(node_brokering_activity) export(node_brokering_exclusivity) export(node_by_brokerage) +export(node_by_dyad) export(node_by_exposure) export(node_by_path) export(node_by_quad) @@ -537,6 +545,7 @@ export(node_efficiency) export(node_effsize) export(node_eigenvector) export(node_equivalence) +export(node_equivalency) export(node_exposure) export(node_fast_greedy) export(node_flow) @@ -544,6 +553,7 @@ export(node_fluid) export(node_harmonic) export(node_heterophily) export(node_hierarchy) +export(node_hub) export(node_in_adopter) export(node_in_automorphic) export(node_in_betweenness) @@ -665,6 +675,7 @@ export(scale_fill_sdgs) export(scale_fill_uzh) export(scale_size) export(select_ties) +export(set_manynet_theme) export(summarise_ties) export(table_data) export(theme_ethz) @@ -909,7 +920,6 @@ importFrom(stats,cor) importFrom(stats,cutree) importFrom(stats,hclust) importFrom(stats,median) -importFrom(tidygraph,"%E>%") importFrom(tidygraph,.E) importFrom(tidygraph,.G) importFrom(tidygraph,.N) diff --git a/NEWS.md b/NEWS.md index 063489ec..89554636 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,61 @@ +# manynet 1.2.0 + +## Package + +- Added progress updates, information, and unavailability errors to several functions + - These can be silenced by setting `options(manynet_verbosity ="quiet")` + - Where a feature is unavailable, users are directed to the Github issues page +- Added console theme to color the startup and various warning or info messages + +## Making + +- Added `create_ego()` for collecting ego networks through interviews, including arguments for: + - Indicating whether a roster should be used, otherwise follows a name generator approach + - Indicating whether nodes should be interpreted, i.e. nodal attributes collected + - Indicating whether ties between alters should be requested +- Added `create_motifs()` for creating networks that correspond to the isomorphic subgraphs of certain size and format + +## Modifying + +- Improved `print.mnet()` + - Prints multiplex types if available + - Prints both nodesets for two-mode networks +- Added `add_info()` for adding grand info to tidygraph objects + - This includes the name of the network, node sets and ties, DOI, year and mode of collection +- Fixed `to_unweighted()` so that it passes through unweighted networks correctly + +## Mapping + +- Added `set_manynet_theme()` to set theme (re #60), but not yet fully implemented + +## Marking + +- Improved `is_multiplex()` to ignore "name" tie attributes + +## Measuring + +- Added `node_authority()` and `node_hub()` centrality measures +- Added `node_equivalency()` for calculating four-cycle closure by node +- Extended `net_equivalency()` to one-mode networks + +## Members + +- Fixed `node_in_equivalence()` to use census directly + +## Motifs + +- Added plot methods for network_motif and node_motif classes that use `create_motifs()` +- Added `node_by_dyad()` for node level dyad census +- Added `net_by_quad()` for network level quad census +- Fixed `node_by_quad()` to avoid `{oaqc}` dependency (#89), more flexible but slower +- Fixed `print.node_motif()` to convert to tibble and add modes and names where available only upon print + - The underlying object is still a matrix, used for equivalence and blockmodelling + +## Data + +- Updated `ison_southern_women` with grand info +- Updated `ison_laterals` with reordered nodes + # manynet 1.1.0 ## Package @@ -98,7 +156,7 @@ - `table_data()` can now report on data from multiple packages - `{manynet}` and `{migraph}` are included by default, and if any are not installed they are just ignored -- `tabe_data()` can now filter by any reported formats, +- `table_data()` can now filter by any reported formats, such as 'directed' or 'twomode' ## Website @@ -198,7 +256,7 @@ including force-directed, layered, circular, spectral, and grid layouts existing network was incorrect - Added `generate_configuration()` for generating configuration models (including for two-mode networks) -- `play_diffuson()` now includes an explicit contact argument to control the +- `play_diffusion()` now includes an explicit contact argument to control the basis of exposure ## Marking @@ -277,7 +335,7 @@ and `node_is_infected()` (closes #71) `net_balance()`, `net_change()`, and `net_stability()` - Updated properties from mapping to measuring - Updated attributes from mapping to measuring - - Renamed `node_mode()` (deprecated) to node_is_mode() since it returns a + - Renamed `node_mode()` (deprecated) to `node_is_mode()` since it returns a logical vector - Updated `node_attribute()` and `tie_attribute()` to return measures when the output is numeric diff --git a/R/class_motifs.R b/R/class_motifs.R index d20faf6a..12e68465 100644 --- a/R/class_motifs.R +++ b/R/class_motifs.R @@ -1,6 +1,7 @@ make_node_motif <- function(out, .data) { class(out) <- c("node_motif", class(out)) - attr(out, "mode") <- node_is_mode(.data) + if(is_twomode(.data)) attr(out, "mode") <- node_is_mode(.data) + if(is_labelled(.data)) attr(out, "dimnames")[[1]] <- node_names(.data) out } @@ -14,17 +15,55 @@ make_network_motif <- function(out, .data) { print.node_motif <- function(x, ..., n = 6, digits = 3) { - if(!is.null(attr(x, "dimnames")[[1]])){ - x <- data.frame(names = attr(x, "dimnames")[[1]], x) - } if (any(attr(x, "mode"))) { - print(dplyr::tibble(as.data.frame(x)[!attr(x, "mode")]), n = n) - print(dplyr::tibble(as.data.frame(x)[attr(x, "mode")]), n = n) + y <- as.data.frame(x[!attr(x, "mode"),]) + z <- as.data.frame(x[attr(x, "mode"),]) + if(!is.null(attr(x, "dimnames")[[1]])){ + y <- data.frame(names = attr(x, "dimnames")[[1]][!attr(x, "mode")], y) + z <- data.frame(names = attr(x, "dimnames")[[1]][attr(x, "mode")], z) + } + print(dplyr::tibble(y), n = n) + print(dplyr::tibble(z), n = n) } else { - print(dplyr::tibble(as.data.frame(x)), n = n) + if(!is.null(attr(x, "dimnames")[[1]])){ + x <- data.frame(names = attr(x, "dimnames")[[1]], x) + } else x <- as.data.frame(x) + print(dplyr::tibble(x), n = n) } } +#' @export +plot.node_motif <- function(x, ...) { + motifs <- dimnames(x)[[2]] + if("X4" %in% motifs){ + graphs(create_motifs(4), waves = 1:11) + } else if("021D" %in% motifs){ + graphs(create_motifs(3, directed = TRUE), waves = 1:16) + } else if("102" %in% motifs){ + graphs(create_motifs(3), waves = 1:4) + } else if("Asymmetric" %in% motifs){ + graphs(create_motifs(2, directed = TRUE), waves = 1:3) + } else if("Mutual" %in% motifs){ + graphs(create_motifs(2), waves = 1:2) + } else mnet_unavailable("Cannot plot these motifs yet, sorry.") +} + +#' @export +plot.network_motif <- function(x, ...) { + motifs <- dimnames(x)[[2]] + if("X4" %in% motifs){ + graphs(create_motifs(4), waves = 1:11) + } else if("021D" %in% motifs){ + graphs(create_motifs(3, directed = TRUE), waves = 1:16) + } else if("102" %in% motifs){ + graphs(create_motifs(3), waves = 1:4) + } else if("Asymmetric" %in% motifs){ + graphs(create_motifs(2, directed = TRUE), waves = 1:3) + } else if("Mutual" %in% motifs){ + graphs(create_motifs(2), waves = 1:2) + } else mnet_unavailable("Cannot plot these motifs yet, sorry.") +} + # summary(node_by_triad(mpn_elite_mex), # membership = node_regular_equivalence(mpn_elite_mex, "elbow")) #' @export diff --git a/R/class_networks.R b/R/class_networks.R index c4947365..885256d0 100644 --- a/R/class_networks.R +++ b/R/class_networks.R @@ -6,22 +6,23 @@ print.mnet <- function(x, ..., n = 6) { arg_list <- list(...) arg_list[['useS4']] <- NULL + if(is_grand(x) && !is.null(igraph::graph_attr(x, "grand")$name)) + cli::cli_text("# {igraph::graph_attr(x, 'grand')$name}") graph_desc <- describe_graph(x) + tie_desc <- describe_ties(x) + node_desc <- describe_nodes(x) + cli::cli_text("# {graph_desc} network of {node_desc} and {tie_desc}") top <- dplyr::as_tibble(tidygraph::activate(x, "nodes")) bottom <- dplyr::as_tibble(tidygraph::activate(x, "edges")) - if(is.null(igraph::graph_attr(x, "grand"))) node_name <- "nodes" else - node_name <- igraph::graph_attr(x, "grand")$vertex1 - if(is.null(igraph::graph_attr(x, "grand"))) - tie_name <- ifelse(is_directed(x), "arcs", "ties") else - tie_name <- paste(igraph::graph_attr(x, "grand")$edge.pos, - ifelse(is_directed(x), "arcs", "ties")) - cat('#', graph_desc, 'network of', igraph::gorder(x), node_name, 'and', - igraph::gsize(x), tie_name, '\n', sep = ' ') if (ncol(top)>0) print(top, n = n) if (ncol(bottom)>0) print(bottom, n = n, max_footer_lines = 1) invisible(x) } +is_grand <- function(.data){ + !is.null(igraph::graph_attr(.data, "grand")) +} + describe_graph <- function(x) { paste0("A ", ifelse(is_dynamic(x), "dynamic, ", ""), @@ -35,3 +36,26 @@ describe_graph <- function(x) { ifelse(is_directed(x), "directed", "undirected")) ) } + +describe_nodes <- function(x){ + nd <- net_dims(x) + if(!is.null(igraph::graph_attr(x, "grand")$vertex1)){ + node_name <- paste(nd[1], igraph::graph_attr(x, "grand")$vertex1) + if(length(nd)==2 && !is.null(igraph::graph_attr(x, "grand")$vertex2)) + node_name <- c(node_name, paste(nd[2], igraph::graph_attr(x, "grand")$vertex2)) + } else node_name <- paste(sum(nd), "nodes") + node_name +} + +describe_ties <- function(x){ + nt <- net_ties(x) + tie_name <- ifelse(is_directed(x), "arcs", "ties") + if(!is.null(igraph::graph_attr(x, "grand")$edge.pos)){ + tie_name <- paste(igraph::graph_attr(x, "grand")$edge.pos, + tie_name) + } else if(!is.null(tie_attribute(x, "type"))){ + tie_name <- paste(cli::ansi_collapse(unique(tie_attribute(x, "type"))), + tie_name) + } + paste(nt, tie_name) +} diff --git a/R/make_create.R b/R/make_create.R index 3bc7b436..fe7dbfd8 100644 --- a/R/make_create.R +++ b/R/make_create.R @@ -2,7 +2,6 @@ #' Making networks with explicit ties #' -#' #' @description #' This function creates a network from a vector of explicitly named nodes #' and ties between them. @@ -116,6 +115,175 @@ create_explicit <- function(...){ as_tidygraph(res) } +# Collections #### + +#' Making ego networks through interviewing +#' +#' @description +#' This function creates an ego network through interactive interview questions. +#' Note that it only creates a simplex, directed network. +#' @param max_alters The maximum number of alters to collect. +#' By default infinity, but many name generators will expect a maximum of +#' e.g. 5 alters to be named. +#' @param roster A vector of node names to offer as potential alters for ego. +#' @param interpreter Logical. If TRUE, then it will ask for which attributes +#' to collect and give prompts for each attribute for each node in the network. +#' By default FALSE. +#' @param interrelater Logical. If TRUE, then it will ask for the contacts from +#' each of the alters perspectives too. +#' @name make_ego +#' @family makes +#' @export +create_ego <- function(max_alters = Inf, + roster = NULL, + interpreter = FALSE, + interrelater = FALSE){ + cli::cli_text("What is ego's name?") + ego <- readline() + cli::cli_text("What is the relationship you are collecting? Name it in the singular, e.g. 'friendship'") + ties <- readline() + # cli::cli_text("Is this a weighted network?") + # weighted <- q_yes() + alters <- vector() + if(!is.null(roster)){ + for (alt in roster){ + cli::cli_text("Is {ego} connected by {ties} to {alt}?") + alters <- c(alters, q_yes()) + } + alters <- roster[alters] + } else { + repeat{ + cli::cli_text("Please name a contact:") + alters <- c(alters, readline()) + if(length(alters) == max_alters){ + cli::cli_alert_info("{.code max_alters} reached.") + break + } + if (q_yes("Are these all the contacts?")) break + } + } + out <- as_tidygraph(as.data.frame(cbind(ego, alters))) + if(interpreter){ + attr <- vector() + repeat{ + cli::cli_text("Please name an attribute you are collecting, or press [Enter] to continue.") + attr <- c(attr, readline()) + if (attr[length(attr)]==""){ + attr <- attr[-length(attr)] + break + } + } + if(length(attr)>0){ + for(att in attr){ + values <- vector() + for (alt in c(ego, alters)){ + cli::cli_text("What value does {alt} have for {att}:") + values <- c(values, readline()) + } + out <- add_node_attribute(out, att, values) + } + } + } + if(interrelater){ + for(alt in alters){ + others <- setdiff(c(ego,alters), alt) + extra <- vector() + for(oth in others){ + cli::cli_text("Is {alt} connected by {ties} to {oth}?") + extra <- c(extra, q_yes()) + } + # cat(c(rbind(alt, others[extra]))) + out <- add_ties(out, c(rbind(alt, others[extra]))) + } + } + if(!is.null(roster) && any(!roster %in% node_names(out))){ + isolates <- roster[!roster %in% node_names(out)] + out <- add_nodes(out, length(isolates), list(name = isolates)) + } + out <- add_info(out, ties = ties, + collection = "Interview", + year = format(as.Date(Sys.Date(), format="%d/%m/%Y"),"%Y")) + out +} + +q_yes <- function(msg = NULL){ + if(!is.null(msg)) cli::cli_text(msg) + out <- readline() + if(is.logical(out)) return(out) + if(out=="") return(FALSE) + choices <- c("yes","no","true","false") + out <- c(TRUE,FALSE,TRUE,FALSE)[pmatch(tolower(out), tolower(choices))] + out +} + +# Collections #### + +#' Making motifs +#' +#' @description +#' `create_motifs()` is used to create a list of networks that represent the +#' subgraphs or motifs corresponding to a certain number of nodes and direction. +#' Note that currently only `n==2` to `n==4` is implemented, +#' and the latter only for undirected networks. +#' +#' @inheritParams make_create +#' @name make_motifs +#' @family makes +#' @export +create_motifs <- function(n, directed = FALSE){ + directed <- infer_directed(n, directed) + n <- infer_n(n) + if(!directed & n==2){ + return(list(Null = mutate_nodes(create_empty(2), + name = c("A","B")), + M = create_explicit(A--B))) + } else if(directed & n==2){ + return(list(Null = mutate_nodes(create_empty(2, directed = TRUE), + name = c("A","B")), + Asymmetric = create_explicit(A-+B), + Mutual = create_explicit(A++B))) + } else if(!directed & n==3){ + return(list(Empty = mutate_nodes(create_empty(3), + names = c("A","B","C")), + Edge = create_explicit(A--B, C), + Path = create_explicit(A--B--C), + Triangle = create_explicit(A--B--C--A))) + } else if(directed & n==3){ + return(list(`003` = mutate_nodes(create_empty(3, directed = TRUE), + names = c("A","B","C")), + `012` = create_explicit(A-+B, C), + `102` = create_explicit(A++B, C), + `021D` = create_explicit(A-+B, A-+C), + `021U` = create_explicit(A+-B, A+-C), + `021C` = create_explicit(A-+B, B-+C), + `111D` = create_explicit(A++B, C-+B), + `111U` = create_explicit(A++B, B-+C), + `030T` = create_explicit(A-+B, A-+C, B-+C), + `030C` = create_explicit(A-+B, B-+C, C-+A), + `201` = create_explicit(A++B, B++C), + `120D` = create_explicit(A++B, C-+A:B), + `120U` = create_explicit(A++B, A:B-+C), + `120C` = create_explicit(A++B, A-+C-+B), + `210` = create_explicit(A++B, B++C, A-+C), + `300` = create_explicit(A++B++C++A))) + } else if(!directed & n==4){ + return(list(E4 = mutate_nodes(create_empty(4), + name = c("A","B","C","D")), + I4 = create_explicit(A--B, C, D), + H4 = create_explicit(A--B, C--D), + L4 = create_explicit(A--B--C, D), + D4 = create_explicit(A--B--C--A, D), + U4 = create_explicit(A--B--C--D), + Y4 = create_explicit(A--B--C, B--D), + P4 = create_explicit(A--B--C, B--D--C), + C4 = create_explicit(A--B--C--D--A), + Z4 = create_explicit(A--B--C--D--A--C), + X4 = create_explicit(A--B--C--D--A--C, B--D))) + } else + cli::cli_alert_warning("Motifs not yet available for that kind of network.") +} + + # Defined #### #' Making networks with defined structures diff --git a/R/make_read.R b/R/make_read.R index 729475a9..dde1f4bc 100644 --- a/R/make_read.R +++ b/R/make_read.R @@ -684,6 +684,7 @@ write_graphml <- function(.data, #' # edge_color = "type", node_color = "Compilation") #' @export read_cran <- function(pkg = "all"){ + mnet_progress_step("Downloading data about available packages from CRAN") cranInfoDF <- as.data.frame(utils::available.packages( utils::contrib.url(getOption("repos"), type = "source"))) if(pkg=="all") new <- cranInfoDF$Package else diff --git a/R/manip_nodes.R b/R/manip_nodes.R index 988beda4..9562b528 100644 --- a/R/manip_nodes.R +++ b/R/manip_nodes.R @@ -173,3 +173,59 @@ rename <- tidygraph::rename filter_nodes <- function(.data, ..., .by){ tidygraph::filter(.data, ..., .by = .by) } + +# Network information #### + +#' Modifying network data +#' +#' @description +#' These functions allow users to add and edit information about the network +#' itself. +#' This includes the name, year, and mode of collection of the network, +#' as well as definitions of the nodes and ties in the network. +#' Where available, this information is printed for tidygraph-class objects, +#' and can be used for printing a grand table in the `{grand}` package. +#' @name manip_net +#' @inheritParams mark_is +#' @param ... Named attributes. The following are currently recognised: +#' "name", "year", and "doi" of the network, +#' "collection" or "mode" of the network +#' ("survey", "interview","sensor","observation","archival", or "simulation"), +#' "nodes" (a vector of the names of the nodes) or "vertex1"/"vertex2", +#' "ties" or "edge.pos"/"edge.neg" for defining the ties. +#' @examples +#' add_info(ison_algebra, name = "Algebra") +#' @export +add_info <- function(.data, ...){ + if(!is.null(igraph::graph_attr(.data)$grand)){ + cli::cli_abort("Hmm, I don't know how to do that yet.") + } else { + info <- list(...) + unrecog <- setdiff(names(info), c("name", "nodes", "ties", "doi", + "collection", "year", "mode", "vertex1", + "vertex1.total", "vertex2", + "vertex2.total", "edge.pos", "edge.neg")) + if(length(unrecog)>0) + cli::cli_alert_warning("{unrecog} are not recognised fields.") + if("nodes" %in% names(info)){ + info$vertex1 <- info$nodes[1] + if(is_twomode(.data) && length(info$nodes)==2) + info$vertex2 <- info$nodes[2] + info$nodes <- NULL + } + if("ties" %in% names(info)){ + info$edge.pos <- info$ties + info$ties <- NULL + } + if("collection" %in% names(info)){ + info$mode <- info$collection + info$collection <- NULL + } + # return(str(info)) # for debugging + out <- .data + igraph::graph_attr(out)$grand <- info + } + as_tidygraph(out) +} + + diff --git a/R/manip_reformat.R b/R/manip_reformat.R index 6d636739..64a6f29b 100644 --- a/R/manip_reformat.R +++ b/R/manip_reformat.R @@ -264,10 +264,12 @@ to_unweighted <- function(.data, threshold = 1) UseMethod("to_unweighted") #' @export to_unweighted.tbl_graph <- function(.data, threshold = 1) { - edges <- weight <- NULL - .data %>% activate(edges) %>% - dplyr::filter(weight >= threshold) %>% - dplyr::select(-c(weight)) + if(is_weighted(.data)){ + edges <- weight <- NULL + .data %>% activate(edges) %>% + dplyr::filter(weight >= threshold) %>% + dplyr::select(-c(weight)) + } else .data } #' @export diff --git a/R/manip_split.R b/R/manip_split.R index 15668789..8f17ae9f 100644 --- a/R/manip_split.R +++ b/R/manip_split.R @@ -32,6 +32,7 @@ to_egos.igraph <- function(.data, max_dist = 1, min_dist = 0){ if(is_twomode(.data)) max_dist <- max_dist*2 + mnet_progress_step("Obtaining neighbourhoods") out <- igraph::make_ego_graph(.data, order = max_dist, mindist = min_dist) diff --git a/R/manynet-utils.R b/R/manynet-utils.R index 51cdcedb..bd146c06 100644 --- a/R/manynet-utils.R +++ b/R/manynet-utils.R @@ -1,5 +1,5 @@ # defining global variables more centrally -utils::globalVariables(c(".data", "obs", "from", "to", "name")) +utils::globalVariables(c(".data", "obs", "from", "to", "name", "A","B","C","D")) # Helper function for declaring available methods available_methods <- function(fun_vctr) { @@ -41,6 +41,10 @@ thisRequiresBio <- function(pkgname) { patchwork::wrap_plots(e1, e2, ...) } +seq_nodes <- function(.data){ + seq.int(net_nodes(.data)) +} + # #' @export # `%||%` <- function(x, y) { # if (is_null(x)) y else x diff --git a/R/map_autograph.R b/R/map_autograph.R index 0821fcb6..2fadaee7 100644 --- a/R/map_autograph.R +++ b/R/map_autograph.R @@ -388,7 +388,7 @@ graphr <- function(.data, layout, labels = TRUE, } } if (is_complex(g)) { - p <- p + ggraph::geom_edge_loop0(edge_width = esize, edge_alpha = 0.4) + p <- p + ggraph::geom_edge_loop0(edge_alpha = 0.4) } if (length(unique(esize)) == 1) { p <- p + ggplot2::guides(edge_width = "none") diff --git a/R/map_theme.R b/R/map_theme.R index 594893f4..0b60e769 100644 --- a/R/map_theme.R +++ b/R/map_theme.R @@ -15,6 +15,20 @@ #' theme_iheid() NULL +#' @rdname map_themes +#' @param theme String naming a theme. +#' By default "default". +#' @export +set_manynet_theme <- function(theme = "default"){ + theme_opts <- c("default", "iheid", "ethz", "uzh", "rug", "crisp") + if(theme %in% theme_opts){ + options(mnet_theme = theme) + cli::cli_alert_success("Theme set to {theme}.") + } else { + cli::cli_alert_danger("Please choose one of the available themes: {.emph {theme_opts}}.") + } +} + #' @rdname map_themes #' @export theme_iheid <- function(base_size = 12, base_family = "serif") { diff --git a/R/mark_net.R b/R/mark_net.R index b5b3d927..b8d236d5 100644 --- a/R/mark_net.R +++ b/R/mark_net.R @@ -391,7 +391,7 @@ is_multiplex.matrix <- function(.data) { FALSE } -reserved_tie_attr <- c("wave","panel","sign","weight","date","begin","end") +reserved_tie_attr <- c("wave","panel","sign","weight","date","begin","end","name") #' @export is_multiplex.tbl_graph <- function(.data) { diff --git a/R/measure_centrality.R b/R/measure_centrality.R index 7cf2af32..c1874791 100644 --- a/R/measure_centrality.R +++ b/R/measure_centrality.R @@ -657,6 +657,8 @@ net_harmonic <- function(.data, normalized = TRUE, k = 2){ #' - `node_power()` measures the Bonacich, beta, or power centrality of nodes in a network. #' - `node_alpha()` measures the alpha or Katz centrality of nodes in a network. #' - `node_pagerank()` measures the pagerank centrality of nodes in a network. +#' - `node_hub()` measures how well nodes in a network serve as hubs pointing to many authorities. +#' - `node_authority()` measures how well nodes in a network serve as authorities from many hubs. #' - `tie_eigenvector()` measures the eigenvector centrality of ties in a network. #' - `net_eigenvector()` measures the eigenvector centralization for a network. #' @@ -825,6 +827,27 @@ node_pagerank <- function(.data){ .data) } +#' @rdname measure_central_eigen +#' @references +#' Kleinberg, Jon. 1999. +#' "Authoritative sources in a hyperlinked environment". +#' _Journal of the ACM_ 46(5): 604–632. +#' \doi{110.1145/324133.324140}. +#' @export +node_authority <- function(.data){ + if(missing(.data)) {expect_nodes(); .data <- .G()} + make_node_measure(igraph::authority_score(manynet::as_igraph(.data))$vector, + .data) +} + +#' @rdname measure_central_eigen +#' @export +node_hub <- function(.data){ + if(missing(.data)) {expect_nodes(); .data <- .G()} + make_node_measure(igraph::hub_score(manynet::as_igraph(.data))$vector, + .data) +} + #' @rdname measure_central_eigen #' @examples #' tie_eigenvector(ison_adolescents) diff --git a/R/measure_closure.R b/R/measure_closure.R index 844fb9d1..6b8300f0 100644 --- a/R/measure_closure.R +++ b/R/measure_closure.R @@ -94,20 +94,53 @@ node_transitivity <- function(.data) { #' @export net_equivalency <- function(.data) { if(missing(.data)) {expect_nodes(); .data <- .G()} - if (manynet::is_twomode(.data)) { + if(is_twomode(.data)){ mat <- manynet::as_matrix(.data) c <- ncol(mat) indegrees <- colSums(mat) twopaths <- crossprod(mat) diag(twopaths) <- 0 - output <- sum(twopaths * (twopaths - 1)) / + out <- sum(twopaths * (twopaths - 1)) / (sum(twopaths * (twopaths - 1)) + sum(twopaths * - (matrix(indegrees, c, c) - twopaths))) - if (is.nan(output)) output <- 1 - if(manynet::is_weighted(.data)) output <- output / mean(mat[mat>0]) - } else cli::cli_abort("This function expects a two-mode network") - make_network_measure(output, .data) + (matrix(indegrees, c, c) - twopaths))) + if (is.nan(out)) out <- 1 + if(manynet::is_weighted(.data)) out <- out / mean(mat[mat>0]) + } else { + out <- rowSums(vapply(cli::cli_progress_along(1:net_nodes(.data)), function(i){ + threepaths <- igraph::all_simple_paths(.data, i, cutoff = 3, + mode = "all") + onepaths <- threepaths[vapply(threepaths, length, + FUN.VALUE = numeric(1))==2] + threepaths <- threepaths[vapply(threepaths, length, + FUN.VALUE = numeric(1))==4] + c(sum(sapply(threepaths,"[[",4) %in% sapply(onepaths,"[[",2)), + length(threepaths)) + }, FUN.VALUE = numeric(2))) + out <- out[1]/out[2] + } + make_network_measure(out, .data) +} + +#' @rdname measure_closure +#' @examples +#' node_equivalency(ison_southern_women) +#' @export +node_equivalency <- function(.data) { + if(missing(.data)) {expect_nodes(); .data <- .G()} + # if(is_weighted(.data)) + # mnet_info("Using unweighted form of the network.") + out <- vapply(cli::cli_progress_along(1:net_nodes(.data)), function(i){ + threepaths <- igraph::all_simple_paths(.data, i, cutoff = 3, + mode = "all") + onepaths <- threepaths[vapply(threepaths, length, + FUN.VALUE = numeric(1))==2] + threepaths <- threepaths[vapply(threepaths, length, + FUN.VALUE = numeric(1))==4] + mean(sapply(threepaths,"[[",4) %in% sapply(onepaths,"[[",2)) + }, FUN.VALUE = numeric(1)) + if (any(is.nan(out))) out[is.nan(out)] <- 0 + make_node_measure(out, .data) } #' @rdname measure_closure diff --git a/R/member_equivalence.R b/R/member_equivalence.R index 6e99e5f3..b94d5a75 100644 --- a/R/member_equivalence.R +++ b/R/member_equivalence.R @@ -57,8 +57,7 @@ node_in_equivalence <- function(.data, census, range = 8L){ if(missing(.data)) {expect_nodes(); .data <- .G()} hc <- switch(match.arg(cluster), - hierarchical = cluster_hierarchical(`if`(manynet::is_twomode(.data), - manynet::to_onemode(census), census), + hierarchical = cluster_hierarchical(census, match.arg(distance)), concor = cluster_concor(.data, census)) @@ -105,13 +104,13 @@ node_in_structural <- function(.data, #' } #' @export node_in_regular <- function(.data, - k = c("silhouette", "elbow", "strict"), - cluster = c("hierarchical", "concor"), - distance = c("euclidean", "maximum", "manhattan", - "canberra", "binary", "minkowski"), - range = 8L){ + k = c("silhouette", "elbow", "strict"), + cluster = c("hierarchical", "concor"), + distance = c("euclidean", "maximum", "manhattan", + "canberra", "binary", "minkowski"), + range = 8L){ if(missing(.data)) {expect_nodes(); .data <- .G()} - if(manynet::is_twomode(.data)){ + if(is_twomode(.data)){ mat <- as.matrix(node_by_quad(.data)) } else { mat <- node_by_triad(.data) diff --git a/R/motif_census.R b/R/motif_census.R index 6bb9545c..57789bad 100644 --- a/R/motif_census.R +++ b/R/motif_census.R @@ -84,6 +84,26 @@ node_by_tie <- function(.data){ make_node_motif(t(mat), object) } +#' @rdname motif_node +#' @examples +#' node_by_dyad(ison_networkers) +#' @export +node_by_dyad <- function(.data) { + if(missing(.data)) {expect_nodes(); .data <- .G()} + if(is_weighted(.data)){ + .data <- to_unweighted(.data) + mnet_info("Ignoring tie weights.") + } + mat <- as_matrix(.data) + out <- t(vapply(seq_nodes(.data), function(x){ + vec <- mat[x,] + mat[,x] + c(sum(vec==2), sum(vec==1), sum(vec==0)) + }, FUN.VALUE = numeric(3))) + colnames(out) <- c("Mutual", "Asymmetric", "Null") + if (!is_directed(.data)) out <- out[,c(1, 3)] + make_node_motif(out, .data) +} + #' @rdname motif_node #' @references #' Davis, James A., and Samuel Leinhardt. 1967. @@ -95,83 +115,117 @@ node_by_triad <- function(.data){ if(missing(.data)) {expect_nodes(); .data <- .G()} out <- t(sapply(seq.int(manynet::net_nodes(.data)), function(x) net_by_triad(.data) - net_by_triad(manynet::delete_nodes(.data, x)))) - rownames(out) <- manynet::node_names(.data) make_node_motif(out, .data) } -#' @rdname motif_node -#' @section Quad census: -#' The quad census uses the `{oaqc}` package to do -#' the heavy lifting of counting the number of each orbits. -#' See `vignette('oaqc')`. -#' However, our function relabels some of the motifs -#' to avoid conflicts and improve some consistency with -#' other census-labelling practices. -#' The letter-number pairing of these labels indicate -#' the number and configuration of ties. -#' For now, we offer a rough translation: -#' -#' | migraph | Ortmann and Brandes -#' | ------------- |------------- | -#' | E4 | co-K4 -#' | I40, I41 | co-diamond -#' | H4 | co-C4 -#' | L42, L41, L40 | co-paw -#' | D42, D40 | co-claw -#' | U42, U41 | P4 -#' | Y43, Y41 | claw -#' | P43, P42, P41 | paw -#' | 04 | C4 -#' | Z42, Z43 | diamond -#' | X4 | K4 -#' -#' See also [this list of graph classes](https://www.graphclasses.org/smallgraphs.html#nodes4). -#' @importFrom tidygraph %E>% -#' @references -#' Ortmann, Mark, and Ulrik Brandes. 2017. -#' “Efficient Orbit-Aware Triad and Quad Census in Directed and Undirected Graphs.” -#' \emph{Applied Network Science} 2(1):13. -#' \doi{10.1007/s41109-017-0027-2}. +# #' @rdname motif_node +# #' @section Quad census: +# #' The quad census uses the `{oaqc}` package to do +# #' the heavy lifting of counting the number of each orbits. +# #' See `vignette('oaqc')`. +# #' However, our function relabels some of the motifs +# #' to avoid conflicts and improve some consistency with +# #' other census-labelling practices. +# #' The letter-number pairing of these labels indicate +# #' the number and configuration of ties. +# #' For now, we offer a rough translation: +# #' +# #' | migraph | Ortmann and Brandes +# #' | ------------- |------------- | +# #' | E4 | co-K4 +# #' | I40, I41 | co-diamond +# #' | H4 | co-C4 +# #' | L42, L41, L40 | co-paw +# #' | D42, D40 | co-claw +# #' | U42, U41 | P4 +# #' | Y43, Y41 | claw +# #' | P43, P42, P41 | paw +# #' | 04 | C4 +# #' | Z42, Z43 | diamond +# #' | X4 | K4 +# #' +# #' See also [this list of graph classes](https://www.graphclasses.org/smallgraphs.html#nodes4). +# #' @importFrom tidygraph %E>% +# #' @references +# #' Ortmann, Mark, and Ulrik Brandes. 2017. +# #' “Efficient Orbit-Aware Triad and Quad Census in Directed and Undirected Graphs.” +# #' \emph{Applied Network Science} 2(1):13. +# #' \doi{10.1007/s41109-017-0027-2}. +# #' @examples +# #' node_by_quad(ison_southern_women) +# #' @export +# node_by_quad <- function(.data){ +# if(missing(.data)) {expect_nodes(); .data <- .G()} +# thisRequires("oaqc") +# graph <- .data %>% manynet::as_tidygraph() %E>% +# as.data.frame() +# if(ncol(graph)>2) graph <- graph[,1:2] +# out <- oaqc::oaqc(graph)[[1]] +# out <- out[-1,] +# rownames(out) <- manynet::node_names(.data) +# colnames(out) <- c("E4", # co-K4 +# "I41","I40", # co-diamond +# "H4", # co-C4 +# "L42","L41","L40", # co-paw +# "D42","D40", # co-claw +# "U42","U41", # P4 +# "Y43","Y41", # claw +# "P43","P42","P41", # paw +# "04", # C4 +# "Z42","Z43", # diamond +# "X4") # K4 +# if(manynet::is_twomode(.data)) out <- out[,-c(8,9,14,15,16,18,19,20)] +# make_node_motif(out, .data) +# } + +#' @rdname motif_node #' @examples -#' node_by_quad(manynet::ison_southern_women) +#' node_by_quad(ison_southern_women) #' @export node_by_quad <- function(.data){ - if(missing(.data)) {expect_nodes(); .data <- .G()} - thisRequires("oaqc") - graph <- .data %>% manynet::as_tidygraph() %E>% - as.data.frame() - if(ncol(graph)>2) graph <- graph[,1:2] - out <- oaqc::oaqc(graph)[[1]] - out <- out[-1,] - rownames(out) <- manynet::node_names(.data) - colnames(out) <- c("E4", # co-K4 - "I41","I40", # co-diamond - "H4", # co-C4 - "L42","L41","L40", # co-paw - "D42","D40", # co-claw - "U42","U41", # P4 - "Y43","Y41", # claw - "P43","P42","P41", # paw - "04", # C4 - "Z42","Z43", # diamond - "X4") # K4 - if(manynet::is_twomode(.data)) out <- out[,-c(8,9,14,15,16,18,19,20)] + cmbs <- utils::combn(1:net_nodes(.data), 4) + mat <- as_matrix(to_onemode(.data)) + dd <- apply(cmbs, 2, function(x) c(sum(mat[x,x]), + max(rowSums(mat[x,x])))) + + types <- rep(NA, ncol(cmbs)) + types[dd[1,] == 0] <- "E4" + types[dd[1,] == 2] <- "I4" + types[dd[1,] == 4 & dd[2,] == 1] <- "H4" + types[dd[1,] == 4 & dd[2,] == 2] <- "L4" + types[dd[1,] == 6 & dd[2,] == 2] <- "D4" + types[dd[1,] == 6 & dd[2,] == 1] <- "U4" + types[dd[1,] == 6 & dd[2,] == 3] <- "Y4" + types[dd[1,] == 8 & dd[2,] == 3] <- "P4" + types[dd[1,] == 8 & dd[2,] == 2] <- "C4" + types[dd[1,] == 10] <- "Z4" + types[dd[1,] == 12] <- "X4" + + appears <- sapply(seq.int(net_nodes(.data)), + function(x) types[which(cmbs == x, arr.ind = TRUE)[,2]]) + out <- apply(appears, 2, table) + + if(is.list(out)){ + out <- as.matrix(dplyr::bind_rows(out)) + } else out <- as.matrix(as.data.frame(t(out))) + out.order <- c("E4","I4","H4","L4","D4","U4","Y4","P4","C4","Z4","X4") + out <- out[,match(out.order, colnames(out))] + colnames(out) <- out.order + out[is.na(out)] <- 0 + make_node_motif(out, .data) } -# #' @export -# node_bmotif_census <- function(.data, normalized = FALSE){ -# if (!("bmotif" %in% rownames(utils::installed.packages()))) { -# message("Please install package `{bmotif}`.") -# out <- bmotif::node_positions(manynet::as_matrix(.data), -# weights_method = ifelse(manynet::is_weighted(.data), -# 'mean_motifweights', 'none'), -# normalisation = ifelse(normalized, -# 'levelsize_NAzero', 'none')) -# make_node_motif(out, .data) -# } +# https://stackoverflow.com/questions/26828301/faster-version-of-combn#26828486 +# comb2.int <- function(n, choose = 2){ +# # e.g. n=3 => (1,2), (1,3), (2,3) +# x <- rep(1:n,(n:1)-1) +# i <- seq_along(x)+1 +# o <- c(0,cumsum((n-2):1)) +# y <- i-o[x] +# return(cbind(x,y)) # } -# + # #' @export # node_igraph_census <- function(.data, normalized = FALSE){ # out <- igraph::motifs(manynet::as_igraph(.data), 4) @@ -204,8 +258,8 @@ node_by_quad <- function(.data){ #' _Social Networks_ 32(3): 245-51. #' \doi{10.1016/j.socnet.2010.03.006}. #' @examples -#' node_by_path(manynet::ison_adolescents) -#' node_by_path(manynet::ison_southern_women) +#' node_by_path(ison_adolescents) +#' node_by_path(ison_southern_women) #' @export node_by_path <- function(.data){ if(missing(.data)) {expect_nodes(); .data <- .G()} @@ -243,7 +297,7 @@ NULL net_by_dyad <- function(.data) { if(missing(.data)) {expect_nodes(); .data <- .G()} if (manynet::is_twomode(.data)) { - cli::cli_abort("A twomode or multilevel option for a dyad census is not yet implemented.") + mnet_unavailable("A twomode or multilevel option for a dyad census is not yet implemented.") } else { out <- suppressWarnings(igraph::dyad_census(manynet::as_igraph(.data))) out <- unlist(out) @@ -275,6 +329,53 @@ net_by_triad <- function(.data) { } } +#' @rdname motif_net +#' @examples +#' net_by_quad(ison_southern_women) +#' @export +net_by_quad <- function(.data){ + if(missing(.data)) {expect_nodes(); .data <- .G()} + cmbs <- utils::combn(1:net_nodes(.data), 4) + mat <- as_matrix(to_onemode(.data)) + dens <- apply(cmbs, 2, function(x) sum(mat[x,x])) + + E4 <- sum(dens == 0) + I4 <- sum(dens == 1) + + if(any(dens==2)){ + if(sum(dens==2)>1){ + twosies <- apply(cmbs[,dens==2], 2, function(x) max(rowSums(mat[x,x]))) + } else twosies <- max(rowSums(mat[cmbs[,dens==2], cmbs[,dens==2]])) + H4 <- sum(twosies==1) + L4 <- sum(twosies==2) + } else H4 <- L4 <- 0 + + if(any(dens==3)){ + if(sum(dens==3)>1){ + threesies <- apply(cmbs[,dens==3], 2, function(x) max(rowSums(mat[x,x]))) + } else threesies <- max(rowSums(mat[cmbs[,dens==3], cmbs[,dens==3]])) + D4 <- sum(threesies==2) + U4 <- sum(threesies==1) + Y4 <- sum(threesies==3) + } else D4 <- U4 <- Y4 <- 0 + + if(any(dens==4)){ + if(sum(dens==4)>1){ + foursies <- apply(cmbs[,dens==4], 2, function(x) max(rowSums(mat[x,x]))) + } else foursies <- max(rowSums(mat[cmbs[,dens==4], cmbs[,dens==4]])) + P4 <- sum(foursies==3) + C4 <- sum(foursies==2) + } else P4 <- C4 <- 0 + + Z4 <- sum(dens == 5) + X4 <- sum(dens == 6) + + out <- c(E4 = E4, I4 = I4, H4 = H4, L4 = L4, D4 = D4, U4 = U4, Y4 = Y4, + P4 = P4, C4 = C4, Z4 = Z4, X4 = X4) + + make_network_motif(out, .data) +} + #' @rdname motif_net #' @source Alejandro Espinosa 'netmem' #' @references diff --git a/R/zzz.R b/R/zzz.R index 1549c505..9a048c47 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -3,15 +3,18 @@ # suppressMessages(suppressPackageStartupMessages(library("manynet", warn.conflicts = FALSE))) if (!interactive()) return() - + + options(manynet_verbosity = getOption("manynet_verbosity", "verbose")) + # options(manynet_theme = getOption("manynet_theme", "default")) + options(cli.theme = manynet_console_theme()) + # pkgs <- as.data.frame(utils::available.packages(utils::contrib.url(getOption("repos")))) # # cran_version <- pkgs[pkgs$Package == "manynet","Version"] local_version <- utils::packageVersion("manynet") - cli::cli_div(theme = list(span.emph = list(color = "red"))) - cli::cli_inform("This is {.pkg manynet} version {.emph {local_version}}", class = "packageStartupMessage") - cli::cli_end() + cli::cli_inform("You are using {.pkg manynet} version {.version {local_version}}.", + class = "packageStartupMessage") old.list <- as.data.frame(utils::old.packages()) behind_cran <- "manynet" %in% old.list$Package @@ -20,6 +23,8 @@ "i" = "There are lots of ways to contribute to {.pkg manynet} at {.url https://github.com/stocnet/manynet/}.", "i" = "Please let us know any issues or features requests at {.url https://github.com/stocnet/manynet/issues}. It's really helpful!", "i" = "To eliminate package startup messages, use: `suppressPackageStartupMessages(library({.pkg manynet}))`.", + # "i" = "Changing the theme of all your graphs is straightforward with `set_manynet_theme()`", + "i" = "If there are too many messages in the console, run `options(manynet_verbosity = 'quiet')`", "i" = "Visit the website to learn more: {.url https://stocnet.github.io/manynet/}.", "i" = "We recommend the 'Function Overview' page online to discover new analytic opportunities: {.url https://stocnet.github.io/manynet/reference/index.html}.", "i" = "Discover all the {.emph stocnet} R packages at {.url https://github.com/stocnet/}.", @@ -43,3 +48,72 @@ } } + +mnet_progress_step <- function(...){ + if(getOption("manynet_verbosity", default = "quiet")!="quiet") + cli::cli_progress_step(...) +} + +mnet_info <- function(...){ + if(getOption("manynet_verbosity", default = "quiet")!="quiet") + cli::cli_alert_info(...) +} + +mnet_unavailable <- function(...){ + if(getOption("manynet_verbosity", default = "quiet")!="quiet") + cli::cli_abort(paste(..., + "If you are interested in this feature,", + "please vote for it or raise it as an issue at", + "{.url https://github.com/stocnet/manynet/issues}.")) +} + +manynet_console_theme <- function(){ + # dark <- detect_dark_theme(dark) + list(h1 = list(`margin-top` = 1, `margin-bottom` = 0, color = "#199D77", + fmt = function(x) cli::rule(x, line_col = "#199D77")), + h2 = list(`margin-top` = 1, `margin-bottom` = 0, color = "#199D77", + fmt = function(x) paste0(cli::symbol$line, " ", x, " ", cli::symbol$line, cli::symbol$line)), + h3 = list(`margin-top` = 1, `margin-bottom` = 0, color = "#199D77"), + par = list(`margin-top` = 0, `margin-bottom` = 1), + `.alert-danger` = list(`background-color` = "#D83127", color = "white", + before = function() paste0(cli::symbol$cross, " ")), + `.alert-warning` = list(color = "#E6AB02", `font-weight` = "bold", before = paste0("!", " ")), + `.alert-success` = list(before = function() paste0(col_mnet_green(cli::symbol$tick), " ")), + `.alert-info` = list(before = function() paste0(col_mnet_blue(cli::symbol$info), " ")), + `.alert-start` = list(before = function() paste0(cli::symbol$arrow_right, " ")), + span.pkg = list(color = "#199D77", `font-weight` = "bold"), + span.version = list(color = "#D83127"), + span.emph = list(color = "#D83127"), + span.strong = list(`font-weight` = "bold", `font-style` = "italic"), + span.fun = utils::modifyList(simple_theme_code(), + list(after = "()")), + span.fn = utils::modifyList(simple_theme_code(), + list(after = "")), + span.arg = simple_theme_code(), + span.kbd = utils::modifyList(simple_theme_code(), + list(before = "<", after = ">")), + span.key = utils::modifyList(simple_theme_code(), + list(before = "<", after = ">")), + span.file = list(color = "#4576B5"), + span.path = list(color = "#4576B5"), + span.email = list(color = "#4576B5"), + span.url = utils::modifyList(list(color = "#4576B5"), list(before = "<", + after = ">")), + span.var = simple_theme_code(), + span.envvar = simple_theme_code(), + span.timestamp = list(before = "[", after = "]", color = "grey")) +} + +simple_theme_code <- function(){ + # if (dark) { + # list(`background-color` = "#232323", color = "#f0f0f0") + # } + # else { + list(`background-color` = "#f8f8f8", color = "#202020") + # } +} + +col_mnet_green <- cli::make_ansi_style("#199D77") + +col_mnet_blue <- cli::make_ansi_style("#4576B5") + diff --git a/cran-comments.md b/cran-comments.md index 732539ec..2e6e0b1f 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -8,3 +8,5 @@ ## R CMD check results 0 errors | 0 warnings | 0 notes + +* This version fixes errors on Linux versions for which the {oaqc} package is not available \ No newline at end of file diff --git a/data/ison_laterals.rda b/data/ison_laterals.rda index fc51fbc3..7b4c4e4e 100644 Binary files a/data/ison_laterals.rda and b/data/ison_laterals.rda differ diff --git a/data/ison_southern_women.rda b/data/ison_southern_women.rda index 0ed513bf..dc1fd4fc 100644 Binary files a/data/ison_southern_women.rda and b/data/ison_southern_women.rda differ diff --git a/inst/tutorials/tutorial0/tutorial0.Rmd b/inst/tutorials/tutorial0/tutorial0.Rmd index 3cb9e704..d8d02cbf 100644 --- a/inst/tutorials/tutorial0/tutorial0.Rmd +++ b/inst/tutorials/tutorial0/tutorial0.Rmd @@ -36,6 +36,7 @@ Recommended elsewhere are the following: - http://data.princeton.edu/R/gettingStarted.html - http://www.ats.ucla.edu/stat/R/sk/ - http://www.statmethods.net/ +- https://www.r-bloggers.com/2022/05/best-books-to-learn-r-programming-2/ These sites will help you learn or refresh your memory. But you can also expect to return to Google often as you go and type "R ..." as a query. diff --git a/inst/tutorials/tutorial1/data.Rmd b/inst/tutorials/tutorial1/data.Rmd index 7605b6c3..a8973e0a 100644 --- a/inst/tutorials/tutorial1/data.Rmd +++ b/inst/tutorials/tutorial1/data.Rmd @@ -514,6 +514,8 @@ Reimport the `data/adols.csv` file, make it an igraph-class object, and then mak read_edgelist("data/adols.csv") %>% as_igraph() %>% to_undirected() ``` +### Free play + Try this out with other compatible classes of objects, and reformatting other aspects of the network. For example: @@ -650,6 +652,8 @@ is just one (albeit the default) option for how ties in the projection are weigh Other options included in `{manynet}` include the Jaccard index, Rand simple matching coefficient, Pearson coefficient, and Yule's Q. These may be of interest if, for example, overlap should be weighted by participation. +### Other transformations + Other transforming functions include: - `to_giant()` identifies and returns only the main component of a network. @@ -658,11 +662,20 @@ Other transforming functions include: - `to_ties()` returns a network where the ties in the original network become the nodes, and the ties are shared adjacencies to nodes. - `to_matching()` returns a network in which each node is only tied to one of its previously existing ties such that the network's cardinality is maximised. +In other words, the algorithm tries to match nodes as best as possible so that each +node has a partner. +Note that this is not always possible. Remember, all these `to_*()` functions work on any compatible class; the `to_*()` functions will also attempt to return that same class of object, making it even easier to manipulate networks into shape for analysis. +### Free play + +```{r transform-free, exercise = TRUE, purl=FALSE} + +``` + ## Modifying data After choosing and/or importing some network data, diff --git a/inst/tutorials/tutorial1/data.html b/inst/tutorials/tutorial1/data.html index 044ee9d8..f1e9419d 100644 --- a/inst/tutorials/tutorial1/data.html +++ b/inst/tutorials/tutorial1/data.html @@ -247,6 +247,18 @@

Calling the data

+
+

Free play

+

See whether you can call up other datasets now too. You won’t need to +load the {manynet} package again (it’ll stay loaded), but +identify a network that interests you from table_data() and +then call/print it.

+
+ +
+

Describing networks

@@ -398,7 +410,7 @@

Network class objects

data-completion="1" data-diagnostics="1" data-startover="1" data-lines="0" data-pipe="|>">
data(package = "network")
-data(flo)
+data(flo, package = "network")
 flo

This data uses quite a different class to what we encountered above. @@ -650,6 +662,8 @@

Reformatting networks

data-lines="0" data-pipe="|>">
read_edgelist("data/adols.csv") %>% as_igraph() %>% to_undirected()
+
+

Free play

Try this out with other compatible classes of objects, and reformatting other aspects of the network. For example:

+

Transforming networks

These functions are similar to the reformatting functions, and are @@ -793,6 +808,9 @@

Projections

{manynet} include the Jaccard index, Rand simple matching coefficient, Pearson coefficient, and Yule’s Q. These may be of interest if, for example, overlap should be weighted by participation.

+
+
+

Other transformations

Other transforming functions include:

Remember, all these to_*() functions work on any compatible class; the to_*() functions will also attempt to return that same class of object, making it even easier to manipulate networks into shape for analysis.

+
+

Free play

+
+ +
+

Modifying data

@@ -1028,19 +1056,19 @@

Adding/deleting attributes

@@ -1059,22 +1087,22 @@

Adding/deleting attributes

@@ -1129,6 +1157,45 @@

Adding/deleting attributes

))) + + + + + @@ -1206,23 +1273,23 @@

Adding/deleting attributes

@@ -1330,25 +1397,25 @@

Adding/deleting attributes

opts = list(label = "\"netdata\"", exercise = "TRUE", purl = "FALSE"), engine = "r")), code_check = NULL, error_check = NULL, check = NULL, solution = structure(c("data(package = \"network\")", - "data(flo)", "flo"), chunk_opts = list(label = "netdata-solution")), - tests = NULL, options = list(eval = FALSE, echo = TRUE, results = "markup", - tidy = FALSE, tidy.opts = NULL, collapse = FALSE, prompt = FALSE, - comment = NA, highlight = FALSE, size = "normalsize", - background = "#F7F7F7", strip.white = TRUE, cache = 0, - cache.path = "data_cache/html/", cache.vars = NULL, cache.lazy = TRUE, - dependson = NULL, autodep = FALSE, cache.rebuild = FALSE, - fig.keep = "high", fig.show = "asis", fig.align = "default", - fig.path = "data_files/figure-html/", dev = "png", dev.args = NULL, - dpi = 192, fig.ext = "png", fig.width = 6.5, fig.height = 4, - fig.env = "figure", fig.cap = NULL, fig.scap = NULL, - fig.lp = "fig:", fig.subcap = NULL, fig.pos = "", out.width = 624, - out.height = NULL, out.extra = NULL, fig.retina = 2, - external = TRUE, sanitize = FALSE, interval = 1, aniopts = "controls,loop", - warning = TRUE, error = FALSE, message = TRUE, render = NULL, - ref.label = NULL, child = NULL, engine = "r", split = FALSE, - include = TRUE, purl = FALSE, max.print = 1000, label = "netdata", - exercise = TRUE, code = "", out.width.px = 624, out.height.px = 384, - params.src = "netdata, exercise = TRUE, purl=FALSE", + "data(flo, package = \"network\")", "flo"), chunk_opts = list( + label = "netdata-solution")), tests = NULL, options = list( + eval = FALSE, echo = TRUE, results = "markup", tidy = FALSE, + tidy.opts = NULL, collapse = FALSE, prompt = FALSE, comment = NA, + highlight = FALSE, size = "normalsize", background = "#F7F7F7", + strip.white = TRUE, cache = 0, cache.path = "data_cache/html/", + cache.vars = NULL, cache.lazy = TRUE, dependson = NULL, + autodep = FALSE, cache.rebuild = FALSE, fig.keep = "high", + fig.show = "asis", fig.align = "default", fig.path = "data_files/figure-html/", + dev = "png", dev.args = NULL, dpi = 192, fig.ext = "png", + fig.width = 6.5, fig.height = 4, fig.env = "figure", + fig.cap = NULL, fig.scap = NULL, fig.lp = "fig:", fig.subcap = NULL, + fig.pos = "", out.width = 624, out.height = NULL, out.extra = NULL, + fig.retina = 2, external = TRUE, sanitize = FALSE, interval = 1, + aniopts = "controls,loop", warning = TRUE, error = FALSE, + message = TRUE, render = NULL, ref.label = NULL, child = NULL, + engine = "r", split = FALSE, include = TRUE, purl = FALSE, + max.print = 1000, label = "netdata", exercise = TRUE, + code = "", out.width.px = 624, out.height.px = 384, params.src = "netdata, exercise = TRUE, purl=FALSE", fig.num = 0L, exercise.df_print = "paged", exercise.checker = "NULL"), engine = "r", version = "4"), class = c("r", "tutorial_exercise" ))) @@ -1401,20 +1468,20 @@

Adding/deleting attributes

@@ -1556,17 +1623,17 @@

Adding/deleting attributes

@@ -1703,25 +1770,25 @@

Adding/deleting attributes

@@ -1830,27 +1897,27 @@

Adding/deleting attributes

+ + + + +
diff --git a/man/ison_adolescents.Rd b/man/ison_adolescents.Rd index 1628fe70..521ae860 100644 --- a/man/ison_adolescents.Rd +++ b/man/ison_adolescents.Rd @@ -5,7 +5,8 @@ \alias{ison_adolescents} \title{One-mode subset of the adolescent society network (Coleman 1961)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, undirected network of 8 adolescents and 10 friendships ties +\if{html}{\out{
}}\preformatted{#> # The Adolescent Society +#> # A labelled, undirected network of 8 adolescents and 10 friendships ties #> # A tibble: 8 x 1 #> name #> diff --git a/man/ison_algebra.Rd b/man/ison_algebra.Rd index 4a4d3a4a..e1d2903a 100644 --- a/man/ison_algebra.Rd +++ b/man/ison_algebra.Rd @@ -5,7 +5,8 @@ \alias{ison_algebra} \title{Multiplex graph object of friends, social, and task ties (McFarland 2001)} \format{ -\if{html}{\out{
}}\preformatted{#> # A multiplex, weighted, directed network of 16 nodes and 279 arcs +\if{html}{\out{
}}\preformatted{#> # A multiplex, weighted, directed network of 16 nodes and 279 social, tasks, +#> and friends arcs #> # A tibble: 279 x 4 #> from to type weight #> diff --git a/man/ison_brandes.Rd b/man/ison_brandes.Rd index ff23e8c2..138747bd 100644 --- a/man/ison_brandes.Rd +++ b/man/ison_brandes.Rd @@ -5,7 +5,7 @@ \alias{ison_brandes} \title{One-mode and two-mode centrality demonstration networks} \format{ -\if{html}{\out{
}}\preformatted{#> # A undirected network of 11 nodes and 12 ties +\if{html}{\out{
}}\preformatted{#> # A undirected network of 11 nodes and 12 ties #> # A tibble: 11 x 1 #> twomode_type #> diff --git a/man/ison_friends.Rd b/man/ison_friends.Rd index 69353c7d..433db7a3 100644 --- a/man/ison_friends.Rd +++ b/man/ison_friends.Rd @@ -5,7 +5,8 @@ \alias{ison_friends} \title{One-mode Friends character connections (McNulty, 2020)} \format{ -\if{html}{\out{
}}\preformatted{#> # A longitudinal, labelled, weighted, directed network of 650 nodes and 3959 arcs +\if{html}{\out{
}}\preformatted{#> # A longitudinal, labelled, weighted, directed network of 650 nodes and 3959 +#> arcs #> # A tibble: 650 x 1 #> name #> diff --git a/man/ison_greys.Rd b/man/ison_greys.Rd index ac08dd62..8d48dc22 100644 --- a/man/ison_greys.Rd +++ b/man/ison_greys.Rd @@ -5,7 +5,7 @@ \alias{ison_greys} \title{One-mode undirected network of characters hook-ups on Grey's Anatomy TV show} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, undirected network of 53 nodes and 56 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, undirected network of 53 nodes and 56 ties #> # A tibble: 53 x 7 #> name sex race birthyear position season sign #> diff --git a/man/ison_hightech.Rd b/man/ison_hightech.Rd index d5c4e9fa..1e96793c 100644 --- a/man/ison_hightech.Rd +++ b/man/ison_hightech.Rd @@ -5,7 +5,8 @@ \alias{ison_hightech} \title{One-mode multiplex, directed network of managers of a high-tech company (Krackhardt 1987)} \format{ -\if{html}{\out{
}}\preformatted{#> # A multiplex, directed network of 21 nodes and 312 arcs +\if{html}{\out{
}}\preformatted{#> # A multiplex, directed network of 21 nodes and 312 friends, advice, and +#> reports arcs #> # A tibble: 21 x 4 #> age tenure level dept #> diff --git a/man/ison_karateka.Rd b/man/ison_karateka.Rd index 41c0d2cf..550c08a6 100644 --- a/man/ison_karateka.Rd +++ b/man/ison_karateka.Rd @@ -5,7 +5,7 @@ \alias{ison_karateka} \title{One-mode karateka network (Zachary 1977)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, weighted, undirected network of 34 nodes and 78 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, weighted, undirected network of 34 nodes and 78 ties #> # A tibble: 34 x 2 #> name allegiance #> diff --git a/man/ison_koenigsberg.Rd b/man/ison_koenigsberg.Rd index 54656cdd..a0ddac92 100644 --- a/man/ison_koenigsberg.Rd +++ b/man/ison_koenigsberg.Rd @@ -5,7 +5,7 @@ \alias{ison_koenigsberg} \title{One-mode Seven Bridges of Koenigsberg network (Euler 1741)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, multiplex, undirected network of 4 nodes and 7 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, undirected network of 4 nodes and 7 ties #> # A tibble: 4 x 3 #> name lat lon #> diff --git a/man/ison_laterals.Rd b/man/ison_laterals.Rd index e59099b4..23b5c71e 100644 --- a/man/ison_laterals.Rd +++ b/man/ison_laterals.Rd @@ -6,94 +6,94 @@ \title{Two-mode projection examples (Hollway 2021)} \format{ \if{html}{\out{
}}\preformatted{#> $ison_bb -#> # A labelled, two-mode network of 10 nodes and 12 ties +#> # A labelled, two-mode network of 10 nodes and 12 ties #> # A tibble: 10 x 2 #> name type #> #> 1 A FALSE -#> 2 U TRUE -#> 3 B FALSE -#> 4 V TRUE -#> 5 C FALSE -#> 6 W TRUE +#> 2 B FALSE +#> 3 C FALSE +#> 4 D FALSE +#> 5 U TRUE +#> 6 V TRUE #> # i 4 more rows #> # A tibble: 12 x 2 #> from to #> -#> 1 1 2 -#> 2 1 4 -#> 3 3 2 -#> 4 3 6 -#> 5 3 7 -#> 6 3 8 +#> 1 1 5 +#> 2 1 6 +#> 3 2 5 +#> 4 2 7 +#> 5 2 8 +#> 6 2 9 #> # i 6 more rows #> #> $ison_bm -#> # A labelled, two-mode network of 8 nodes and 9 ties +#> # A labelled, two-mode network of 8 nodes and 9 ties #> # A tibble: 8 x 2 #> name type #> #> 1 A FALSE -#> 2 U TRUE -#> 3 B FALSE -#> 4 V TRUE -#> 5 C FALSE -#> 6 W TRUE +#> 2 B FALSE +#> 3 C FALSE +#> 4 D FALSE +#> 5 U TRUE +#> 6 V TRUE #> # i 2 more rows #> # A tibble: 9 x 2 #> from to #> -#> 1 1 2 -#> 2 1 4 -#> 3 3 2 -#> 4 3 6 -#> 5 3 7 -#> 6 5 4 +#> 1 1 5 +#> 2 1 6 +#> 3 2 5 +#> 4 2 7 +#> 5 2 8 +#> 6 3 6 #> # i 3 more rows #> #> $ison_mb -#> # A labelled, two-mode network of 8 nodes and 9 ties +#> # A labelled, two-mode network of 8 nodes and 9 ties #> # A tibble: 8 x 2 #> name type #> #> 1 A FALSE -#> 2 M TRUE -#> 3 B FALSE -#> 4 C FALSE -#> 5 X TRUE -#> 6 Y TRUE +#> 2 B FALSE +#> 3 C FALSE +#> 4 D FALSE +#> 5 M TRUE +#> 6 X TRUE #> # i 2 more rows #> # A tibble: 9 x 2 #> from to #> -#> 1 1 2 -#> 2 3 2 -#> 3 3 5 -#> 4 3 6 -#> 5 4 2 -#> 6 4 5 +#> 1 1 5 +#> 2 2 5 +#> 3 2 6 +#> 4 2 7 +#> 5 3 5 +#> 6 3 6 #> # i 3 more rows #> #> $ison_mm -#> # A labelled, two-mode network of 6 nodes and 6 ties +#> # A labelled, two-mode network of 6 nodes and 6 ties #> # A tibble: 6 x 2 #> name type #> #> 1 A FALSE -#> 2 M TRUE -#> 3 B FALSE -#> 4 C FALSE -#> 5 N TRUE -#> 6 D FALSE +#> 2 B FALSE +#> 3 C FALSE +#> 4 D FALSE +#> 5 M TRUE +#> 6 N TRUE #> # A tibble: 6 x 2 #> from to #> -#> 1 1 2 -#> 2 3 2 -#> 3 3 5 -#> 4 4 2 -#> 5 4 5 -#> 6 6 5 +#> 1 1 5 +#> 2 2 5 +#> 3 2 6 +#> 4 3 5 +#> 5 3 6 +#> 6 4 6 }\if{html}{\out{
}} } \usage{ diff --git a/man/ison_lawfirm.Rd b/man/ison_lawfirm.Rd index 5e8132de..3518817a 100644 --- a/man/ison_lawfirm.Rd +++ b/man/ison_lawfirm.Rd @@ -5,7 +5,8 @@ \alias{ison_lawfirm} \title{One-mode lawfirm (Lazega 2001)} \format{ -\if{html}{\out{
}}\preformatted{#> # A multiplex, directed network of 71 nodes and 2571 arcs +\if{html}{\out{
}}\preformatted{#> # A multiplex, directed network of 71 nodes and 2571 friends, advice, and +#> cowork arcs #> # A tibble: 71 x 7 #> status gender office seniority age practice school #> diff --git a/man/ison_lotr.Rd b/man/ison_lotr.Rd index 52df999d..f3cfc898 100644 --- a/man/ison_lotr.Rd +++ b/man/ison_lotr.Rd @@ -5,7 +5,7 @@ \alias{ison_lotr} \title{One-mode network of Lord of the Rings character interactions} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, complex, undirected network of 36 nodes and 66 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, complex, undirected network of 36 nodes and 66 ties #> # A tibble: 36 x 2 #> name Race #> diff --git a/man/ison_marvel.Rd b/man/ison_marvel.Rd index 2e344d46..4ded2b5c 100644 --- a/man/ison_marvel.Rd +++ b/man/ison_marvel.Rd @@ -8,7 +8,7 @@ \title{Multilevel two-mode affiliation, signed one-mode networks of Marvel comic book characters (Yuksel 2017)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, two-mode network of 194 nodes and 683 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, two-mode network of 194 nodes and 683 ties #> # A tibble: 194 x 2 #> type name #> @@ -31,7 +31,7 @@ book characters (Yuksel 2017)} #> # i 677 more rows }\if{html}{\out{
}} -\if{html}{\out{
}}\preformatted{#> # A labelled, complex, signed, undirected network of 53 nodes and 558 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, complex, signed, undirected network of 53 nodes and 558 ties #> # A tibble: 53 x 10 #> name Gender Appearances Attractive Rich Intellect Omnilingual PowerOrigin #> diff --git a/man/ison_monks.Rd b/man/ison_monks.Rd index d8c6c60a..59fcb206 100644 --- a/man/ison_monks.Rd +++ b/man/ison_monks.Rd @@ -5,7 +5,8 @@ \alias{ison_monks} \title{Multiplex network of three one-mode signed, weighted networks and a three-wave longitudinal network of monks (Sampson 1969)} \format{ -\if{html}{\out{
}}\preformatted{#> # A longitudinal, labelled, multiplex, signed, weighted, directed network of 18 nodes and 463 arcs +\if{html}{\out{
}}\preformatted{#> # A longitudinal, labelled, multiplex, signed, weighted, directed network of 18 +#> nodes and 463 like, esteem, influence, and praise arcs #> # A tibble: 18 x 3 #> name groups left #> diff --git a/man/ison_networkers.Rd b/man/ison_networkers.Rd index 9b17003a..c747489b 100644 --- a/man/ison_networkers.Rd +++ b/man/ison_networkers.Rd @@ -5,7 +5,7 @@ \alias{ison_networkers} \title{One-mode EIES dataset (Freeman and Freeman 1979)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, weighted, directed network of 32 nodes and 440 arcs +\if{html}{\out{
}}\preformatted{#> # A labelled, weighted, directed network of 32 nodes and 440 arcs #> # A tibble: 32 x 3 #> name Discipline Citations #> diff --git a/man/ison_physicians.Rd b/man/ison_physicians.Rd index 092b42ac..6a7595db 100644 --- a/man/ison_physicians.Rd +++ b/man/ison_physicians.Rd @@ -6,7 +6,8 @@ \title{Four multiplex one-mode physician diffusion data (Coleman, Katz, and Menzel, 1966)} \format{ \if{html}{\out{
}}\preformatted{#> $Peoria -#> # A multiplex, directed network of 117 nodes and 543 arcs +#> # A multiplex, directed network of 117 nodes and 543 friendship, advice, and +#> discussion arcs #> # A tibble: 117 x 12 #> adoption specialty conferences journals practice community patients #> @@ -31,7 +32,8 @@ #> # i 537 more rows #> #> $Bloomington -#> # A multiplex, directed network of 50 nodes and 211 arcs +#> # A multiplex, directed network of 50 nodes and 211 friendship, discussion, and +#> advice arcs #> # A tibble: 50 x 12 #> adoption specialty conferences journals practice community patients #> @@ -56,7 +58,8 @@ #> # i 205 more rows #> #> $Quincy -#> # A multiplex, directed network of 44 nodes and 174 arcs +#> # A multiplex, directed network of 44 nodes and 174 advice, discussion, and +#> friendship arcs #> # A tibble: 44 x 12 #> adoption specialty conferences journals practice community patients #> @@ -81,7 +84,8 @@ #> # i 168 more rows #> #> $Galesburg -#> # A multiplex, directed network of 35 nodes and 171 arcs +#> # A multiplex, directed network of 35 nodes and 171 advice, discussion, and +#> friendship arcs #> # A tibble: 35 x 12 #> adoption specialty conferences journals practice community patients #> diff --git a/man/ison_potter.Rd b/man/ison_potter.Rd index bbf24936..e67885de 100644 --- a/man/ison_potter.Rd +++ b/man/ison_potter.Rd @@ -6,7 +6,7 @@ \title{Six complex one-mode support data in Harry Potter books (Bossaert and Meidert 2013)} \format{ \if{html}{\out{
}}\preformatted{#> $book1 -#> # A labelled, complex, directed network of 64 nodes and 47 arcs +#> # A labelled, complex, directed network of 64 nodes and 47 arcs #> # A tibble: 64 x 4 #> name schoolyear gender house #> @@ -29,7 +29,7 @@ #> # i 41 more rows #> #> $book2 -#> # A labelled, complex, directed network of 64 nodes and 110 arcs +#> # A labelled, complex, directed network of 64 nodes and 110 arcs #> # A tibble: 64 x 4 #> name schoolyear gender house #> @@ -52,7 +52,7 @@ #> # i 104 more rows #> #> $book3 -#> # A labelled, complex, directed network of 64 nodes and 104 arcs +#> # A labelled, complex, directed network of 64 nodes and 104 arcs #> # A tibble: 64 x 4 #> name schoolyear gender house #> @@ -75,7 +75,7 @@ #> # i 98 more rows #> #> $book4 -#> # A labelled, complex, directed network of 64 nodes and 49 arcs +#> # A labelled, complex, directed network of 64 nodes and 49 arcs #> # A tibble: 64 x 4 #> name schoolyear gender house #> @@ -98,7 +98,7 @@ #> # i 43 more rows #> #> $book5 -#> # A labelled, complex, directed network of 64 nodes and 160 arcs +#> # A labelled, complex, directed network of 64 nodes and 160 arcs #> # A tibble: 64 x 4 #> name schoolyear gender house #> @@ -121,7 +121,7 @@ #> # i 154 more rows #> #> $book6 -#> # A labelled, complex, directed network of 64 nodes and 74 arcs +#> # A labelled, complex, directed network of 64 nodes and 74 arcs #> # A tibble: 64 x 4 #> name schoolyear gender house #> diff --git a/man/ison_southern_women.Rd b/man/ison_southern_women.Rd index b407c104..77f91dd7 100644 --- a/man/ison_southern_women.Rd +++ b/man/ison_southern_women.Rd @@ -5,7 +5,9 @@ \alias{ison_southern_women} \title{Two-mode southern women (Davis, Gardner and Gardner 1941)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, two-mode network of 32 nodes and 89 ties +\if{html}{\out{
}}\preformatted{#> # Southern Women Data +#> # A labelled, two-mode network of 18 women and 14 social events and 89 +#> participation ties #> # A tibble: 32 x 4 #> type name Surname Title #> diff --git a/man/ison_starwars.Rd b/man/ison_starwars.Rd index 5cfbedfc..008db0cf 100644 --- a/man/ison_starwars.Rd +++ b/man/ison_starwars.Rd @@ -6,7 +6,7 @@ \title{Seven one-mode Star Wars character interactions (Gabasova 2016)} \format{ \if{html}{\out{
}}\preformatted{#> $`Episode I` -#> # A labelled, weighted, undirected network of 38 nodes and 135 ties +#> # A labelled, weighted, undirected network of 38 nodes and 135 ties #> # A tibble: 38 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> @@ -30,7 +30,7 @@ #> # i 129 more rows #> #> $`Episode II` -#> # A labelled, weighted, undirected network of 33 nodes and 101 ties +#> # A labelled, weighted, undirected network of 33 nodes and 101 ties #> # A tibble: 33 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> @@ -54,7 +54,7 @@ #> # i 95 more rows #> #> $`Episode III` -#> # A labelled, weighted, undirected network of 24 nodes and 65 ties +#> # A labelled, weighted, undirected network of 24 nodes and 65 ties #> # A tibble: 24 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> @@ -78,7 +78,7 @@ #> # i 59 more rows #> #> $`Episode IV` -#> # A labelled, weighted, undirected network of 21 nodes and 60 ties +#> # A labelled, weighted, undirected network of 21 nodes and 60 ties #> # A tibble: 21 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> @@ -102,7 +102,7 @@ #> # i 54 more rows #> #> $`Episode V` -#> # A labelled, weighted, undirected network of 21 nodes and 55 ties +#> # A labelled, weighted, undirected network of 21 nodes and 55 ties #> # A tibble: 21 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> @@ -126,7 +126,7 @@ #> # i 49 more rows #> #> $`Episode VI` -#> # A labelled, weighted, undirected network of 20 nodes and 55 ties +#> # A labelled, weighted, undirected network of 20 nodes and 55 ties #> # A tibble: 20 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> @@ -150,7 +150,7 @@ #> # i 49 more rows #> #> $`Episode VII` -#> # A labelled, weighted, undirected network of 27 nodes and 92 ties +#> # A labelled, weighted, undirected network of 27 nodes and 92 ties #> # A tibble: 27 x 11 #> name height mass hair_color skin_color eye_color birth_year sex homeworld #> diff --git a/man/ison_thrones.Rd b/man/ison_thrones.Rd index 78f3c574..f87cea49 100644 --- a/man/ison_thrones.Rd +++ b/man/ison_thrones.Rd @@ -5,7 +5,9 @@ \alias{ison_thrones} \title{One-mode Game of Thrones kinship (Glander 2017)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, multiplex, directed network of 208 characters and 404 kinship arcs +\if{html}{\out{
}}\preformatted{#> # Game of Thrones Kinship +#> # A labelled, multiplex, directed network of 208 characters and 404 kinship +#> arcs #> # A tibble: 208 x 8 #> name male culture house popularity house2 color shape #> diff --git a/man/ison_usstates.Rd b/man/ison_usstates.Rd index 591652de..bb42e747 100644 --- a/man/ison_usstates.Rd +++ b/man/ison_usstates.Rd @@ -5,7 +5,7 @@ \alias{ison_usstates} \title{One-mode undirected network of US state contiguity (Meghanathan 2017)} \format{ -\if{html}{\out{
}}\preformatted{#> # A labelled, undirected network of 50 nodes and 107 ties +\if{html}{\out{
}}\preformatted{#> # A labelled, undirected network of 50 nodes and 107 ties #> # A tibble: 50 x 3 #> name capitol population #> diff --git a/man/make_cran.Rd b/man/make_cran.Rd index 9eac5dc9..b49d70b3 100644 --- a/man/make_cran.Rd +++ b/man/make_cran.Rd @@ -45,8 +45,10 @@ by \href{https://github.com/stocnet/manynet/issues}{raising an issue on Github}. Other makes: \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_read}}, diff --git a/man/make_create.Rd b/man/make_create.Rd index 25c37851..dd7741bd 100644 --- a/man/make_create.Rd +++ b/man/make_create.Rd @@ -147,8 +147,10 @@ create_core(6) Other makes: \code{\link{make_cran}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_read}}, diff --git a/man/make_ego.Rd b/man/make_ego.Rd new file mode 100644 index 00000000..e37ac759 --- /dev/null +++ b/man/make_ego.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/make_create.R +\name{make_ego} +\alias{make_ego} +\alias{create_ego} +\title{Making ego networks through interviewing} +\usage{ +create_ego( + max_alters = Inf, + roster = NULL, + interpreter = FALSE, + interrelater = FALSE +) +} +\arguments{ +\item{max_alters}{The maximum number of alters to collect. +By default infinity, but many name generators will expect a maximum of +e.g. 5 alters to be named.} + +\item{roster}{A vector of node names to offer as potential alters for ego.} + +\item{interpreter}{Logical. If TRUE, then it will ask for which attributes +to collect and give prompts for each attribute for each node in the network. +By default FALSE.} + +\item{interrelater}{Logical. If TRUE, then it will ask for the contacts from +each of the alters perspectives too.} +} +\description{ +This function creates an ego network through interactive interview questions. +Note that it only creates a simplex, directed network. +} +\seealso{ +Other makes: +\code{\link{make_cran}}, +\code{\link{make_create}}, +\code{\link{make_explicit}}, +\code{\link{make_learning}}, +\code{\link{make_motifs}}, +\code{\link{make_play}}, +\code{\link{make_random}}, +\code{\link{make_read}}, +\code{\link{make_stochastic}}, +\code{\link{make_write}} +} +\concept{makes} diff --git a/man/make_explicit.Rd b/man/make_explicit.Rd index 6666325d..aec4bd71 100644 --- a/man/make_explicit.Rd +++ b/man/make_explicit.Rd @@ -32,7 +32,9 @@ See the example for a demonstration. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_read}}, diff --git a/man/make_learning.Rd b/man/make_learning.Rd index 21420dbf..11566d1a 100644 --- a/man/make_learning.Rd +++ b/man/make_learning.Rd @@ -83,7 +83,9 @@ These functions allow learning games to be played upon networks. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_read}}, diff --git a/man/make_motifs.Rd b/man/make_motifs.Rd new file mode 100644 index 00000000..cc81a3ec --- /dev/null +++ b/man/make_motifs.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/make_create.R +\name{make_motifs} +\alias{make_motifs} +\alias{create_motifs} +\title{Making motifs} +\usage{ +create_motifs(n, directed = FALSE) +} +\arguments{ +\item{n}{Given: +\itemize{ +\item A single integer, e.g. \code{n = 10}, +a one-mode network will be created. +\item A vector of two integers, e.g. \code{n = c(5,10)}, +a two-mode network will be created. +\item A manynet-compatible object, +a network of the same dimensions will be created. +}} + +\item{directed}{Logical whether the graph should be directed. +By default \code{directed = FALSE}. +If the opposite direction is desired, +use \code{to_redirected()} on the output of these functions.} +} +\description{ +\code{create_motifs()} is used to create a list of networks that represent the +subgraphs or motifs corresponding to a certain number of nodes and direction. +Note that currently only \code{n==2} to \code{n==4} is implemented, +and the latter only for undirected networks. +} +\seealso{ +Other makes: +\code{\link{make_cran}}, +\code{\link{make_create}}, +\code{\link{make_ego}}, +\code{\link{make_explicit}}, +\code{\link{make_learning}}, +\code{\link{make_play}}, +\code{\link{make_random}}, +\code{\link{make_read}}, +\code{\link{make_stochastic}}, +\code{\link{make_write}} +} +\concept{makes} diff --git a/man/make_play.Rd b/man/make_play.Rd index b76c94ac..8c3119a1 100644 --- a/man/make_play.Rd +++ b/man/make_play.Rd @@ -208,8 +208,10 @@ This can be used in in SEI, SEIS, SEIR, and SEIRS models. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_random}}, \code{\link{make_read}}, \code{\link{make_stochastic}}, diff --git a/man/make_random.Rd b/man/make_random.Rd index 299756fa..cb144dfb 100644 --- a/man/make_random.Rd +++ b/man/make_random.Rd @@ -122,8 +122,10 @@ San Francisco: Jossey-Bass. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_read}}, \code{\link{make_stochastic}}, diff --git a/man/make_read.Rd b/man/make_read.Rd index 73d3af73..6f7fe770 100644 --- a/man/make_read.Rd +++ b/man/make_read.Rd @@ -102,8 +102,10 @@ you will need to unpack them and convert them one by one. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_stochastic}}, diff --git a/man/make_stochastic.Rd b/man/make_stochastic.Rd index 164755c2..f2006a85 100644 --- a/man/make_stochastic.Rd +++ b/man/make_stochastic.Rd @@ -127,8 +127,10 @@ Barabasi, Albert-Laszlo, and Reka Albert. 1999. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_read}}, diff --git a/man/make_write.Rd b/man/make_write.Rd index e78e6720..40f9d8b4 100644 --- a/man/make_write.Rd +++ b/man/make_write.Rd @@ -77,8 +77,10 @@ by \href{https://github.com/stocnet/manynet/issues}{raising an issue on Github}. Other makes: \code{\link{make_cran}}, \code{\link{make_create}}, +\code{\link{make_ego}}, \code{\link{make_explicit}}, \code{\link{make_learning}}, +\code{\link{make_motifs}}, \code{\link{make_play}}, \code{\link{make_random}}, \code{\link{make_read}}, diff --git a/man/manip_net.Rd b/man/manip_net.Rd new file mode 100644 index 00000000..4002883c --- /dev/null +++ b/man/manip_net.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/manip_nodes.R +\name{manip_net} +\alias{manip_net} +\alias{add_info} +\title{Modifying network data} +\usage{ +add_info(.data, ...) +} +\arguments{ +\item{.data}{An object of a manynet-consistent class: +\itemize{ +\item matrix (adjacency or incidence) from \code{{base}} R +\item edgelist, a data frame from \code{{base}} R or tibble from \code{{tibble}} +\item igraph, from the \code{{igraph}} package +\item network, from the \code{{network}} package +\item tbl_graph, from the \code{{tidygraph}} package +}} + +\item{...}{Named attributes. The following are currently recognised: +"name", "year", and "doi" of the network, +"collection" or "mode" of the network +("survey", "interview","sensor","observation","archival", or "simulation"), +"nodes" (a vector of the names of the nodes) or "vertex1"/"vertex2", +"ties" or "edge.pos"/"edge.neg" for defining the ties.} +} +\description{ +These functions allow users to add and edit information about the network +itself. +This includes the name, year, and mode of collection of the network, +as well as definitions of the nodes and ties in the network. +Where available, this information is printed for tidygraph-class objects, +and can be used for printing a grand table in the \code{{grand}} package. +} +\examples{ +add_info(ison_algebra, name = "Algebra") +} diff --git a/man/map_themes.Rd b/man/map_themes.Rd index 0a499df4..288176ee 100644 --- a/man/map_themes.Rd +++ b/man/map_themes.Rd @@ -2,12 +2,15 @@ % Please edit documentation in R/map_theme.R \name{map_themes} \alias{map_themes} +\alias{set_manynet_theme} \alias{theme_iheid} \alias{theme_ethz} \alias{theme_uzh} \alias{theme_rug} \title{Many themes} \usage{ +set_manynet_theme(theme = "default") + theme_iheid(base_size = 12, base_family = "serif") theme_ethz(base_size = 12, base_family = "sans") @@ -17,6 +20,9 @@ theme_uzh(base_size = 12, base_family = "sans") theme_rug(base_size = 12, base_family = "mono") } \arguments{ +\item{theme}{String naming a theme. +By default "default".} + \item{base_size}{Font size, by default 12.} \item{base_family}{Font family, by default "sans".} diff --git a/man/measure_central_eigen.Rd b/man/measure_central_eigen.Rd index 159f1d3c..3f51a719 100644 --- a/man/measure_central_eigen.Rd +++ b/man/measure_central_eigen.Rd @@ -6,6 +6,8 @@ \alias{node_power} \alias{node_alpha} \alias{node_pagerank} +\alias{node_authority} +\alias{node_hub} \alias{tie_eigenvector} \alias{net_eigenvector} \title{Measures of eigenvector-like centrality and centralisation} @@ -18,6 +20,10 @@ node_alpha(.data, alpha = 0.85) node_pagerank(.data) +node_authority(.data) + +node_hub(.data) + tie_eigenvector(.data, normalized = TRUE) net_eigenvector(.data, normalized = TRUE) @@ -57,6 +63,8 @@ These functions calculate common eigenvector-related centrality measures for one \item \code{node_power()} measures the Bonacich, beta, or power centrality of nodes in a network. \item \code{node_alpha()} measures the alpha or Katz centrality of nodes in a network. \item \code{node_pagerank()} measures the pagerank centrality of nodes in a network. +\item \code{node_hub()} measures how well nodes in a network serve as hubs pointing to many authorities. +\item \code{node_authority()} measures how well nodes in a network serve as authorities from many hubs. \item \code{tie_eigenvector()} measures the eigenvector centrality of ties in a network. \item \code{net_eigenvector()} measures the eigenvector centralization for a network. } @@ -139,6 +147,11 @@ Bonacich, P. and Lloyd, P. 2001. Brin, Sergey and Page, Larry. 1998. "The anatomy of a large-scale hypertextual web search engine". \emph{Proceedings of the 7th World-Wide Web Conference}. Brisbane, Australia. + +Kleinberg, Jon. 1999. +"Authoritative sources in a hyperlinked environment". +\emph{Journal of the ACM} 46(5): 604–632. +\doi{110.1145/324133.324140}. } \seealso{ Other centrality: diff --git a/man/measure_closure.Rd b/man/measure_closure.Rd index 0aff6774..9890f888 100644 --- a/man/measure_closure.Rd +++ b/man/measure_closure.Rd @@ -7,6 +7,7 @@ \alias{net_transitivity} \alias{node_transitivity} \alias{net_equivalency} +\alias{node_equivalency} \alias{net_congruency} \title{Measures of network closure} \usage{ @@ -20,6 +21,8 @@ node_transitivity(.data) net_equivalency(.data) +node_equivalency(.data) + net_congruency(.data, object2) } \arguments{ @@ -74,6 +77,7 @@ node_reciprocity(to_unweighted(ison_networkers)) net_transitivity(ison_adolescents) node_transitivity(ison_adolescents) net_equivalency(ison_southern_women) +node_equivalency(ison_southern_women) } \references{ Robins, Garry L, and Malcolm Alexander. 2004. diff --git a/man/motif_net.Rd b/man/motif_net.Rd index 75765963..6c46724f 100644 --- a/man/motif_net.Rd +++ b/man/motif_net.Rd @@ -4,6 +4,7 @@ \alias{motif_net} \alias{net_by_dyad} \alias{net_by_triad} +\alias{net_by_quad} \alias{net_by_mixed} \title{Motifs at the network level} \source{ @@ -14,6 +15,8 @@ net_by_dyad(.data) net_by_triad(.data) +net_by_quad(.data) + net_by_mixed(.data, object2) } \arguments{ @@ -41,6 +44,7 @@ a one-mode and a two-mode network. \examples{ net_by_dyad(manynet::ison_algebra) net_by_triad(manynet::ison_adolescents) +net_by_quad(ison_southern_women) marvel_friends <- to_unsigned(ison_marvel_relationships, "positive") (mixed_cen <- net_by_mixed(marvel_friends, ison_marvel_teams)) } diff --git a/man/motif_node.Rd b/man/motif_node.Rd index 8cbea8c5..751c3894 100644 --- a/man/motif_node.Rd +++ b/man/motif_node.Rd @@ -3,6 +3,7 @@ \name{motif_node} \alias{motif_node} \alias{node_by_tie} +\alias{node_by_dyad} \alias{node_by_triad} \alias{node_by_quad} \alias{node_by_path} @@ -10,6 +11,8 @@ \usage{ node_by_tie(.data) +node_by_dyad(.data) + node_by_triad(.data) node_by_quad(.data) @@ -41,52 +44,19 @@ in motifs of four nodes. of each node to every other node in the network. } } -\section{Quad census}{ - -The quad census uses the \code{{oaqc}} package to do -the heavy lifting of counting the number of each orbits. -See \code{vignette('oaqc')}. -However, our function relabels some of the motifs -to avoid conflicts and improve some consistency with -other census-labelling practices. -The letter-number pairing of these labels indicate -the number and configuration of ties. -For now, we offer a rough translation:\tabular{ll}{ - migraph \tab Ortmann and Brandes \cr - E4 \tab co-K4 \cr - I40, I41 \tab co-diamond \cr - H4 \tab co-C4 \cr - L42, L41, L40 \tab co-paw \cr - D42, D40 \tab co-claw \cr - U42, U41 \tab P4 \cr - Y43, Y41 \tab claw \cr - P43, P42, P41 \tab paw \cr - 04 \tab C4 \cr - Z42, Z43 \tab diamond \cr - X4 \tab K4 \cr -} - - -See also \href{https://www.graphclasses.org/smallgraphs.html#nodes4}{this list of graph classes}. -} - \examples{ task_eg <- to_named(to_uniplex(ison_algebra, "tasks")) (tie_cen <- node_by_tie(task_eg)) +node_by_dyad(ison_networkers) (triad_cen <- node_by_triad(task_eg)) -node_by_quad(manynet::ison_southern_women) -node_by_path(manynet::ison_adolescents) -node_by_path(manynet::ison_southern_women) +node_by_quad(ison_southern_women) +node_by_path(ison_adolescents) +node_by_path(ison_southern_women) } \references{ Davis, James A., and Samuel Leinhardt. 1967. “\href{https://files.eric.ed.gov/fulltext/ED024086.pdf}{The Structure of Positive Interpersonal Relations in Small Groups}.” 55. -Ortmann, Mark, and Ulrik Brandes. 2017. -“Efficient Orbit-Aware Triad and Quad Census in Directed and Undirected Graphs.” -\emph{Applied Network Science} 2(1):13. -\doi{10.1007/s41109-017-0027-2}. - Dijkstra, Edsger W. 1959. "A note on two problems in connexion with graphs". \emph{Numerische Mathematik} 1, 269-71. diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 0776afcb..55b0b17b 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -53,6 +53,8 @@ reference: directed and undirected, one-mode and two-mode networks. contents: - make_explicit + - make_ego + - make_motifs - make_create - starts_with("generate_") - subtitle: "Playing" diff --git a/tests/testthat/helper-manynet.R b/tests/testthat/helper-manynet.R index ea092d0c..82a391d3 100644 --- a/tests/testthat/helper-manynet.R +++ b/tests/testthat/helper-manynet.R @@ -1,3 +1,5 @@ +options(manynet_verbosity = "quiet") + collect_functions <- function(pattern, package = "manynet"){ getNamespaceExports(package)[grepl(pattern, getNamespaceExports(package))] } diff --git a/tests/testthat/test-measure_closure.R b/tests/testthat/test-measure_closure.R index 45228b94..c0a17dd3 100644 --- a/tests/testthat/test-measure_closure.R +++ b/tests/testthat/test-measure_closure.R @@ -29,6 +29,12 @@ test_that("two-mode object clustering is reported correctly",{ expect_output(print(net_equivalency(ison_southern_women))) }) +test_that("node_equivalency works correctly",{ + expect_equal(as.numeric(node_equivalency(ison_laterals$ison_mm)), + c(0,1,1,0,0.5,0.5), tolerance = 0.001) + expect_s3_class(node_equivalency(ison_southern_women), "node_measure") +}) + test_that("three-mode clustering calculated correctly",{ mat1 <- manynet::create_ring(c(10,5)) mat2 <- manynet::create_ring(c(5,8)) diff --git a/tests/testthat/test-motif_census.R b/tests/testthat/test-motif_census.R index dff3e7d5..26b05bfe 100644 --- a/tests/testthat/test-motif_census.R +++ b/tests/testthat/test-motif_census.R @@ -21,8 +21,6 @@ test_that("net_dyad census works", { expect_equal(test[[2]], 18) expect_equal(names(test), c("Mutual", "Null")) expect_s3_class(test, "network_motif") - # Error - expect_error(net_by_dyad(ison_southern_women)) }) test <- net_by_triad(ison_adolescents) @@ -38,7 +36,7 @@ test_that("net_triad census works", { test <- node_by_quad(ison_southern_women) test_that("node quad census works", { expect_s3_class(test, "node_motif") - expect_equal(test[1,1], 1463) + expect_equal(test[1,1], 1241) }) test_that("net_mixed census works", {