ETC5523: Communicating with Data

Clearly communicating with code

Lecturer: Emi Tanaka

Department of Econometrics and Business Statistics



Aim

  • Understand and formulate code for communication
  • Understand R package structure
  • Build R package with R code, data, and launching shiny apps

Why

  • Sharing code makes your analysis transparent and reproducible to others.
  • Writing code that is readable by others make author intent explainable
  • An R package makes functions, data or apps accessible, thereby increasing impact of your work

Thanks to Stuart Lee for developing the initial content in this slide, which has been subsequently modified a fair amount by me.

Example data

Plant growth

An experiment to compare yields under control and two different treatment conditions on plants

str(PlantGrowth)
'data.frame':   30 obs. of  2 variables:
 $ weight: num  4.17 5.58 5.18 6.11 4.5 4.61 5.17 4.53 5.33 5.14 ...
 $ group : Factor w/ 3 levels "ctrl","trt1",..: 1 1 1 1 1 1 1 1 1 1 ...

Tooth growth

An experiment to study the effect of vitamin C on tooth growth in guinea pigs

str(ToothGrowth)
'data.frame':   60 obs. of  3 variables:
 $ len : num  4.2 11.5 7.3 5.8 6.4 10 11.2 11.2 5.2 7 ...
 $ supp: Factor w/ 2 levels "OJ","VC": 2 2 2 2 2 2 2 2 2 2 ...
 $ dose: num  0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...

Which one do you prefer?

Code #1

with(PlantGrowth, tapply(weight, group, mean))
 ctrl  trt1  trt2 
5.032 4.661 5.526 

Code #2

library(tidyverse)
PlantGrowth %>% 
  group_by(group) %>% 
  summarise(weight_avg = mean(weight))
# A tibble: 3 × 2
  group weight_avg
  <fct>      <dbl>
1 ctrl        5.03
2 trt1        4.66
3 trt2        5.53

What do you expect the output is?

Code #1

with(ToothGrowth, tapply(len, list(supp, dose), mean))
     0.5     1     2
OJ 13.23 22.70 26.06
VC  7.98 16.77 26.14

Code #2

library(tidyverse)
ToothGrowth %>% 
  group_by(supp, dose) %>% 
  summarise(length_avg = mean(len))
# A tibble: 6 × 3
# Groups:   supp [2]
  supp   dose length_avg
  <fct> <dbl>      <dbl>
1 OJ      0.5      13.2 
2 OJ      1        22.7 
3 OJ      2        26.1 
4 VC      0.5       7.98
5 VC      1        16.8 
6 VC      2        26.1 

Naming matters

Syntactic sugar

Syntactic sugar means using function name or syntax in a programming language that is designed to make things easier to read or to express for humans.

my_function(x)

What do you think this function is doing?

compute_average(x)

A human reads your code, so write your function in a way that reads and works well for humans

Naming cases

camelCase

  • Capitalise all words after first word.
  • Common in R Shiny and JavaScript.

snake_case

  • All words are lower case and separated by an underscore.
  • Preferred by R programmers in general (except Shiny).

PascalCase

  • Capitalise all words.
  • Preferred by C programmers.

kebab-case

  • All words are lower case and separated by a dash.
  • Common in HTML attribute names and CSS property names.

Stick with the style convention of the language as much as possible!

Syntactically valid names in R

  • In R, a syntactically valid name consists of letters, numbers and the dot or underline characters and starts with a letter or the dot not followed by a number.
  • It also cannot be a reserved word, e.g. if, else, TRUE, FALSE, while, function. For full list see ?Reserved.
  • Anything else is a non-syntactic name in R and you can still use any name in R by surrounding it with backticks:
`4` <- 3
  • You can use make.names() to make syntatically valid names in R.

Object names

  • Variable and function names should use only snake case.
  • Strive for names that are concise and meaningful.

Good

day_one
day_1

Bad

DayOne
dayone
first_day_of_the_month
djm1

Function names

  • Function names should be verbs (with exceptions).
  • Avoid using . in the names…
  • …unless writing a function method for S3 object system.

Good

add_row()
permute()
add_column()

Bad

row_adder()
permutation()
add.column()

Variable names

  • Variable names should be nouns.
  • Consider using a list or data.frame to group variables in a similar context instead of assigning it as separate objects.

Good

origin
fit

where

  • fit[[1]] = fit1,
  • fit[[2]] = fit2,
  • and so on.

Bad

originate
fit1
fit2
fit3
fit4
fit5

Readable code

Consistency is key!

Consistency spacing

  • Always put a space after a comma, never before.

Good

x[, 1]

Bad

x[,1]
x[ ,1]
x[ , 1]
  • Do not put spaces inside or outside parentheses for regular function calls.

Good

mean(x, na.rm = TRUE)

Bad

mean (x, na.rm = TRUE)
mean( x, na.rm = TRUE )

Consistency spacing

  • Place a space before and after () when used with if, for, or while.

Good

if (debug) {
  show(x)
}

Bad

if(debug){
  show(x)
}
  • Place a space after () (but not before) used for function arguments:

Good

function(x) {}

Bad

function (x) {}
function(x){}

Consistency spacing

  • Most infix operators (+, -, <-, etc.) should be surrounded by spaces…

Good

height <- (feet * 12) + inches
mean(x, na.rm = TRUE)

Bad

height<-feet*12+inches
mean(x, na.rm=TRUE)
  • …with exceptions of operators with high precedence (::, :::, $, @, [, [[, ^, unary -, unary +, and :).

Good

sqrt(x^2 + y^2)
df$z
x <- 1:10

Bad

sqrt(x ^ 2 + y ^ 2)
df $ z
x <- 1 : 10

Consistency spacing

  • … with exceptions of single-sided formulas when the right-hand side is a single identifier.

Good

~foo
tribble(
  ~col1, ~col2,
  "a",   "b"
)

Bad

~ foo
tribble(
  ~ col1, ~ col2,
  "a", "b"
)
  • Single-sided formulas with a complex right-hand side do need a space.

Good

~ x + y

Bad

~x + y

Avoid long lines

  • Limit your code to 80 characters per line.
  • If the arguments to a function don’t all fit on one line, put each argument on its own line and indent.

Good

do_something_very_complicated(
  something = "that",
  requires = many,
  arguments = "some of which may be long"
)

Bad

do_something_very_complicated("that", requires, many, arguments, "some of which may be long")

Sequence of functions

  • Avoid deeply nesting functions in one line.
  • %>% should always have a space before it, and should usually be followed by a new line.
  • After the first step, each line should be indented by two spaces.

Good

shopping_list %>% 
  buy() %>% 
  prepare() %>% 
  cook()

Bad

cook(prepare(buy(shopping_list)))

shopping_list %>% buy() %>% 
  prepare() %>% cook()

R packages for styling code

  • styler allows you to interactively restyle selected text, files, or entire projects.
  • styler includes an RStudio add-in, the easiest way to re-style existing code.
  • lintr performs automated checks to confirm that you conform to the style guide.

What exactly are R packages?

R packages can be many things…

A container:

  • for a set of R functions,
  • to share data,
  • to share an app,
  • and more, e.g. Rmd templates (out of scope for this unit).

The anatomy of an R package

  • DESCRIPTION file
  • R/ directory for R files that contain your functions
  • NAMESPACE file (manual creation is out of scope for this unit)

Optionally,

  • data/: for binary data available to the user
  • data-raw/: for raw data
  • inst/: for arbitrary additional files that you want include in your package.
  • and others.

The DESCRIPTION file

Metadata for the package

  • Package name
  • Title and description of what the package does
  • Authors
  • Dependencies (depends, imports and suggests)
  • Licencing
  • Version number
  • Where to report bugs and so on

Example: dplyr DESCRIPTION file

Type: Package
Package: dplyr
Title: A Grammar of Data Manipulation
Version: 1.0.99.9000
Authors@R: 
    c(person(given = "Hadley",
             family = "Wickham",
             role = c("aut", "cre"),
             email = "hadley@rstudio.com",
             comment = c(ORCID = "0000-0003-4757-117X")),
      person(given = "Romain",
             family = "François",
             role = "aut",
             comment = c(ORCID = "0000-0002-2444-4226")),
      person(given = "Lionel",
             family = "Henry",
             role = "aut"),
      person(given = "Kirill",
             family = "Müller",
             role = "aut",
             comment = c(ORCID = "0000-0002-1416-3412")),
      person(given = "RStudio",
             role = c("cph", "fnd")))
Description: A fast, consistent tool for working with data frame
    like objects, both in memory and out of memory.
License: MIT + file LICENSE
URL: https://dplyr.tidyverse.org,
    https://github.com/tidyverse/dplyr
BugReports: https://github.com/tidyverse/dplyr/issues
Depends: 
    R (>= 3.4.0)
Imports: 
    generics,
    glue (>= 1.3.2),
    lifecycle (>= 1.0.1.9001),
    magrittr (>= 1.5),
    methods,
    R6,
    rlang (>= 1.0.5),
    tibble (>= 2.1.3),
    tidyselect (>= 1.1.2.9000),
    utils,
    vctrs (>= 0.4.1.9000),
    pillar (>= 1.5.1)
Suggests: 
    bench,
    broom,
    callr,
    covr,
    DBI,
    dbplyr (>= 2.2.1),
    ggplot2,
    knitr,
    Lahman,
    lobstr,
    microbenchmark,
    nycflights13,
    purrr,
    rmarkdown,
    RMySQL,
    RPostgreSQL,
    RSQLite,
    stringi (>= 1.7.6),
    testthat (>= 3.1.1),
    tidyr, 
    withr
Remotes: 
    r-lib/tidyselect,
    r-lib/vctrs,
    r-lib/lifecycle
VignetteBuilder: 
    knitr
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.1
Config/testthat/edition: 3
Config/Needs/website:
    tidyverse,
    shiny,
    pkgdown,
    tidyverse/tidytemplate

The R/ directory

  • The functions you create are stored as R scripts that live in the R/ directory.
  • Functions can be internal to the package or exported so other users have access to them.
  • See for example the dplyr R directory.

The NAMESPACE file

  • The file contains a directive that describes whether an R object is exported from this package or imported from others.
  • These directives can be automatically created by roxygen2 (covered next lecture).
# Generated by roxygen2: do not edit by hand

S3method("$<-",grouped_df)
S3method("[",fun_list)
S3method("[",grouped_df)
S3method("[",rowwise_df)
S3method("[<-",grouped_df)
S3method("[<-",rowwise_df)
S3method("[[<-",grouped_df)
S3method("names<-",grouped_df)
S3method("names<-",rowwise_df)
S3method(add_count,data.frame)
S3method(add_count,default)
S3method(anti_join,data.frame)
S3method(arrange,data.frame)
S3method(arrange_,data.frame)
S3method(arrange_,tbl_df)
S3method(as.data.frame,grouped_df)
S3method(as.tbl,data.frame)
S3method(as.tbl,tbl)
S3method(as_join_by,character)
S3method(as_join_by,default)
S3method(as_join_by,dplyr_join_by)
S3method(as_join_by,list)
S3method(as_tibble,grouped_df)
S3method(as_tibble,rowwise_df)
S3method(auto_copy,data.frame)
S3method(cbind,grouped_df)
S3method(collapse,data.frame)
S3method(collect,data.frame)
S3method(common_by,"NULL")
S3method(common_by,character)
S3method(common_by,default)
S3method(common_by,list)
S3method(compute,data.frame)
S3method(copy_to,DBIConnection)
S3method(copy_to,src_local)
S3method(count,data.frame)
S3method(distinct,data.frame)
S3method(distinct_,data.frame)
S3method(distinct_,grouped_df)
S3method(distinct_,tbl_df)
S3method(do,"NULL")
S3method(do,data.frame)
S3method(do,grouped_df)
S3method(do,rowwise_df)
S3method(do_,"NULL")
S3method(do_,data.frame)
S3method(do_,grouped_df)
S3method(do_,rowwise_df)
S3method(dplyr_col_modify,data.frame)
S3method(dplyr_col_modify,grouped_df)
S3method(dplyr_col_modify,rowwise_df)
S3method(dplyr_reconstruct,data.frame)
S3method(dplyr_reconstruct,grouped_df)
S3method(dplyr_reconstruct,rowwise_df)
S3method(dplyr_row_slice,data.frame)
S3method(dplyr_row_slice,grouped_df)
S3method(dplyr_row_slice,rowwise_df)
S3method(filter,data.frame)
S3method(filter,ts)
S3method(filter_,data.frame)
S3method(filter_,tbl_df)
S3method(filter_bullets,"dplyr:::filter_incompatible_size")
S3method(filter_bullets,"dplyr:::filter_incompatible_type")
S3method(filter_bullets,default)
S3method(format,src_local)
S3method(full_join,data.frame)
S3method(group_by,data.frame)
S3method(group_by_,data.frame)
S3method(group_by_,rowwise_df)
S3method(group_by_drop_default,default)
S3method(group_by_drop_default,grouped_df)
S3method(group_data,data.frame)
S3method(group_data,grouped_df)
S3method(group_data,rowwise_df)
S3method(group_data,tbl_df)
S3method(group_indices,data.frame)
S3method(group_indices_,data.frame)
S3method(group_indices_,grouped_df)
S3method(group_indices_,rowwise_df)
S3method(group_keys,data.frame)
S3method(group_map,data.frame)
S3method(group_modify,data.frame)
S3method(group_modify,grouped_df)
S3method(group_nest,data.frame)
S3method(group_nest,grouped_df)
S3method(group_size,data.frame)
S3method(group_split,data.frame)
S3method(group_split,grouped_df)
S3method(group_split,rowwise_df)
S3method(group_trim,data.frame)
S3method(group_trim,grouped_df)
S3method(group_vars,data.frame)
S3method(groups,data.frame)
S3method(inner_join,data.frame)
S3method(intersect,data.frame)
S3method(left_join,data.frame)
S3method(mutate,data.frame)
S3method(mutate_,data.frame)
S3method(mutate_,tbl_df)
S3method(mutate_bullets,"dplyr:::error_incompatible_combine")
S3method(mutate_bullets,"dplyr:::mutate_constant_recycle_error")
S3method(mutate_bullets,"dplyr:::mutate_incompatible_size")
S3method(mutate_bullets,"dplyr:::mutate_mixed_null")
S3method(mutate_bullets,"dplyr:::mutate_not_vector")
S3method(mutate_bullets,default)
S3method(n_groups,data.frame)
S3method(nest_by,data.frame)
S3method(nest_by,grouped_df)
S3method(nest_join,data.frame)
S3method(print,all_vars)
S3method(print,any_vars)
S3method(print,dplyr_join_by)
S3method(print,dplyr_sel_vars)
S3method(print,fun_list)
S3method(print,src)
S3method(pull,data.frame)
S3method(rbind,grouped_df)
S3method(recode,character)
S3method(recode,factor)
S3method(recode,numeric)
S3method(relocate,data.frame)
S3method(rename,data.frame)
S3method(rename_,data.frame)
S3method(rename_,grouped_df)
S3method(rename_with,data.frame)
S3method(right_join,data.frame)
S3method(rows_append,data.frame)
S3method(rows_delete,data.frame)
S3method(rows_insert,data.frame)
S3method(rows_patch,data.frame)
S3method(rows_update,data.frame)
S3method(rows_upsert,data.frame)
S3method(rowwise,data.frame)
S3method(rowwise,grouped_df)
S3method(same_src,data.frame)
S3method(sample_frac,data.frame)
S3method(sample_frac,default)
S3method(sample_n,data.frame)
S3method(sample_n,default)
S3method(select,data.frame)
S3method(select,list)
S3method(select_,data.frame)
S3method(select_,grouped_df)
S3method(semi_join,data.frame)
S3method(setdiff,data.frame)
S3method(setequal,data.frame)
S3method(slice,data.frame)
S3method(slice_,data.frame)
S3method(slice_,tbl_df)
S3method(slice_head,data.frame)
S3method(slice_max,data.frame)
S3method(slice_min,data.frame)
S3method(slice_sample,data.frame)
S3method(slice_tail,data.frame)
S3method(src_tbls,src_local)
S3method(summarise,data.frame)
S3method(summarise,grouped_df)
S3method(summarise,rowwise_df)
S3method(summarise_,data.frame)
S3method(summarise_,tbl_df)
S3method(summarise_bullets,"dplyr:::error_incompatible_combine")
S3method(summarise_bullets,"dplyr:::summarise_incompatible_size")
S3method(summarise_bullets,"dplyr:::summarise_mixed_null")
S3method(summarise_bullets,"dplyr:::summarise_unsupported_type")
S3method(summarise_bullets,default)
S3method(symdiff,data.frame)
S3method(symdiff,default)
S3method(tally,data.frame)
S3method(tbl,DBIConnection)
S3method(tbl,src_local)
S3method(tbl_ptype,default)
S3method(tbl_sum,grouped_df)
S3method(tbl_sum,rowwise_df)
S3method(tbl_vars,data.frame)
S3method(transmute,data.frame)
S3method(transmute_,data.frame)
S3method(ungroup,data.frame)
S3method(ungroup,grouped_df)
S3method(ungroup,rowwise_df)
S3method(union,data.frame)
S3method(union_all,data.frame)
S3method(union_all,default)
export("%>%")
export(.data)
export(across)
export(add_count)
export(add_count_)
export(add_row)
export(add_rownames)
export(add_tally)
export(add_tally_)
export(all_equal)
export(all_of)
export(all_vars)
export(anti_join)
export(any_of)
export(any_vars)
export(arrange)
export(arrange_)
export(arrange_all)
export(arrange_at)
export(arrange_if)
export(as.tbl)
export(as_data_frame)
export(as_label)
export(as_tibble)
export(auto_copy)
export(bench_tbls)
export(between)
export(bind_cols)
export(bind_rows)
export(c_across)
export(case_match)
export(case_when)
export(changes)
export(check_dbplyr)
export(coalesce)
export(collapse)
export(collect)
export(combine)
export(common_by)
export(compare_tbls)
export(compare_tbls2)
export(compute)
export(consecutive_id)
export(contains)
export(copy_to)
export(count)
export(count_)
export(cumall)
export(cumany)
export(cume_dist)
export(cummean)
export(cur_column)
export(cur_data)
export(cur_data_all)
export(cur_group)
export(cur_group_id)
export(cur_group_rows)
export(current_vars)
export(data_frame)
export(db_analyze)
export(db_begin)
export(db_commit)
export(db_create_index)
export(db_create_indexes)
export(db_create_table)
export(db_data_type)
export(db_desc)
export(db_drop_table)
export(db_explain)
export(db_has_table)
export(db_insert_into)
export(db_list_tables)
export(db_query_fields)
export(db_query_rows)
export(db_rollback)
export(db_save_query)
export(db_write_table)
export(dense_rank)
export(desc)
export(dim_desc)
export(distinct)
export(distinct_)
export(distinct_all)
export(distinct_at)
export(distinct_if)
export(distinct_prepare)
export(do)
export(do_)
export(dplyr_col_modify)
export(dplyr_reconstruct)
export(dplyr_row_slice)
export(ends_with)
export(enexpr)
export(enexprs)
export(enquo)
export(enquos)
export(ensym)
export(ensyms)
export(eval_tbls)
export(eval_tbls2)
export(everything)
export(explain)
export(expr)
export(failwith)
export(filter)
export(filter_)
export(filter_all)
export(filter_at)
export(filter_if)
export(first)
export(full_join)
export(funs)
export(funs_)
export(glimpse)
export(group_by)
export(group_by_)
export(group_by_all)
export(group_by_at)
export(group_by_drop_default)
export(group_by_if)
export(group_by_prepare)
export(group_cols)
export(group_data)
export(group_indices)
export(group_indices_)
export(group_keys)
export(group_map)
export(group_modify)
export(group_nest)
export(group_rows)
export(group_size)
export(group_split)
export(group_trim)
export(group_vars)
export(group_walk)
export(grouped_df)
export(groups)
export(id)
export(ident)
export(if_all)
export(if_any)
export(if_else)
export(inner_join)
export(intersect)
export(is.grouped_df)
export(is.src)
export(is.tbl)
export(is_grouped_df)
export(join_by)
export(lag)
export(last)
export(last_col)
export(lead)
export(left_join)
export(location)
export(lst)
export(make_tbl)
export(matches)
export(min_rank)
export(mutate)
export(mutate_)
export(mutate_all)
export(mutate_at)
export(mutate_each)
export(mutate_each_)
export(mutate_if)
export(n)
export(n_distinct)
export(n_groups)
export(na_if)
export(near)
export(nest_by)
export(nest_join)
export(new_grouped_df)
export(new_rowwise_df)
export(nth)
export(ntile)
export(num_range)
export(one_of)
export(order_by)
export(percent_rank)
export(progress_estimated)
export(pull)
export(quo)
export(quo_name)
export(quos)
export(recode)
export(recode_factor)
export(relocate)
export(rename)
export(rename_)
export(rename_all)
export(rename_at)
export(rename_if)
export(rename_vars)
export(rename_vars_)
export(rename_with)
export(right_join)
export(row_number)
export(rows_append)
export(rows_delete)
export(rows_insert)
export(rows_patch)
export(rows_update)
export(rows_upsert)
export(rowwise)
export(same_src)
export(sample_frac)
export(sample_n)
export(select)
export(select_)
export(select_all)
export(select_at)
export(select_if)
export(select_var)
export(select_vars)
export(select_vars_)
export(semi_join)
export(setdiff)
export(setequal)
export(show_query)
export(slice)
export(slice_)
export(slice_head)
export(slice_max)
export(slice_min)
export(slice_sample)
export(slice_tail)
export(sql)
export(sql_escape_ident)
export(sql_escape_string)
export(sql_join)
export(sql_select)
export(sql_semi_join)
export(sql_set_op)
export(sql_subquery)
export(sql_translate_env)
export(src)
export(src_df)
export(src_local)
export(src_mysql)
export(src_postgres)
export(src_sqlite)
export(src_tbls)
export(starts_with)
export(summarise)
export(summarise_)
export(summarise_all)
export(summarise_at)
export(summarise_each)
export(summarise_each_)
export(summarise_if)
export(summarize)
export(summarize_)
export(summarize_all)
export(summarize_at)
export(summarize_each)
export(summarize_each_)
export(summarize_if)
export(sym)
export(symdiff)
export(syms)
export(tally)
export(tally_)
export(tbl)
export(tbl_df)
export(tbl_nongroup_vars)
export(tbl_ptype)
export(tbl_vars)
export(tibble)
export(top_frac)
export(top_n)
export(transmute)
export(transmute_)
export(transmute_all)
export(transmute_at)
export(transmute_if)
export(tribble)
export(type_sum)
export(ungroup)
export(union)
export(union_all)
export(validate_grouped_df)
export(validate_rowwise_df)
export(vars)
export(with_groups)
export(with_order)
export(wrap_dbplyr_obj)
import(rlang)
import(vctrs, except = data_frame)
importFrom(R6,R6Class)
importFrom(generics,intersect)
importFrom(generics,setdiff)
importFrom(generics,setequal)
importFrom(generics,union)
importFrom(glue,glue)
importFrom(glue,glue_collapse)
importFrom(glue,glue_data)
importFrom(lifecycle,deprecated)
importFrom(magrittr,"%>%")
importFrom(methods,is)
importFrom(pillar,glimpse)
importFrom(pillar,tbl_sum)
importFrom(pillar,type_sum)
importFrom(stats,setNames)
importFrom(stats,update)
importFrom(tibble,add_row)
importFrom(tibble,as_data_frame)
importFrom(tibble,as_tibble)
importFrom(tibble,data_frame)
importFrom(tibble,is_tibble)
importFrom(tibble,lst)
importFrom(tibble,new_tibble)
importFrom(tibble,tibble)
importFrom(tibble,tribble)
importFrom(tibble,view)
importFrom(tidyselect,all_of)
importFrom(tidyselect,any_of)
importFrom(tidyselect,contains)
importFrom(tidyselect,ends_with)
importFrom(tidyselect,everything)
importFrom(tidyselect,last_col)
importFrom(tidyselect,matches)
importFrom(tidyselect,num_range)
importFrom(tidyselect,one_of)
importFrom(tidyselect,starts_with)
importFrom(utils,head)
importFrom(utils,tail)
useDynLib(dplyr, .registration = TRUE)

Creating an R package

  • usethis::create_package("mypkg") for creating a skeleton R package
  • Add things to your R package
  • devtools::load_all() for loading the functions in the R/ directory to the current environment

Adding functions to an R package

  • usethis::use_r("new-r-file") for creating a new R file in the R/ directory
- mypackage
  |- R
     |- new-r-file.R
     |- ...
  |- DESCRIPTION
  |- ...

Distribute data via an R package

  • usethis::use_data_raw("filename") for adding a file to data-raw/ directory to include code to reproduce data.
  • usethis::use_data(mydata) for creating a binary data file in data/ directory.
  • More information on this at R Packages (2e) Chapter 8 Data.

Launcing shiny app via an R package

- mypackage
  |- inst
     |- myapp
        |- app.R
  |- R
     |- run-app.R
     |- ...
  |- DESCRIPTION
  |- ...

run-app.R

#' @export
run_app <- function() {
  app_dir <- system.file("myapp", package = "mypackage")
  shiny::runApp(app_dir, display.mode = "normal")
}

Note: for this to work, you need to first install the package!

Installing the package

  • First run devtools::document()
    (we will cover this more next lecture).
  • Then run devtools::install().
  • Now you can call library(mypackage) to use exported functions or data in your package!

Master the keyboard shortcuts

  • Cmd/Ctrl + Shift + L: Load all
  • Cmd/Ctrl + Shift + D: Document
  • Cmd/Ctrl + Shift + B: Build and Reload
  • plus more… see RStudio IDE > Tools > Keyboard Shortcuts Help

Week 8 Lesson

Summary

  • How to enhance communication in code by adopting a consistent styling.
  • R packages are flexible containers to share R code, data, and app amongst other things.
  • An R package can be set up, documented, and tried out with usethis and devtools.