R/rtweettree_plot.R

Defines functions add_profile_pics_to_tree_ggraph autoplot.character

Documented in add_profile_pics_to_tree_ggraph autoplot.character

# https://stackoverflow.com/a/49894698 :

#' Plot rtweettree
#'
#' Plot a tree graph of the data resulting of the `status_id` of a tweet.
#'
#'
#' The following functions are imported and then re-exported
#' from the ggplot2 package to avoid loading them.
#'
#' rtweettree exported operators and S3 methods
#'
#' @param x rtweet status_id (character string), rtweettree_data or
#'   rtweettree_tbl_graph object. The object is first transformed to a
#'   rtweettree_tbl_graph which is then plotted with ggraph.
#' @param add_profile_pics logical whether to add the profile pictures of the
#' users to the graph; defaults to TRUE; (should be set to FALSE for large graphs)
#' @param ... arguments passed to methods
#'
#' @return An rtweettree ggraph plot.
#' @export
#'
#' @examples
#' main_status_id <- "1438481824922181635"
#' \dontrun{
#' rtweettree_data_scraped <- rtweettree_data(main_status_id)
#' ggplot2::autoplot(rtweettree_data_scraped)
#' # when you're not interested to store the scraped data in an R object,
#' # you can also directly plot it with:
#' # autoplot(main_status_id)
#' }
#' # With package example dataset included:
#' ggplot2::autoplot(rtweettree_data_example)
#'
#' @importFrom ggplot2 autoplot
#'
#' @export
autoplot.character <- function(x, add_profile_pics = TRUE, ...) {
  g <- rtweettree_tbl_graph(x, add_profile_pics, ...)

  g1 <- g %>% ggraph::ggraph(...)
  # Put all user nodes on the bottom line of the graph:
  g1$data$y[g1$data$type == "user"] <- min(g1$data$y[g1$data$type == "tweet"]) - 1

  # distribute user nodes equidistantly on the x-axis along the x-range of the tweets:
  user_x <- g1$data$x[g1$data$type == "user"]
  tweets_xrange <- range(g1$data$x[g1$data$type == "tweet"])
  user_x_eq <- seq(tweets_xrange[1], tweets_xrange[2], length.out = length(user_x))
  df_user_eq <- tibble::tibble(user_x) %>%
    dplyr::mutate(i = dplyr::row_number()) %>%
    dplyr::arrange(user_x) %>%
    dplyr::mutate(user_x_eq) %>%
    dplyr::arrange(.data$i)
  g1$data$x[g1$data$type == "user"] <- df_user_eq$user_x_eq


  if (add_profile_pics) {
    df_profile_pic <- g %>%
      dplyr::as_tibble() %>%
      dplyr::filter(purrr::map_lgl(.data$profile_pic, ~!is.null(.x))) %>%
      dplyr::select(.data$screen_name, .data$profile_pic)

    g1 <- add_profile_pics_to_tree_ggraph(
      g1,
      df_profile_pic
    )
  }

  g1 +
    ggraph::geom_edge_diagonal(ggplot2::aes(color = .data$type)) +
    ggraph::scale_edge_colour_hue(name = "action") +
    ggraph::geom_node_point(ggplot2::aes(shape = .data$type)) +
    ggplot2::scale_color_viridis_c(direction = -1) +
    ggplot2::theme_void()

}
#' @export
autoplot.rtweettree_data <- autoplot.character
#' @export
autoplot.rtweettree_tbl_graph <- autoplot.character


#' Create ggraph object with profile pictures added
#'
#' @param g1 tbl_graph object
#' @param df_profile_pic tibble of profile pictures, generated by `scrape_profile_pics()` (see examples).
#'
#' @return ggraph object of tweet tree with profile pictures
#' @export
#'
#' @examples
#' \dontrun{
#' rtweettree_data_scraped <- rtweettree_data("1438481824922181635")
#' g <- rtweettree_tbl_graph(rtweettree_data_scraped)
#' g1 <- ggraph(g)
#' g1 <- add_profile_pics_to_tree_ggraph(g1, rtweettree:::scrape_profile_pics(tidygraph::as_tibble(g)))
#' g1 + ggraph::geom_edge_diagonal(aes(color = type)) + ggraph::geom_node_point(aes(shape = type))
#' }
add_profile_pics_to_tree_ggraph <- function(g1, df_profile_pic) {
  user_coords <- g1$data %>%
    dplyr::filter(.data$type == "user") %>%
    dplyr::select(.data$screen_name, .data$x, .data$y)

  df_profile_pic <- df_profile_pic %>% dplyr::inner_join(user_coords, by = "screen_name")
  user_coords <- df_profile_pic %>% dplyr::select(.data$screen_name, .data$x, .data$y)
  add_img <- function(g1, user_images, user_coords) {
    # TODO: allow to choose the width & height parameters from the calling function:
    g1  + ggplot2::annotation_raster(user_images, xmin = user_coords$x[1] - 0.4, ymin = user_coords$y[1] + 0.2, xmax = user_coords$x[1] + 0.4, ymax = user_coords$y[1] + 0.6)
  }
  purrr::reduce2(
    df_profile_pic$profile_pic,
    user_coords %>% dplyr::rowwise() %>% dplyr::group_split(),
    add_img,
    .init = g1
  )
}
urswilke/rtweettree documentation built on Oct. 14, 2021, 6:32 p.m.