Skip to content

Instantly share code, notes, and snippets.

@ateucher
Last active December 21, 2017 19:01
Show Gist options
  • Save ateucher/8c1a16378cf9224d1b270512b7147080 to your computer and use it in GitHub Desktop.
Save ateucher/8c1a16378cf9224d1b270512b7147080 to your computer and use it in GitHub Desktop.
Get and plot package dependencies using metacran services
#' Search for packages that are dependent on a particular package
#'
#' @param pkg The name of the package
#' @param size Maximum number of dependencies to search for
#' @param ... Additional argumentst passed on to \link{seer}{see}
#'
#' @return A \code{tibble} with columns \code{package} and \code{relationship}
#' @export
#'
#' @examples
get_pkg_deps <- function(pkg, size = 10, ...) {
if (!require("seer")) stop("You need to install the seer package from httsp://github.com/metacran/seer")
if (!requireNamespace("purrr")) stop("You need to install the purrr package")
matches <- seer::see(pkg, size = size, ...)
regex_string <- paste0("(^|\\s|,)", pkg, "(,|\\s|$)")
purrr::map_df(matches$hits$hits,
~ {
id <- .x[["_id"]]
src <- .x[["_source"]]
if (id == pkg) {
return(list(package = pkg, relationship = "Package"))
}
depends <- isTRUE(grepl(regex_string, src[["Depends"]]))
imports <- isTRUE(grepl(regex_string, src[["Imports"]]))
suggests <- isTRUE(grepl(regex_string, src[["Suggests"]]))
relationships <- c(Depends = depends, Imports = imports, Suggests = suggests)
if (!any(relationships)) return(NULL)
list(package = id, relationship = names(relationships[relationships]))
})
}
#' Plot CRAN download logs of a package along with packages that depend on it.
#'
#' @param pkg The name of the package
#' @param when time period (one of "last-day", "last-week", or "last-month")
#' @param from Start date, in yyyy-mm-dd format, or last-day. It is ignored if when is given.
#' @param to End date, in yyyy-mm-dd format, or last-day. It is ignored if when is given.
#' @param by either "package" to show all packages on the plot, or "relationship"
#' to group dependent packages by their relationship to the package ("Depends", "Imports", and "Suggests")
#' @param type Type of graph to dispaly - either "line" or "area"
#' @param size Maximum number of dependencies to search for
#' @param ... Additional argumentst passed on to \link{seer}{see}
#'
#' @return a ggplot2 object
#' @export
#'
#' @examples
plot_pkg_deps <- function(pkg, when = "last-month", from, to,
by = c("package", "relationship"),
type = c("area", "line"), size = 10, ...) {
if (!requireNamespace("cranlogs")) stop("You need to install the cranlogs package from httsp://github.com/metacran/cranlogs")
if (!requireNamespace("dplyr")) stop("You need to install the dplyr package")
if (!requireNamespace("ggplot2")) stop("You need to install the ggplot2 package")
deps <- get_pkg_deps(pkg, size = size, ...)
by <- match.arg(by)
type <- match.arg(type)
downloads <- cranlogs::cran_downloads(unique(deps$package), when = when, from, to)
downloads <- dplyr::left_join(downloads, deps, by = "package")
if (by == "relationship") {
downloads <- dplyr::group_by_(downloads, ~ relationship, ~ date)
downloads <- dplyr::summarize_(downloads, count = ~ sum(count))
}
if (type == "line") {
colour_breaks <- switch(by,
"package" = c(pkg, setdiff(deps$package, pkg)),
"relationship" = c("Package", "Depends", "Imports", "Suggests"))
p <- ggplot2::ggplot(downloads, ggplot2::aes_string(x = "date", y = "count", colour = by, linetype = "relationship")) +
ggplot2::geom_line() +
ggplot2::scale_linetype_manual(values = c(Package = "solid", Depends = "longdash", Imports = "dashed", Suggests = "dotted"),
breaks = c("Package", "Depends", "Imports", "Suggests")) +
ggplot2::scale_colour_discrete(breaks = colour_breaks) +
ggplot2::labs(title = paste("CRAN downloads for package:", pkg))
} else {
pkg_subset <- ifelse(by == "package", pkg, "Package")
p <- ggplot2::ggplot(downloads[downloads[[by]] != pkg_subset, ],
ggplot2::aes_string(x = "date", y = "count", fill = by)) +
ggplot2::geom_area() +
ggplot2::geom_line(data = downloads[downloads[[by]] == pkg_subset, ],
ggplot2::aes_string(x = "date", y = "count", linetype = by),
inherit.aes = FALSE) +
ggplot2::scale_linetype_manual(values = "solid", labels = pkg, name = "Package") +
ggplot2::labs(title = paste("CRAN downloads for package:", pkg),
fill = "Reverse Dependencies") +
ggplot2::guides(linetype = ggplot2::guide_legend(order = 1), fill = ggplot2::guide_legend(order = 2))
}
p
}
# install_github("metacran/seer")
library(devtools)
source_gist("https://gist.github.com/ateucher/8c1a16378cf9224d1b270512b7147080", filename = "package_deps.R")
#> Using GitHub PAT from envvar GITHUB_PAT
#> Sourcing https://gist.githubusercontent.com/ateucher/8c1a16378cf9224d1b270512b7147080/raw/6db9b5e7225aa92b7f2dac390471b2f5a7996c7c/package_deps.R
#> SHA-1 hash of file is 89d58320b3c892a06534c830c20d36bf1d984606

get_pkg_deps("rmapshaper")
#> Loading required package: seer
#> Loading required namespace: purrr
#> # A tibble: 7 x 2
#>              package relationship
#>                <chr>        <chr>
#> 1         rmapshaper      Package
#> 2           mregions     Suggests
#> 3          tmaptools      Imports
#> 4       leaflet.esri     Suggests
#> 5     leaflet.extras     Suggests
#> 6 MazamaSpatialUtils      Imports
#> 7           eechidna      Imports

plot_pkg_deps("rmapshaper")
#> Loading required namespace: cranlogs
#> Loading required namespace: ggplot2

plot_pkg_deps("rmapshaper", type = "line")

plot_pkg_deps("ggplot2", when = "last-week", by = "relationship")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment