Upgrade to Pro — share decks privately, control downloads, hide ads and more …

reprex: Reproducible Examples with R

reprex: Reproducible Examples with R

Slides from an RStudio webinar about the reprex package. Youtube video: https://youtu.be/MmTPhGQWPUo. Package website: https://reprex.tidyverse.org.

Jennifer (Jenny) Bryan

September 19, 2018
Tweet

More Decks by Jennifer (Jenny) Bryan

Other Decks in Programming

Transcript

  1.  @jennybc
     @JennyBryan
    Jennifer Bryan
    Creating reproducible
    examples with reprex
    2018 September
    rstd.io/reprex

    View full-size slide

  2. rstd.io/reprex
    https://reprex.tidyverse.org

    View full-size slide

  3. This work is licensed under a Creative Commons
    Attribution-ShareAlike 4.0 International License.
    To view a copy of this license, visit 

    http://creativecommons.org/licenses/by-sa/4.0/

    View full-size slide

  4. rstd.io/reprex
    basic usage

    View full-size slide

  5. 1. Copy code.
    2. Run reprex().
    3. Admire, locally.
    4. Paste into target.
    5. Wait for help.

    View full-size slide

  6. reprex (noun)
    a reproducible example
    reprex
    an R package available on CRAN
    reprex::reprex()
    an R function in reprex to make a reprex

    View full-size slide

  7. Include a reprex when you ...
    1. Seek R help on community.rstudio.com
    2. Ask an [r] question on stackoverflow.com
    3. Report a bug in an R package on github.com
    4. Talk about R stuff in Slack or in email
    reprex::reprex() makes this easier!

    View full-size slide

  8. rstd.io/reprex
    installation
    & setup

    View full-size slide

  9. ## install JUST reprex
    install.packages("reprex")
    ## install reprex,
    ## as part of the tidyverse
    install.packages("tidyverse")
    Pick one, do once per machine

    View full-size slide

  10. library(reprex)
    Do once per R session

    View full-size slide

  11. ## put this in ~/.Rprofile to make reprex
    ## available 24/7
    if (interactive()) {
    suppressMessages(require(reprex))
    }
    ## one way to create or open your .Rprofile
    ## install.packages("usethis")
    usethis::edit_r_profile()
    Or ... do this once per machine

    View full-size slide

  12. You are now ready to use reprex::reprex()
    call in the R Console use RStudio addin

    View full-size slide

  13. reprex is a workflow package
    you use it interactively
    not in scripts, Rmd's, packages, Shiny apps
    therefore, it is safe to attach via .Rprofile
    do not do this with dplyr, ggplot2, etc.

    View full-size slide

  14. rstd.io/reprex
    What drove
    me to this?

    View full-size slide

  15. stat545.com
    I participated in
    300 - 500 R-heavy
    GitHub issue threads
    in Sept-Nov each year

    View full-size slide

  16. Now, I work with R a lot on GitHub and in Slack (not shown)

    View full-size slide

  17. rstd.io/reprex
    reprex
    philosophy

    View full-size slide

  18. conversations about code are more productive with:
    code that actually runs
    code that I don’t have to run
    code that I can easily run

    View full-size slide

  19. code that actually runs
    code is run in new R session
    ergo, it must be self-contained!
    must load all necessary packages
    must create all necessary objects

    View full-size slide

  20. not self-contained — forgot to attach necessary package
    not self-contained — forgot to define template object
    YAAAASSSSSS
    template <- "${EXCLAMATION} - your reprex is ${adjective}!"
    praise(template)
    #> Error in praise(template): could not find function "praise"
    library(praise)
    praise(template)
    #> Error in grepl(template_pattern, x): object 'template' not found
    library(praise)
    template <- "${EXCLAMATION} - your reprex is ${adjective}!"
    praise(template)
    #> [1] "WOWIE - your reprex is astounding!"

    View full-size slide

  21. https://reprex.tidyverse.org/articles/reprex-dos-and-donts.html
    • Use the smallest, simplest, most built-in
    data possible.
    • Include commands on a strict "need to
    run" basis.
    • Pack it in, pack it out, and don’t take
    liberties with other people’s computers.

    View full-size slide

  22. standard tricks for the inline
    creation of a small data frame

    View full-size slide

  23. x <- read.csv(text = "a,b\n1,2\n3,4")
    x
    #> a b
    #> 1 1 2
    #> 2 3 4
    x <- data.frame(
    a = c(1, 2),
    b = c(3, 4)
    )
    x
    #> a b
    #> 1 1 3
    #> 2 2 4

    View full-size slide

  24. library(readr)
    x <- read_csv("a,b\n1,2\n3,4")
    x
    #> # A tibble: 2 x 2
    #> a b
    #>
    #> 1 1 2
    #> 2 3 4

    View full-size slide

  25. library(tibble)
    x <- tribble(
    ~a, ~b,
    1, 2,
    3, 4
    )
    x
    #> # A tibble: 2 x 2
    #> a b
    #>
    #> 1 1 2
    #> 2 3 4
    x <- tibble(
    a = c(1, 2),
    b = c(3, 4)
    )
    x
    #> # A tibble: 2 x 2
    #> a b
    #>
    #> 1 1 3
    #> 2 2 4

    View full-size slide

  26. ## what if you already have an object and you want
    ## the tribble() call to define it?
    library(datapasta)
    x <- tribble_construct(head(iris))
    #> Warning in tribble_construct(head(iris)): Column(s) 5 have been converted
    #> from factor to character in tribble output.
    cat(x)
    #> tibble::tribble(
    #> ~Sepal.Length, ~Sepal.Width, ~Petal.Length, ~Petal.Width, ~Species,
    #> 5.1, 3.5, 1.4, 0.2, "setosa",
    #> 4.9, 3, 1.4, 0.2, "setosa",
    #> 4.7, 3.2, 1.3, 0.2, "setosa",
    #> 4.6, 3.1, 1.5, 0.2, "setosa",
    #> 5, 3.6, 1.4, 0.2, "setosa",
    #> 5.4, 3.9, 1.7, 0.4, "setosa"
    #> )

    View full-size slide

  27. code that I don’t have to run
    many readers have lots of experience
    they can often get the point w/o running code,
    especially if they can see the output
    reveal the output produced by your code

    View full-size slide

  28. Maintainer can label this and fellow users
    can this because reprex shows the output.
    https://github.com/tidyverse/readr/issues/784

    View full-size slide

  29. code that I can easily run
    do not copy/paste from the R console
    do not take a screenshot of your R session

    View full-size slide

  30. > test1 <- "\"Header\nLine Two\"\nValue"
    > cat(test1)
    "Header
    Line Two"
    Value
    > readr::read_csv(test1)
    # A tibble: 2 x 1
    `Header\nLine Two`

    1 "Line Two\""
    2 Value

    Do not copy/paste from the R console.
    Others must make fiddly edits to reproduce.

    View full-size slide


  31. Do not take a screenshot.
    Others must retype everything to reproduce.

    View full-size slide


  32. A proper reprex can be re-run via copy/paste.
    test1 <- "\"Header\nLine Two\"\nValue"
    cat(test1)
    #> "Header
    #> Line Two"
    #> Value
    readr::read_csv(test1)
    #> # A tibble: 2 x 1
    #> `Header\nLine Two`
    #>
    #> 1 "Line Two\""
    #> 2 Value

    View full-size slide


  33. See also reprex_invert() and reprex_rescue().
    test1 <- "\"Header\nLine Two\"\nValue"
    cat(test1)
    readr::read_csv(test1)
    Or, if you really want really clean code ...
    Copy from GitHub → reprex_clean() → Paste.

    View full-size slide

  34. rstd.io/reprex
    Shock and Awe

    View full-size slide

  35. live demo of ...
    automatic imgur.com upload of figs
    input as expression
    take control of where output goes
    venues: gh, so, r, rtf
    ad, session info, comment
    capture std out and err

    View full-size slide

  36. ## figures are uploaded to imgur.com and linked, by default
    library(gapminder)
    library(ggplot2)
    ggplot(subset(gapminder, continent != "Oceania"),
    aes(x = year, y = lifeExp, group = country, color = country)) +
    geom_line(lwd = 1, show.legend = FALSE) + facet_wrap(~ continent) +
    scale_color_manual(values = country_colors) +
    theme_bw() + theme(strip.text = element_text(size = rel(1.1)))
    ## copy the above ^^ to clipboard
    reprex()
    ## paste into, e.g., GitHub issue
    ## OMG the figure is there! w00t!
    demo: figure upload to imgur.com

    View full-size slide

  37. demo: reprex from an expression
    see also: the input argument
    ## provide input as an expression
    reprex({
    x <- rnorm(100)
    y <- rnorm(100)
    cor(x, y)
    })

    View full-size slide

  38. demo: outfile argument to control where things go
    ## ask to work in working directory
    ## (vs session temp directory)
    ## helpful if reprex does file I/O
    reprex(
    writeLines(letters[1:6]),
    outfile = NA
    )
    ## provide a humane base for the filename
    reprex(
    writeLines(letters[21:26]),
    outfile = "shock-and-awe"
    )

    View full-size slide

  39. demo: venue argument (default is "gh" for GitHub)
    ## render to markdown tuned to Stack Overflow (vs
    ## GitHub or Discourse)
    reprex(
    mean(rnorm(100)),
    venue = "so"
    )
    ## render to a commented R script
    ## great for email or Slack
    reprex(
    mean(rnorm(100)),
    venue = "r"
    )
    ## render to RTF to paste into Keynote or PowerPoint
    reprex(
    mean(rnorm(100)),
    venue = "rtf"
    )

    View full-size slide

  40. demo: advertise, si, style arguments
    ## suppress the "advertisement" (toggle it!)
    reprex(
    mean(rnorm(100)),
    advertise = TRUE
    )
    ## include session info (toggle it!)
    reprex(
    mean(rnorm(100)),
    si = TRUE
    )
    ## re-style the code (toggle it!)
    reprex(
    input = c(
    'if (TRUE) "true branch" else {',
    '"else branch"',
    ' }'
    ),
    style = TRUE
    )

    View full-size slide

  41. demo: std_out_err argument
    ## include output from standard output and standard error
    remove.packages("bench")
    reprex(
    devtools::install_github("r-lib/bench"),
    std_out_err = TRUE
    )

    View full-size slide

  42. Customize your defaults in .Rprofile
    options(
    reprex.advertise = FALSE,
    reprex.si = TRUE,
    reprex.style = TRUE,
    reprex.comment = "#;-)",
    reprex.tidyverse_quiet = FALSE
    )

    View full-size slide

  43. Two RStudio addins
    Render reprex... launches
    a gadget, i.e. a GUI
    Reprex selection is
    conceived for use with a
    keyboard shortcut

    View full-size slide

  44. I bind Reprex selection to Shift + Cmd + R.
    Hadley binds to Alt + Cmd + R.
    Tools > Modify Keyboard Shortcuts...

    View full-size slide

  45. rstd.io/reprex
    the
    human
    side

    View full-size slide

  46. https://unsplash.com/photos/xdEeLyK4iBo

    View full-size slide

  47. ⚠ WARNING ⚠
    Tough love!
    Hyperbole!
    Real talk!

    View full-size slide

  48. With all the love in the world ...
    if your theory about what's wrong was so great?
    we probably wouldn't be having this conversation.
    Show us the code.

    View full-size slide

  49. Have you ever helped a relative with their
    computer problem over the phone?
    That's how it feels to answer a programming
    question based on a prose narrative.
    Show us the code.

    View full-size slide

  50. Assume everyone is acting in good faith.
    (If not, they are irrelevant.)
    True story: experts are afraid to offer a solution if
    they can't prove to themselves that it works.
    Show us the code.

    View full-size slide

  51. "Making a good reprex is a lot of work!"
    Yes, it is!
    You're asking others to experience your pain.
    This is how you meet them halfway.

    View full-size slide

  52. Let's get selfish.
    Making good reprexes?
    Reproducing other people's problems?
    Eventually ... solving them?
    This is a great way to get better at programming.

    View full-size slide

  53. Let's stay selfish.
    Pleasant surprise: making a good reprex often
    leads to solving your own problem. In private.
    reprex() helps you organize your attack. It
    forces you to strip your problem down to basics.

    View full-size slide

  54. rstd.io/reprex
    what
    actually
    happens

    View full-size slide

  55. {{{yaml}}}
    {{{so_syntax_highlighting}}}
    #+ reprex-setup, include = FALSE
    options(tidyverse.quiet = {{{tidyverse_quiet}}})
    knitr::opts_chunk$set(collapse = TRUE, comment = "{{{comment}}}", error = TRUE)
    knitr::opts_knit$set(upload.fun = {{{upload_fun}}})
    #+ reprex-body
    {{{body}}}
    {{{std_file_stub}}}
    {{{ad}}}
    {{{si}}}
    your code goes here
    then .R → .md → .html
    ?.R .rtf?

    View full-size slide

  56. (y <- 1:4)
    mean(y)
    ``` r
    (y <- 1:4)
    #> [1] 1 2 3 4
    ...
    reprex()
    bit o' code
    html preview in RStudio gfm on  as seen on GitHub

    View full-size slide

  57. (y <- 1:4)
    mean(y)

    (y <- 1:4)
    #> [1] 1 2 3 4
    ...
    reprex(venue = "so")
    bit o' code
    html preview in RStudio SO md on  as seen on StackOverflow

    View full-size slide

  58. (y <- 1:4)
    mean(y)
    (y <- 1:4)
    #> [1] 1 2 3 4
    mean(y)
    #> [1] 2.5
    ...
    reprex(venue = "r")
    bit o' code
    html preview in RStudio commented R on  as Slack R snippet

    View full-size slide

  59. Huge to Yihui Xie and all those who bring us
    rmarkdown and Pandoc
    reprex is "just" a wrapper around those things
    All reprex co-authors, contributors, users

    View full-size slide

  60. rstd.io/reprex
    engage in Q & A
    report bugs
    request features
    be a chatty R nerd!

    View full-size slide