Note: This package was generated using the litr R package, which lets you define full R packages in a single R Markdown file. For more on litr, see here.

Package setup

We start by specifying the information needed in the DESCRIPTION file of the R package.

usethis::create_package(
  path = ".",
  fields = list(
    Package = params$package_name,
    Version = "0.0.1",
    Title = "Deciding on Your Schedule for JSM",
    Description = "Navigate the JSM schedule from the comfort of an R console, get personalized recommendations for talks, and export your schedule as an ical.",
    `Authors@R` = c(
      person(
        given = "Jacob",
        family = "Bien",
        email = "jbien@usc.edu",
        role = c("aut", "cre")
        ),
      person(
        given = "Yibin",
        family = "Xiong",
        role = "ctb")
      )
    )
)
usethis::use_mit_license(copyright_holder = "J. Bien")
#' A package to help you decide what talks to attend at JSM
#'
#' We scraped the JSM program and wrangled decades of citation and coauthorship
#' data from Semantic Scholar and Arxiv.  We have also included functionality 
#' for exporting your schedule as an ical that can be loaded into Google 
#' Calendar or similar. The result is a package that streamlines the
#' process of finding talks that you may want to attend.
#' 
#' @docType package
#' @seealso [`get_talks`], [`get_coauthors`], [`get_out_citations`], [`get_in_citations`], [`export_calendar_to_ics`], [`export_calendar_to_csv`]

Some packages we’ll be using:

library(dplyr)
library(stringr)
library(purrr)
library(lubridate)

Putting the JSM schedule into the package

Quite a bit of coding went into scraping and wrangling the JSM program to get it into the form of a data frame. At some point we can add that code, but for now let’s just load it from RDS file.

load(file.path("..", "source-files", "jsm_program.Rdata"), envir = jsm <- new.env())
talks <- jsm$talks %>% 
  transmute(session_number = session_id,
            session_title = session_title,
            session_type = session_type,
            day = day,
            start_time = start_time,
            end_time = end_time,
            author = Author %>% map_chr(~ paste(.x, collapse = ", ")),
            speaker = Presenter %>% map_chr(~ paste(.x, collapse = ", ")),
            title = talk_title,
            room = room,
            chair = Chair %>% map_chr(~ paste(.x, collapse = ", ")),
            organizer = Organizer %>% map_chr(~ paste(.x, collapse = ", ")))

There are 3245 talks. For each talk, we provide the following information:

names(talks)
##  [1] "session_number" "session_title"  "session_type"   "day"           
##  [5] "start_time"     "end_time"       "author"         "speaker"       
##  [9] "title"          "room"           "chair"          "organizer"

Let’s send this off to the package:

usethis::use_data(talks)
## ✔ Adding 'R' to Depends field in DESCRIPTION
## ✔ Creating 'data/'
## ✔ Setting LazyData to 'true' in 'DESCRIPTION'
## ✔ Saving 'talks' to 'data/talks.rda'
## • Document your data (see 'https://r-pkgs.org/data.html')

And we’ll need to document the data set as well:

#' The JSM program as a data frame
#' 
#' @format A data frame where each row is a talk and with the following variables:
#' \describe{
#' \item{session_number}{}
#' \item{session_title}{}
#' \item{session_type}{}
#' \item{day}{The day}{}
#' \item{start_time}{}
#' \item{end_time}{}
#' \item{author}{The name(s) of the author(s).  Names separated by commas.}
#' \item{speaker}{The name of the speaker.  In rare cases where there are multiple speakers, their names are separated by commas.}
#' \item{title}{The talk title}
#' \item{room}{}
#' \item{chair}{}
#' \item{organizer}{}
#' }
#' @source This data was scraped from the JSM 2023 website.
"talks"
## [1] "talks"

Since this is a tibble, we’ll need to make sure our package knows how to handle tibbles:

usethis::use_tibble()
## ✔ Adding 'tibble' to Imports field in DESCRIPTION
## ✔ Adding '@importFrom tibble tibble' to 'R/jsm2023-package.R'
## ✔ Writing 'NAMESPACE'
## • Document a returned tibble like so:
##   #' @return a [tibble][tibble::tibble-package]

Let’s also add a character vector of words appearing in the titles:

words <- jsm$words
usethis::use_data(words)
## ✔ Saving 'words' to 'data/words.rda'
## • Document your data (see 'https://r-pkgs.org/data.html')
#' JSM words used in titles
#' @format A character vector of 4853 JSM author names
#' @source This data was scraped from the JSM 2023 program.
"words"
## [1] "words"

Helper functions

A convenience function for filtering talks

While some users might just be happy with talks itself, we can offer some helpful functions.

#' Get talks based on some criteria
#' 
#' @param speakers character vector of speaker names.  Names start with given (first) name, following the format of JSM program.
#' @param authors character vector of author names. Same as above.
#' @param people character vector of people names.  This looks for the person as a speaker, author, organizer, and chair.
#' @param keywords character vector of words to look for in talk title
#' @param days vector of Dates (e.g. "2023-08-07")
#' @param session_types character vector, e.g. "Invited Papers"
#' @export
get_talks <- function(speakers, authors, people, keywords, days, session_types) {
  talks <- jsm2023::talks
  if (!missing(speakers)) {
    pattern <- paste(speakers, collapse = "|") %>% 
      stringr::str_replace("\\(", "\\\\(") %>% # escape parentheses in names
      stringr::str_replace("\\)", "\\\\)") 
    talks <- talks %>% dplyr::filter(stringr::str_detect(.data$speaker, pattern))
  }
  if (!missing(authors)) {
    pattern <- paste(authors, collapse = "|") %>% 
      stringr::str_replace("\\(", "\\\\(") %>% # escape parentheses in names
      stringr::str_replace("\\)", "\\\\)")
    talks <- talks %>% dplyr::filter(stringr::str_detect(.data$author, pattern))
  }
  if (!missing(people)) {
    pattern <- paste(people, collapse = "|") %>% 
      stringr::str_replace("\\(", "\\\\(") %>% # escape parentheses in names
      stringr::str_replace("\\)", "\\\\)")
    talks <- talks %>% 
      dplyr::filter(
        stringr::str_detect(.data$author, pattern) |
          stringr::str_detect(.data$speaker, pattern) |
          stringr::str_detect(.data$chair, pattern) |
          stringr::str_detect(.data$organizer, pattern)
        )
  }
  if (!missing(keywords)) {
    pattern <- paste(tolower(keywords), collapse = "|")
    talks <- talks %>% 
      dplyr::filter(stringr::str_detect(tolower(.data$title), pattern))
  }
  if (!missing(days)) {
    talks <- talks %>% dplyr::filter(.data$day %in% days)
  }
  if (!missing(session_types)) {
    pattern <- paste(tolower(session_types), collapse = "|")
    talks <- talks %>% 
      dplyr::filter(stringr::str_detect(tolower(.data$session_type), pattern))
  }
  talks %>% dplyr::arrange(.data$start_time)
}

In the above we used dplyr, stringr, the magrittr pipe, and .data so let’s make sure these are properly included in the package.

usethis::use_pipe()
usethis::use_package("dplyr")
usethis::use_package("stringr")
usethis::use_import_from("rlang", ".data")
## ✔ Adding 'magrittr' to Imports field in DESCRIPTION
## ✔ Writing 'R/utils-pipe.R'
## • Run `devtools::document()` to update 'NAMESPACE'
## ✔ Adding 'dplyr' to Imports field in DESCRIPTION
## • Refer to functions with `dplyr::fun()`
## ✔ Adding 'stringr' to Imports field in DESCRIPTION
## • Refer to functions with `stringr::fun()`
## ✔ Adding 'rlang' to Imports field in DESCRIPTION
## ✔ Adding '@importFrom rlang .data' to 'R/jsm2023-package.R'
## ✔ Writing 'NAMESPACE'
testthat::test_that("get_talks() works", {
  talk_jb <- get_talks(speakers = "Jacob Bien")
  testthat::expect_equal(
    talk_jb$title[[1]],
    "New and Evolving Roles of Business Statistics in the Big-data Era"
  )
  testthat::expect_equal(
    nrow(get_talks(speakers = c("Jacob Bien", "Guo Yu"))),
    1
  )
  jb_dw <- c("Jacob Bien", "Daniela Witten")
  testthat::expect_equal(nrow(get_talks(speakers = jb_dw)), 2)
  testthat::expect_true(
    all(
      get_talks(speakers = jb_dw)$title %in% get_talks(authors = jb_dw)$title
  ))
  testthat::expect_equal(
    nrow(get_talks(authors = "Sumanta Basu")),
    2
  )
  testthat::expect_equal(
    get_talks(speakers = "Jacob Bien", authors = c("Jacob Bien", "Guo Yu")),
    talk_jb
  )
  testthat::expect_equal(
    nrow(get_talks(people = "Jacob Bien")),
    310 # poster chair!
  )
  testthat::expect_equal(
    get_talks(keywords = "Business Statistics"),
    talk_jb
  )
  testthat::expect_equal(
    get_talks(keywords = "business statistics"),
    talk_jb
  )
  testthat::expect_equal(
    get_talks(people = "Jacob Bien",
              session_types = "Invited Panel Session"),
    talk_jb
  )
  testthat::expect_equal(
    get_talks(people = "Jacob Bien", 
              session_types = c("Invited Paper Session",
                                "Contributed Posters",
                                "Invited Panel Session")),
    get_talks(people = "Jacob Bien")
  )
})

Coauthorship and citation information

Quite a lot of work went into obtaining and processing coauthorship and citation information. We combined three sources of information:

  1. Metadata from all arxiv papers in stat.XX from January 1, 2012 to July 1, 2023 (using the arxiv bulk metadata access OAI protocol). There were 102,198 such papers.

  2. Semantic Scholar (S2)’s bulk data sets (on papers, authors, and citations), in which we started with about 200M papers and filtered down to about 350K papers (written by about 390K authors) by restricting attention to papers in statistics journals or having the arxiv stat.XX tag.

  3. The JSM program itself, which includes 6017 authors.

The S2 citation data can be thought of as a paper-cites-paper matrix. We computed from this an author-cites-author matrix. We then mapped S2 authors to JSM authors. Entity matching and fusion approaches were used to map the Arxiv and S2 author names to JSM author names. This is important and challenging since authors publish under many variations of their name (e.g. First Last, First Middle Last, F. Last, First M. Last, etc.) and since multiple people can have the same first and last name.

For the Semantic Scholar data sets we used, we acknowledge the following paper:

Waleed Ammar, Dirk Groeneveld, Chandra Bhagavatula, Iz Beltagy, Miles Crawford, Doug Downey, Jason Dunkelberger, Ahmed Elgohary, Sergey Feldman, Vu A. Ha, Rodney Michael Kinney, Sebastian Kohlmeier, Kyle Lo, Tyler C. Murray, Hsu-Han Ooi, Matthew E. Peters, Joanna L. Power, Sam Skjonsberg, Lucy Lu Wang, Christopher Wilhelm, Zheng Yuan, Madeleine van Zuylen, Oren Etzioni, “Construction of the Literature Graph in Semantic Scholar.” NAACL 2018.

library(Matrix)
authors <- readRDS(file.path("..", "source-files", "jsm_authors.RDS"))
coauthor <- readRDS(file.path("..", "source-files", "coauthorships.RDS"))
cites <- readRDS(file.path("..", "source-files", "author_cites_author.RDS"))

To make the package size as small as possible, let’s remove the redundant information before storing in the package:

stopifnot(rownames(coauthor) == authors)
stopifnot(colnames(coauthor) == authors)
stopifnot(rownames(cites) == authors)
stopifnot(colnames(cites) == authors)
rownames(coauthor) <- colnames(coauthor) <- NULL
rownames(cites) <- colnames(cites) <- NULL

Let’s send these three objects to the package:

usethis::use_data(authors)
usethis::use_data(coauthor)
usethis::use_data(cites)
## ✔ Saving 'authors' to 'data/authors.rda'
## • Document your data (see 'https://r-pkgs.org/data.html')
## ✔ Saving 'coauthor' to 'data/coauthor.rda'
## • Document your data (see 'https://r-pkgs.org/data.html')
## ✔ Saving 'cites' to 'data/cites.rda'
## • Document your data (see 'https://r-pkgs.org/data.html')

We’ll need the package to know about the sparse matrix classes from the Matrix package, so let’s add it:

usethis::use_package("Matrix")
# We need to import at least one function since we're not using "Matrix::": 
usethis::use_import_from("Matrix", "Matrix")
## ✔ Adding 'Matrix' to Imports field in DESCRIPTION
## • Refer to functions with `Matrix::fun()`
## ✔ Adding '@importFrom Matrix Matrix' to 'R/jsm2023-package.R'
## ✔ Writing 'NAMESPACE'
#' JSM author names
#' @format A character vector of 6017 JSM author names
#' @source This data was scraped from the JSM 2023 program.
"authors"
## [1] "authors"
#' Coauthorship information on JSM authors
#' 
#' A coauthorship matrix.  Element ij gives a numerical measure of how much
#' author `authors[i]` coauthors with author `authors[j]`.  This can be roughly
#' thought of as the number of papers coauthored between this pair, even though
#' that is not strictly true.  These coauthors were computed based on
#' coauthorship information across three sources: Semantic Scholar, Arxiv, and
#' the JSM program. An approximate entity matching was performed to associate
#' names across these different data sets.  Fractional values arise when we have
#' matched a JSM author to multiple Semantic Scholar authors. 
#' 
#' @format A sparse matrix of class "dgCMatrix" from the `Matrix` package.
#' @source This data was created by processing data from Arxiv, Semantic Scholar, and the JSM 2023 program.
#' 
#' Waleed Ammar, Dirk Groeneveld, Chandra Bhagavatula, Iz Beltagy, 
#' Miles Crawford, Doug Downey, Jason Dunkelberger, Ahmed Elgohary, 
#' Sergey Feldman, Vu A. Ha, Rodney Michael Kinney, Sebastian Kohlmeier, 
#' Kyle Lo, Tyler C. Murray, Hsu-Han Ooi, Matthew E. Peters, Joanna L. Power, 
#' Sam Skjonsberg, Lucy Lu Wang, Christopher Wilhelm, Zheng Yuan, 
#' Madeleine van Zuylen, Oren Etzioni, "Construction of the Literature Graph in
#' Semantic Scholar." NAACL 2018.
"coauthor"
## [1] "coauthor"
#' Citation information on JSM authors
#' 
#' A citation matrix.  Element ij gives a numerical measure of how much
#' author `authors[i]` cites author `authors[j]`.  This can be roughly thought 
#' of as the number of times `authors[i]` cites `authors[j]` in the literature.
#' This was based on Semantic Scholar citation data. An approximate entity matching was performed to associate names across these different data sets.
#' Fractional values arise when we have matched a JSM author to multiple 
#' Semantic Scholar authors. 
#' 
#' @format A sparse matrix of class "dgCMatrix" from the `Matrix` package.
#' @source This data was created by processing the JSM 2023 program and the "papers", "authors", and "citations" data sets from Semantic Scholar:
#'  
#' Waleed Ammar, Dirk Groeneveld, Chandra Bhagavatula, Iz Beltagy, 
#' Miles Crawford, Doug Downey, Jason Dunkelberger, Ahmed Elgohary, 
#' Sergey Feldman, Vu A. Ha, Rodney Michael Kinney, Sebastian Kohlmeier, 
#' Kyle Lo, Tyler C. Murray, Hsu-Han Ooi, Matthew E. Peters, Joanna L. Power, 
#' Sam Skjonsberg, Lucy Lu Wang, Christopher Wilhelm, Zheng Yuan, 
#' Madeleine van Zuylen, Oren Etzioni, "Construction of the Literature Graph in
#' Semantic Scholar." NAACL 2018.
"cites"
## [1] "cites"
#' Get indices of nonzero elements of a vector ordered from largest to smallest
#' 
#' This is like `which(vec != 0)`, but with indices sorted by size of `vec`.
#' 
#' @param vec a numerical vector
ordered_nz <- function(vec) {
  ii <- which(vec != 0)
  if (length(ii) == 0) return(integer(0))
  ii[order(vec[ii], decreasing = TRUE)]
}

For example:

ordered_nz(c(0, 0, 14, 0, 2, 100, -2))
## [1] 6 3 5 7
testthat::test_that("ordered_nz() works", {
  testthat::expect_equal(
    ordered_nz(c(0, 0, 14, 0, 2, 100, -2)),
    c(6, 3, 5, 7)
  )
})
## Test passed
#' Return the JSM authors who are co-authors
#' 
#' @param name name of a JSM author
#' 
#' @export
get_coauthors <- function(name) {
  ii <- which(jsm2023::authors == name)
  if (length(ii) == 0) {
    message("Author not found.")
    return(character(0))
  }
  ii_coa <- ordered_nz(jsm2023::coauthor[ii, ])
  jsm2023::authors[ii_coa]
}

And let’s put in a test.

testthat::test_that("get_coauthors() works", {
  testthat::expect_true("Daniela Witten" %in% get_coauthors("Jacob Bien"))
})
#' Return the JSM authors that this JSM author cites
#' 
#' For some authors (particularly new ones), it can be useful to augment their
#' citations with those of coauthors.  Use `augment=TRUE` for this.
#' 
#' @param name name of a JSM author
#' @param augment should we include out citations of coauthors?
#' 
#' @export
get_out_citations <- function(name, augment = FALSE) {
  ii <- which(jsm2023::authors == name)
  if (length(ii) == 0) {
    message("Author not found.")
    return(character(0))
  }
  ii_cites <- ordered_nz(jsm2023::cites[ii, ])
  if (augment) {
    ii_coa <- ordered_nz(jsm2023::coauthor[ii, ])
    # weighted sum of who the coauthors cite (weighted by coauthor strength):
    wtd <- jsm2023::coauthor[ii, ii_coa] %*% jsm2023::cites[ii_coa, ]
    ii_coa_cites <- ordered_nz(as.numeric(wtd))
    # start with author's own cites and follow with those of coauthors:
    ii_cites <- c(ii_cites, setdiff(ii_coa_cites, ii_cites))
  }
  jsm2023::authors[ii_cites]
}
#' Return the JSM authors that cite this JSM author
#' 
#' For some authors (particularly new ones), it can be useful to augment their
#' citations with those of coauthors.  Use `augment=TRUE` for this.
#' 
#' @param name name of a JSM author
#' @param augment should we include out citations of coauthors?
#' 
#' @export
get_in_citations <- function(name, augment = FALSE) {
  ii <- which(jsm2023::authors == name)
  if (length(ii) == 0) {
    message("Author not found.")
    return(character(0))
  }
  ii_cites <- ordered_nz(jsm2023::cites[, ii])
  if (augment) {
    ii_coa <- ordered_nz(jsm2023::coauthor[ii, ])
    # weighted sum of who cites the coauthors (weighted by coauthor strength):
    wtd <- jsm2023::coauthor[ii, ii_coa] %*% Matrix::t(jsm2023::cites[, ii_coa])
    ii_coa_cites <- ordered_nz(as.numeric(wtd))
    # start with author's own cites and follow with those of coauthors:
    ii_cites <- c(ii_cites, setdiff(ii_coa_cites, ii_cites))
  }
  jsm2023::authors[ii_cites]
}

And let’s test these functions.

testthat::test_that("get_*_citations() works", {
  jb_out_cite <- get_out_citations("Jacob Bien", augment = FALSE)
  jb_in_cite <- get_in_citations("Jacob Bien", augment = FALSE)
  testthat::expect_true("Daniela Witten" %in% jb_out_cite)
  testthat::expect_true("Daniela Witten" %in% jb_in_cite)
  testthat::expect_equal(
    jb_out_cite,
    get_out_citations("Jacob Bien", augment = TRUE)[1:length(jb_out_cite)]
  )
  testthat::expect_equal(
    jb_in_cite,
    get_in_citations("Jacob Bien", augment = TRUE)[1:length(jb_in_cite)]
  )
})

Exporting for import into Google Calendar

#' Export events to a .csv format that can be imported to Google Calendar
#' 
#' This will create a .csv file that can then be imported into Google Calendar.
#' To do so, go to https://calendar.google.com/calendar/u/0/r/settings/export
#' and then click "Select file from your computer", and find the file created by
#' this function. Then choose which calendar you want these events added to and
#' click "Import."  The disadvantage of this approach is that the times (which are
#' ET) will be entered in the local time of your calendar.  So if your calendar is
#' in a different time zone when you enter these, the events will be at the wrong 
#' time.  Using `export_calendar_to_ics()` does not have this problem so is the 
#' recommended function to use rather than this one.
#' 
#' @param schedule output of a call to `get_talks()`
#' @param file filename of .csv that will be created
#' 
#' @seealso [`export_calendar_to_ics`]
#' @export
export_calendar_to_csv <- function(schedule, file = NULL) {
  schedule %>% 
    dplyr::transmute(
      Subject = paste0(.data$speaker, ": ", .data$title),
      `Start Date` = .data$day,
      `All Day Event` = FALSE,
      `Start Time` = .data$start_time,
      `End Time` = .data$end_time,
      Location = .data$room,
      Description = stringr::str_glue("Authors: {.data$author}\nSession: {.data$session_title} ({.data$session_type})\nOrganizer: {.data$organizer}; Chair: {.data$chair}; https://ww2.aievolution.com/JSMAnnual/index.cfm?do=ev.viewEv&ev={.data$session_number}")
    ) %>% 
    readr::write_csv(file)
}
usethis::use_package("readr")
## ✔ Adding 'readr' to Imports field in DESCRIPTION
## • Refer to functions with `readr::fun()`
#' Export events to a .ics file that can be imported to Google Calendar, etc.
#' 
#' This will represent the events in the standardized iCalendar format and export
#' as a .ics file that can then be imported into most calendar apps (including 
#' Google Calendar). To do so, go to 
#' https://calendar.google.com/calendar/u/0/r/settings/export
#' and then click "Select file from your computer", and find the file created by
#' this function. Then choose which calendar you want these events added to and
#' click "Import."
#' 
#' @param schedule output of a call to `get_talks()`
#' @param file filename (should end with .ics) that will be created
#' 
#' @export
export_calendar_to_ics <- function(schedule, file = NULL) {
  if (is.null(file)) 
    file <- paste0("jsm2023-cal-", 
                   stringr::str_replace_all(Sys.time(), " ", "-"),
                   ".ics")
  cal <- schedule %>% 
    dplyr::rowwise() %>% 
    dplyr::mutate(
      event = calendar::ic_event(
        start_time = .data$start_time,
        end_time = as.numeric(difftime(time1 = .data$end_time,
                                       time2 = .data$start_time,
                                       units = "hours")),
        summary = paste0(.data$speaker, ": ", .data$title)
      )
    )
  cal$event$LOCATION <- schedule$room
  cal$event$DESCRIPTION <- stringr::str_glue_data(
    schedule, 
    "Authors: {author}\\nSession: <a href='https://ww2.aievolution.com/JSMAnnual/index.cfm?do=ev.viewEv&ev={session_number}' target='_blank'>{session_title}</a> ({session_type})\\nOrganizer: {organizer}; Chair: {chair}")
  cal$event %>% 
    calendar::ic_character() %>%
    stringr::str_replace_all("^DTSTART", "DTSTART;TZID=America/New_York") %>% 
    stringr::str_replace_all("^DTEND", "DTEND;TZID=America/New_York") %>% 
    writeLines(file)
}
usethis::use_package("calendar")
## ✔ Adding 'calendar' to Imports field in DESCRIPTION
## • Refer to functions with `calendar::fun()`

Documenting the package

We finish by running commands that will document the package.

litr::document() # <-- use instead of devtools::document()
## ℹ Updating jsm2023 documentation
## ℹ Loading jsm2023
## Writing 'NAMESPACE'
## Writing 'authors.Rd'
## Writing 'cites.Rd'
## Writing 'coauthor.Rd'
## Writing 'export_calendar_to_csv.Rd'
## Writing 'export_calendar_to_ics.Rd'
## Writing 'get_coauthors.Rd'
## Writing 'get_in_citations.Rd'
## Writing 'get_out_citations.Rd'
## Writing 'get_talks.Rd'
## Writing 'jsm2023-package.Rd'
## Writing 'ordered_nz.Rd'
## Writing 'talks.Rd'
## Writing 'pipe.Rd'
## Writing 'words.Rd'

Add README

litr::add_readme("../source-files/README.Rmd")
## ✔ Writing 'README.Rmd'
## ✔ Adding '^README\\.Rmd$' to '.Rbuildignore'
## ✔ Creating '.git/hooks/'
## ✔ Writing '.git/hooks/pre-commit'

The README has an image, which we’ll put in the package:

if (!fs::dir_exists("man/figures")) fs::dir_create("man/figures")
fs::file_copy("../source-files/ics-imported.png", "man/figures/ics-imported.png")

Add a pkgdown site

First, let’s include the github link of our package as the URL so that we can have a link to it on our pkgdown site.

desc::desc_set(
  "URL",
  "https://github.com/jacobbien/jsm2023-project/tree/main/jsm2023"
  )
## Package: jsm2023
## Title: Deciding on Your Schedule for JSM
## Version: 0.0.1
## Authors@R (parsed):
##     * Jacob Bien <jbien@usc.edu> [aut, cre]
##     * Yibin Xiong [ctb]
## Description: Navigate the JSM schedule from the comfort of an R console,
##     get personalized recommendations for talks, and export your schedule
##     as an ical.
## License: MIT + file LICENSE
## URL: https://github.com/jacobbien/jsm2023-project/tree/main/jsm2023
## Depends:
##     R (>= 2.10)
## Imports:
##     calendar,
##     dplyr,
##     magrittr,
##     Matrix,
##     readr,
##     rlang,
##     stringr,
##     tibble
## Suggests:
##     testthat (>= 3.0.0)
## Config/testthat/edition: 3
## Encoding: UTF-8
## LazyData: true
## Roxygen: list(markdown = TRUE)
## RoxygenNote: 7.2.3

Also, let’s add a hex sticker:

add_hex_sticker("../source-files/jsm2023-hex.png")

Be sure that this next command appears after litr::document() has been called in this file.

litr::add_pkgdown("../source-files/_pkgdown.yml")
## ✔ Adding '^_pkgdown\\.yml$', '^docs$', '^pkgdown$' to '.Rbuildignore'
## Warning in readLines(con, warn = readLines.warn): incomplete final line found
## on './_pkgdown.yml'
## -- Installing package into temporary library -----------------------------------
## == Building pkgdown site =======================================================
## Reading from: '/Users/jacobbien/Dropbox/jsmscheduler/2023/jsm2023-project/jsm2023'
## Writing to:   '/Users/jacobbien/Dropbox/jsmscheduler/2023/jsm2023-project/docs'
## -- Initialising site -----------------------------------------------------------
## -- Building favicons -----------------------------------------------------------
## Building favicons with realfavicongenerator.net...
## Copying 'pkgdown/favicon/apple-touch-icon-120x120.png' to 'apple-touch-icon-120x120.png'
## Copying 'pkgdown/favicon/apple-touch-icon-152x152.png' to 'apple-touch-icon-152x152.png'
## Copying 'pkgdown/favicon/apple-touch-icon-180x180.png' to 'apple-touch-icon-180x180.png'
## Copying 'pkgdown/favicon/apple-touch-icon-60x60.png' to 'apple-touch-icon-60x60.png'
## Copying 'pkgdown/favicon/apple-touch-icon-76x76.png' to 'apple-touch-icon-76x76.png'
## Copying 'pkgdown/favicon/apple-touch-icon.png' to 'apple-touch-icon.png'
## Copying 'pkgdown/favicon/favicon-16x16.png' to 'favicon-16x16.png'
## Copying 'pkgdown/favicon/favicon-32x32.png' to 'favicon-32x32.png'
## -- Building home ---------------------------------------------------------------
## Reading 'LICENSE.md'
## Copying 'man/figures/ics-imported.png' to 'reference/figures/ics-imported.png'
## Writing '404.html'
## -- Building function reference -------------------------------------------------
## Reading 'man/authors.Rd'
## Reading 'man/cites.Rd'
## Reading 'man/coauthor.Rd'
## Reading 'man/export_calendar_to_csv.Rd'
## Reading 'man/export_calendar_to_ics.Rd'
## Reading 'man/get_coauthors.Rd'
## Reading 'man/get_in_citations.Rd'
## Reading 'man/get_out_citations.Rd'
## Reading 'man/get_talks.Rd'
## Reading 'man/jsm2023-package.Rd'
## Reading 'man/ordered_nz.Rd'
## Reading 'man/pipe.Rd'
## Reading 'man/talks.Rd'
## Reading 'man/words.Rd'
## Writing 'sitemap.xml'
## -- Building search index -------------------------------------------------------
## == DONE ========================================================================