diff --git a/NAMESPACE b/NAMESPACE index e2a2f8d..b111ecf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,6 +6,7 @@ S3method(author_with,cranly_network) S3method(build_dependence_tree,cranly_network) S3method(build_network,cranly_db) S3method(depends,cranly_network) +S3method(enhances,cranly_network) S3method(imports,cranly_network) S3method(linking_to,cranly_network) S3method(package_by,cranly_network) @@ -26,6 +27,7 @@ export(clean_up_author) export(clean_up_directives) export(compute_dependence_tree) export(depends) +export(enhances) export(imports) export(linking_to) export(package_by) diff --git a/R/cranly-package.R b/R/cranly-package.R index 6c5f815..7c4a203 100644 --- a/R/cranly-package.R +++ b/R/cranly-package.R @@ -131,6 +131,11 @@ linking_to <- function(x, package = NULL, exact = FALSE) { UseMethod("linking_to") } +#' @rdname package_by +#' @export +enhances <- function(x, package = NULL, exact = FALSE) { + UseMethod("enhances") +} #' \code{build_network} method for an object diff --git a/R/extractors.R b/R/extractors.R index d38aa8a..c98fddc 100644 --- a/R/extractors.R +++ b/R/extractors.R @@ -9,7 +9,7 @@ package_by.cranly_network <- function(x, author = NULL, exact = FALSE) { if (any(is.infinite(author))) { return(unique(unlist(x$nodes$package))) } - perspective <- attr(x, "perspective") + if (exact) { str <- paste(author, collapse = "$|^") str <- paste0("^", str, "$") @@ -24,7 +24,7 @@ package_by.cranly_network <- function(x, author = NULL, exact = FALSE) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } @@ -38,7 +38,7 @@ package_with.cranly_network <- function(x, name = NULL, exact = FALSE) { if (any(is.infinite(name))) { return(unique(unlist(x$nodes$package))) } - perspective <- attr(x, "perspective") + ## Escape . name <- gsub("\\.", "\\\\.", name) if (exact) { @@ -49,14 +49,15 @@ package_with.cranly_network <- function(x, name = NULL, exact = FALSE) { str <- paste(name, collapse = "|") } package <- unlist(x$nodes$package) - inds <- grep(str, package, ignore.case = !exact, perl = TRUE) + + inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) out <- unique(package[inds]) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } @@ -70,7 +71,7 @@ author_of.cranly_network <- function(x, package = NULL, exact = FALSE) { if (any(is.infinite(package))) { return(unique(unlist(x$nodes$author))) } - perspective <- attr(x, "perspective") + package <- gsub("\\.", "\\\\.", package) if (exact) { str <- paste(package, collapse = "$(?!\\.)|^") @@ -79,14 +80,15 @@ author_of.cranly_network <- function(x, package = NULL, exact = FALSE) { else { str <- paste(package, collapse = "|") } - inds <- grep(str, x$nodes$package, ignore.case = !exact, perl = TRUE) + + inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) out <- unique(unlist(x$nodes[inds, "author"])) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } @@ -99,7 +101,7 @@ author_with.cranly_network <- function(x, name = NULL, exact = FALSE) { if (any(is.infinite(name))) { return(unique(unlist(x$nodes$author))) } - perspective <- attr(x, "perspective") + if (exact) { str <- paste(name, collapse = "$|^") str <- paste0("^", str, "$") @@ -108,27 +110,31 @@ author_with.cranly_network <- function(x, name = NULL, exact = FALSE) { str <- paste(name, collapse = "|") } authors <- unlist(x$nodes$author) - inds <- grep(str, authors, ignore.case = !exact) + inds <- sapply(x$nodes$author, function(z) any(grepl(str, z, ignore.case = !exact))) out <- unique(authors[inds]) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } #' @rdname package_by #' @export suggests.cranly_network <- function(x, package = NULL, exact = FALSE) { + if (attr(x, "perspective") == "author") { + stop(match.call()[[1]], " is not designed for cranly_network objects with perspective = 'author'") + } + if (is.null(package)) { return(NULL) # return(unlist(x$nodes$Package)) } if (any(is.infinite(package))) { return(unique(unlist(x$nodes$suggests))) } - perspective <- attr(x, "perspective") + package <- gsub("\\.", "\\\\.", package) if (exact) { str <- paste(package, collapse = "$(?!\\.)|^") @@ -137,15 +143,16 @@ suggests.cranly_network <- function(x, package = NULL, exact = FALSE) { else { str <- paste(package, collapse = "|") } + inds <- grep(str, x$nodes$package, ignore.case = !exact, perl = TRUE) - ## inds <- sapply(x$nodes$Package, function(x) any(grepl(str, x))) + ## inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) out <- unique(unlist(x$nodes[inds, "suggests"])) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } @@ -153,13 +160,17 @@ suggests.cranly_network <- function(x, package = NULL, exact = FALSE) { #' @rdname package_by #' @export imports.cranly_network <- function(x, package = NULL, exact = FALSE) { + if (attr(x, "perspective") == "author") { + stop(match.call()[[1]], " is not designed for cranly_network objects with perspective = 'author'") + } + if (is.null(package)) { return(NULL) # return(unlist(x$nodes$Package)) } if (any(is.infinite(package))) { return(unique(unlist(x$nodes$imports))) } - perspective <- attr(x, "perspective") + package <- gsub("\\.", "\\\\.", package) if (exact) { str <- paste(package, collapse = "$(?!\\.)|^") @@ -168,28 +179,34 @@ imports.cranly_network <- function(x, package = NULL, exact = FALSE) { else { str <- paste(package, collapse = "|") } + inds <- grep(str, x$nodes$package, ignore.case = !exact, perl = TRUE) - ## inds <- sapply(x$nodes$Package, function(x) any(grepl(str, x))) + ## inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) + out <- unique(unlist(x$nodes[inds, "imports"])) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } #' @rdname package_by #' @export depends.cranly_network <- function(x, package = NULL, exact = FALSE) { + if (attr(x, "perspective") == "author") { + stop(match.call()[[1]], " is not designed for cranly_network objects with perspective = 'author'") + } + if (is.null(package)) { return(NULL) # return(unlist(x$nodes$Package)) } if (any(is.infinite(package))) { return(unique(unlist(x$nodes$depends))) } - perspective <- attr(x, "perspective") + package <- gsub("\\.", "\\\\.", package) if (exact) { str <- paste(package, collapse = "$(?!\\.)|^") @@ -198,15 +215,17 @@ depends.cranly_network <- function(x, package = NULL, exact = FALSE) { else { str <- paste(package, collapse = "|") } + inds <- grep(str, x$nodes$package, ignore.case = !exact, perl = TRUE) - ## inds <- sapply(x$nodes$Package, function(x) any(grepl(str, x))) + ## inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) + out <- unique(unlist(x$nodes[inds, "depends"])) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) } } @@ -214,13 +233,17 @@ depends.cranly_network <- function(x, package = NULL, exact = FALSE) { #' @rdname package_by #' @export linking_to.cranly_network <- function(x, package = NULL, exact = FALSE) { + if (attr(x, "perspective") == "author") { + stop(match.call()[[1]], " is not designed for cranly_network objects with perspective = 'author'") + } + if (is.null(package)) { return(NULL) # return(unlist(x$nodes$Package)) } if (any(is.infinite(package))) { return(unique(unlist(x$nodes$linkingto))) } - perspective <- attr(x, "perspective") + package <- gsub("\\.", "\\\\.", package) if (exact) { str <- paste(package, collapse = "$(?!\\.)|^") @@ -229,15 +252,53 @@ linking_to.cranly_network <- function(x, package = NULL, exact = FALSE) { else { str <- paste(package, collapse = "|") } + inds <- grep(str, x$nodes$package, ignore.case = !exact, perl = TRUE) - ## inds <- sapply(x$nodes$Package, function(x) any(grepl(str, x))) + ## inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) out <- unique(unlist(x$nodes[inds, "linkingto"])) if (all(is.na(out)) | !length(out)) { return(NULL) } else { - return(out) + return(out[!is.na(out)]) + } +} + + +#' @rdname package_by +#' @export +enhances.cranly_network <- function(x, package = NULL, exact = FALSE) { + if (attr(x, "perspective") == "author") { + stop(match.call()[[1]], " is not designed for cranly_network objects with perspective = 'author'") + } + + if (is.null(package)) { + return(NULL) # return(unlist(x$nodes$Package)) + } + + if (any(is.infinite(package))) { + return(unique(unlist(x$nodes$enhances))) + } + + package <- gsub("\\.", "\\\\.", package) + if (exact) { + str <- paste(package, collapse = "$(?!\\.)|^") + str <- paste0("^", str, "$(?!\\.)") + } + else { + str <- paste(package, collapse = "|") + } + + inds <- grep(str, x$nodes$package, ignore.case = !exact, perl = TRUE) + ## inds <- sapply(x$nodes$package, function(z) any(grepl(str, z, ignore.case = !exact, perl = TRUE))) + out <- unique(unlist(x$nodes[inds, "enhances"])) + + if (all(is.na(out)) | !length(out)) { + return(NULL) + } + else { + return(out[!is.na(out)]) } } diff --git a/man/as.igraph.cranly_network.Rd b/man/as.igraph.cranly_network.Rd index cc28d7b..8ebed70 100644 --- a/man/as.igraph.cranly_network.Rd +++ b/man/as.igraph.cranly_network.Rd @@ -32,13 +32,13 @@ undirected network of authors. \examples{ \dontrun{ -data("cran_sample", package = "cranly") +#' cran_db <- clean_CRAN_db() ## Package directives network -package_network <- build_network(object = cran_sample, perspective = "package") +package_network <- build_network(object = cran_db, perspective = "package") igraph::as.igraph(package_network) ## Author collaboration network -author_network <- build_network(object = cran_sample, perspective = "author") +author_network <- build_network(object = cran_db, perspective = "author") igraph::as.igraph(author_network) } diff --git a/man/cran_sample.Rd b/man/cran_sample.Rd deleted file mode 100644 index fe225d9..0000000 --- a/man/cran_sample.Rd +++ /dev/null @@ -1,41 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data.R -\docType{data} -\name{cran_sample} -\alias{cran_sample} -\title{Cleaned and processed CRAN package metadata from 30 March 2018} -\format{An object of class \code{cranly_db} (inherits from \code{data.frame}) with 1000 rows and 64 columns.} -\usage{ -cran_sample -} -\description{ -This is a random sample of 1000 R packages from a processed version -of the result of a \code{\link[tools]{CRAN_package_db}()} call on -30 March 2018. Specifically, the resulting data frame was passed to -the \code{\link{clean_CRAN_db}} function and only the following -variables have been kept: -} -\details{ -\itemize{ - \item package - \item version - \item date - \item url - \item depends - \item imports - \item suggests - \item enhances - \item linkingto - \item license - \item author - \item maintainer - \item contact - \item md5sum -} - - - -The author names have been converted to ASCII using transliteration -through the \code{\link{iconv}} function. -} -\keyword{datasets} diff --git a/man/package_by.Rd b/man/package_by.Rd index 6bf1aaa..e14df6d 100644 --- a/man/package_by.Rd +++ b/man/package_by.Rd @@ -9,6 +9,7 @@ \alias{imports} \alias{depends} \alias{linking_to} +\alias{enhances} \alias{package_by.cranly_network} \alias{package_with.cranly_network} \alias{author_of.cranly_network} @@ -17,6 +18,7 @@ \alias{imports.cranly_network} \alias{depends.cranly_network} \alias{linking_to.cranly_network} +\alias{enhances.cranly_network} \title{Find packages and authors by authors or packages with names matching a specific string} \usage{ package_by(x, author = NULL, exact = FALSE) @@ -35,6 +37,8 @@ depends(x, package = NULL, exact = FALSE) linking_to(x, package = NULL, exact = FALSE) +enhances(x, package = NULL, exact = FALSE) + \method{package_by}{cranly_network}(x, author = NULL, exact = FALSE) \method{package_with}{cranly_network}(x, name = NULL, exact = FALSE) @@ -50,6 +54,8 @@ linking_to(x, package = NULL, exact = FALSE) \method{depends}{cranly_network}(x, package = NULL, exact = FALSE) \method{linking_to}{cranly_network}(x, package = NULL, exact = FALSE) + +\method{enhances}{cranly_network}(x, package = NULL, exact = FALSE) } \arguments{ \item{x}{a \code{\link{cranly_network}} object} @@ -67,9 +73,9 @@ Find packages and authors by authors or packages with names matching a specific } \examples{ \dontrun{ -data("cran_sample", package = "cranly") +cran_db <- clean_CRAN_db() ## Using a package directives network -package_network <- build_network(cran_sample) +package_network <- build_network(cran_db) ## Find all packages containing glm in their name package_with(package_network, name = "glm") ## Find all authors of packages containing brglm in their name @@ -88,7 +94,7 @@ imports(package_network, package = "Rcpp", exact = TRUE) linking_to(package_network, package = "RcppArmadillo", exact = TRUE) ## Using an author collaboration network -author_network <- build_network(cran_sample, perspective = "author") +author_network <- build_network(cran_db, perspective = "author") ## Find all packages containing glm in their name package_with(author_network, name = "glm") ## Find all authors of packages containing brglm in their name diff --git a/man/plot.cranly_network.Rd b/man/plot.cranly_network.Rd index 359ddc3..45abae8 100644 --- a/man/plot.cranly_network.Rd +++ b/man/plot.cranly_network.Rd @@ -53,15 +53,15 @@ Interactive visualization of a package or author \code{\link{cranly_network}} } \examples{ \dontrun{ -data("cran_sample", package = "cranly") -package_network <- build_network(cran_sample) +cran_db <- clean_CRAN_db() +package_network <- build_network(cran_db) ## The package directives network of all users with Ioannis in -## their name from the CRAN database subset cran_sample +## their name from the CRAN database subset cran_db plot(package_network, author = "Ioannis") ## The package directives network of "Achim Zeileis" plot(package_network, author = "Achim Zeileis") -author_network <- build_network(cran_sample, perspective = "author") +author_network <- build_network(cran_db, perspective = "author") plot(author_network, author = "Ioannis", title = TRUE) } } diff --git a/man/plot.summary_cranly_network.Rd b/man/plot.summary_cranly_network.Rd index 799084c..9a5aa44 100644 --- a/man/plot.summary_cranly_network.Rd +++ b/man/plot.summary_cranly_network.Rd @@ -24,16 +24,16 @@ Top-n package or author barplots according to a range of network statistics \examples{ \dontrun{ -data("cran_sample", package = "cranly") +cran_db <- clean_CRAN_db() ## package network -package_network <- build_network(cran_sample) +package_network <- build_network(cran_db) package_summaries <- summary(package_network) plot(package_summaries, according_to = "n_imported_by", top = 30) plot(package_summaries, according_to = "n_depended_by", top = 30) plot(package_summaries, according_to = "page_rank", top = 30) ## author network -author_network <- build_network(cran_sample, perspective = "author") +author_network <- build_network(cran_db, perspective = "author") author_summaries <- summary(author_network) plot(author_summaries, according_to = "n_collaborators", top = 30) plot(author_summaries, according_to = "n_packages", top = 30) diff --git a/tests/testthat/test-extractors.R b/tests/testthat/test-extractors.R index 2c08e8c..f3a3467 100644 --- a/tests/testthat/test-extractors.R +++ b/tests/testthat/test-extractors.R @@ -5,16 +5,16 @@ package_network <- build_network(object = cran_db) author_network <- build_network(object = cran_db, perspective = "author") test_that("author_of returnes same value when applied to a package network and when applied to an author network", - expect_equal(sort(author_of(package_network, "MASS")), - sort(author_of(author_network, "MASS"))) + expect_equal(sort(author_of(package_network, "MASS", exact = TRUE)), + sort(author_of(author_network, "MASS", exact = TRUE))) ) test_that("package_by with exact = TRUE returns correct results", { expect_true(all(package_by(package_network, "Ioannis Kosmidis", exact = TRUE) %in% - c("betareg", "brglm", "brglm2", "enrichwith", "PlackettLuce", + c("betareg", "brglm", "brglm2", "cranly", "enrichwith", "PlackettLuce", "profileModel", "trackeR"))) expect_true(all(package_by(author_network, "Ioannis Kosmidis", exact = TRUE) %in% - c("betareg", "brglm", "brglm2", "enrichwith", "PlackettLuce", + c("betareg", "brglm", "brglm2", "cranly", "enrichwith", "PlackettLuce", "profileModel", "trackeR"))) } ) @@ -24,3 +24,11 @@ test_that("author_of with exact = TRUE returns correct results", { } ) +test_that("suggets, imports, linking_to works", { + expect_true(all(suggests(package_network, "cranly", exact = TRUE) == c("testthat", "knitr", "rmarkdown", "covr"))) + expect_equal(imports(package_network, "cranly", exact = TRUE), + c("visNetwork", "colorspace", "igraph", "magrittr", "stringr", + "ggplot2", "countrycode")) + expect_equal(linking_to(package_network, "RcppArmadillo", exact = TRUE), + "Rcpp") +})