R/exp_plot_richness.R

Defines functions plot_richness

Documented in plot_richness

#' Plot richness of interview codes over time
#'
#' The full definition of novel and duplicate codes is in [score_codes()].
#' Briefly, 'novel' codes are topics/ideas/concepts that were not mentioned in
#' previous interviews, whereas 'duplicate' codes are topics that other
#' interviews have discussed previously.
#'
#' Some interviews will touch on many different topics and generate many different
#' codes, whereas other interviews will be brief or limited. We call this 'richness'.
#' This plot complements [plot_novelty()] by visualising the richness of each
#' interview in terms of novel and duplicate codes, in context with any
#' refinements to interview questions that were made (marked by stars underneath
#' each bar). By examining this plot together with their field notes, researchers
#' can get insight into the effects of their refinements and the richness of the
#' data.
#'
#' @param score_df (Dataframe) A dataframe of scored codes, as generated by [score_codes()].
#' @param refinements Either a list object generated by [import_field_notes()], or
#'    an Integer vector that lists when (in terms of interview
#'    sequence) refinements were made to the interview questions. For example,
#'    `c(10, 15)` means that interview questions were revised twice: First **before**
#'    the 10th interview, and then again **before** the 15th interview.
#' @param col (List) A List containing named Character vectors. Accepted names are:
#'    - `stroke_novel` and `stroke_duplicate` control line colours for novel and duplicate codes.
#'    - `fill_novel` and `fill_duplicate` control fill colours for novel and duplicate codes.
#'
#' @return A ggplot object.
#' @export
#'
#' @seealso [score_codes()], [import_field_notes()], [plot_novelty()], [save_last_plot()]
#'
#' @examples
#' # Field notes and coding matrices included with the package
#' path_to_notes    <- system.file("insect_study/records/refinements.xlsx", package = "novelqualcodes")
#' path_to_matrices <- system.file("insect_study/matrices/", package = "novelqualcodes")
#'
#' # Import the data
#' my_refinements <- import_field_notes(path_to_notes)
#' my_matrices    <- import_coding_matrices(path_to_matrices)
#'
#' # Score novel and duplicate codes
#' my_scores <- score_codes(my_matrices)
#'
#' # Generate a plot with no refinements
#' plot_richness(score_df = my_scores)
#'
#' # Generate a plot using scored codes and imported refinements
#' plot_richness(score_df = my_scores, refinements = my_refinements)
#'
#' # Generate a plot using scored codes and a vector of refinement times
#' plot_richness(score_df = my_scores, refinements = c(4, 8, 10))
#'
#' @md
#' @importFrom ggplot2 .data
plot_richness <- function(score_df, refinements = integer(0),
                          col = list(stroke_novel = "black", stroke_duplicate = "gray80",
                                     fill_novel = "black", fill_duplicate = "gray90")) {
    if ("field_notes" %in% class(refinements)) {
        refinements <- refinements$ref_points
    }

    plot_df <- reshape_for_plots(score_df, refinements)

    # 2023-07-05: For now, percentage (proportion of novel and duplicate codes
    # as a function of the total number of codes) is not exposed as an option
    # for this plot. We are happy to include it again if a good argument can
    # be made for its usefulness.
    percent <- FALSE
    if (isTRUE(percent)) {
        y_label = "Percent of interview codes"
        plot_df$measure <- plot_df$Proportion * 100
    } else {
        y_label = "Count of interview codes"
        plot_df$measure <- plot_df$n
    }

    annotate_refinements <- list(
        ggplot2::annotate(geom  = "text",
                          y     = rep(max(plot_df$measure) + 1, length(refinements)),
                          x     = refinements,
                          label = rep("\u2605", length(refinements)))
        )

    ggplot2::ggplot(plot_df,
                    ggplot2::aes(x = .data$Interview, y = .data$measure,
                                 fill = .data$Code, colour = .data$Code,
                                 pattern = .data$Code, pattern_colour = .data$Code,
                                 pattern_fill = .data$Code)) +
        ggplot2::theme_bw() +
        ggplot2::theme(panel.grid.minor.x = ggplot2::element_blank(),
                       panel.grid.major.x = ggplot2::element_blank()) +
        ggpattern::geom_bar_pattern(stat = "identity", width = 0.7) +
        ggpattern::scale_pattern_manual(values = c(Duplicate = "stripe", Novel = "none")) +
        ggpattern::scale_pattern_colour_manual(values = c(Duplicate = col$fill_duplicate,   Novel = col$fill_novel)) +
        ggpattern::scale_pattern_fill_manual(values = c(Duplicate = col$stroke_duplicate, Novel = col$stroke_novel)) +
        ggplot2::scale_fill_manual(values = c(Duplicate = col$fill_duplicate,   Novel = col$fill_novel)) +
        ggplot2::scale_colour_manual(values = c(Duplicate = col$stroke_duplicate, Novel = col$stroke_novel)) +
        ggplot2::theme(legend.position = "top") +
        ggplot2::ylab(y_label) +
        ggplot2::xlab("Interview order\n(Refinements indicated by \u2605)") +
        annotate_refinements
}

Try the novelqualcodes package in your browser

Any scripts or data that you put into this service are public.

novelqualcodes documentation built on May 29, 2024, 9:11 a.m.