qr code pointing to stbl.wrangle.zoneThe Design of Everyday R Functions

Jon Harmon, Atorus Research

“All artificial things are designed.”

Make functionality obvious

🔋 Forgive “close enough” input

ℹ️ Help users fix mistakes

Make functionality obvious

What does this function do?

my_fun <- function(x, y, z) {
  y2 <- ceiling(y * z * 100) / 100
  y3 <- y + y2
  data.frame(
    item = x,
    price = y,
    sales_tax = y2,
    total_price = y3
  )
}

Make it obvious what functions do

compile_sales_df <- function(x, y, z) {
  y2 <- ceiling(y * z * 100) / 100
  y3 <- y + y2
  data.frame(
    item = x,
    price = y,
    sales_tax = y2,
    total_price = y3
  )
}

Make it obvious what functions do

compile_sales_df <- function(items, prices, tax_rate) {
  y2 <- ceiling(y * z * 100) / 100
  y3 <- y + y2
  data.frame(
    item = x,
    price = y,
    sales_tax = y2,
    total_price = y3
  )
}

Make it obvious what functions do

compile_sales_df <- function(items, prices, tax_rate) {
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Make it obvious what functions do

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

The function works with “normal” input

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c(12.33, 20.77)
)

The function works with “normal” input

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c(12.33, 20.77)
)
          item price sales_tax total_price
1 paper towels 12.33      1.02       13.35
2 toilet paper 20.77      1.72       22.49

What happens if data types are incorrect?

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c(12.33, 20.77)
)

What happens if data types are incorrect?

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c("12.33", "20.77")
)

What happens if data types are incorrect?

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c("12.33", "20.77")
)
Error in `prices * tax_rate`:
! non-numeric argument to binary operator

Forgive “close enough” input

Forgive “close enough” input

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Forgive “close enough” input

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices)
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Forgive “close enough” input

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c("12.33", "20.77")
)

Forgive “close enough” input

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c("12.33", "20.77")
)
          item price sales_tax total_price
1 paper towels 12.33      1.02       13.35
2 toilet paper 20.77      1.72       22.49

Why did I make this package?

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices)
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Why did I make this package?

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- as.double(prices)
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Why did I make this package?

compile_sales_df(
  items = c("paper towels", "toilet paper"),
  prices = c("12.33", "20.77")
)
          item price sales_tax total_price
1 paper towels 12.33      1.02       13.35
2 toilet paper 20.77      1.72       22.49

Why did I make this package?

compile_sales_df(
  items = c("item", "price", "", ""),
  prices = c("paper towels", "12.33", "toilet paper", "20.77")
)

Why did I make this package?

compile_sales_df(
  items = c("item", "price", "", ""),
  prices = c("paper towels", "12.33", "toilet paper", "20.77")
)
Warning in compile_sales_df(items = c("item", "price", "", ""), prices =
c("paper towels", : NAs introduced by coercion
   item price sales_tax total_price
1  item    NA        NA          NA
2 price 12.33      1.02       13.35
3          NA        NA          NA
4       20.77      1.72       22.49

Help users fix mistakes

Help users fix mistakes

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices)
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Help users fix mistakes

compile_sales_df(
  items = c("item", "price", "", ""),
  prices = c("paper towels", "12.33", "toilet paper", "20.77")
)

Help users fix mistakes

compile_sales_df(
  items = c("item", "price", "", ""),
  prices = c("paper towels", "12.33", "toilet paper", "20.77")
)
Error in `compile_sales_df()`:
! `prices` <character> must be coercible to <double>
✖ Can't convert some values due to non-numeric strings.
• Locations: 1 and 3
• Values: "paper towels" and "toilet paper"

Help users fix mistakes

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices)
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Help users fix mistakes

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices) |>
    stbl::replace_stbl_error(
      c(
        "{.arg prices} must be numeric",
        i = "Check that the input CSV is formatted correctly"
      )
    )
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Help users fix mistakes

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices) |>
    stbl::replace_stbl_error(
      c(
        "{.arg prices} must be numeric",
        i = "Check that the input CSV is formatted correctly"
      ),
      subclass = c("incompatible_values")
    )
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Help users fix mistakes

compile_sales_df <- function(items, prices, tax_rate = 0.0825) {
  prices <- stbl::to_dbl(prices) |>
    stbl::replace_stbl_error(
      c(
        "{.arg prices} must be numeric",
        i = "Check that the input CSV is formatted correctly"
      ),
      subclass = c("incompatible_values", "double")
    )
  sales_tax <- ceiling(prices * tax_rate * 100) / 100
  total_price <- prices + sales_tax
  data.frame(
    item = items,
    price = prices,
    sales_tax = sales_tax,
    total_price = total_price
  )
}

Help users fix mistakes

compile_sales_df(
  items = c("item", "price", "", ""),
  prices = c("paper towels", "12.33", "toilet paper", "20.77")
)

Help users fix mistakes

compile_sales_df(
  items = c("item", "price", "", ""),
  prices = c("paper towels", "12.33", "toilet paper", "20.77")
)
Error in `compile_sales_df()`:
! `prices` must be numeric
ℹ Check that the input CSV is formatted correctly

Help users fix mistakes

Error in `compile_sales_df()`:
! `prices` must be numeric
ℹ Check that the input CSV is formatted correctly

❗ Problem statement

ℹ️ Suggestions

❌ Exact issue (if known)

🔵 More info

You are a designer

You are a designer

Make functionality obvious

🔋 Forgive “close enough” input

ℹ️ Help users fix mistakes

Thank you!