Little useless-useful R functions – Absurd converter with Markdown report

[This article was first published on R – TomazTsql, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

This time, I will do an absurd amount of useless conversions 🙂 Some might make some sense – in the long looong run, but most will for sure have none. It all started with coffee 🙂 and the initial question was, how many Italian macchiatos you need to to distribute a litre of milk.

Factor in, an Italian macchiato is an espresso and a small amount of steamed milk, usually with milk foam on top. And the ratio is normally 2 parts espresso, 1 part milk. And espresso is usually 9 grams of coffee, making it 20-30 grams of coffee. For good measure, let’s say 25 grams, making 12 grams (or millilitres) of milk per espresso and this adds to 80 macchiatos with 1 litre of milk 🙂

Absurd enough, here are the cumbersome useless lists of absurd conversions (remember, the useless, the better):

    "meters"     = list(to = "lightyears", factor = 1.057e-16),
    "grams"      = list(to = "elephants", factor = 1 / 5000000),
    "liters"     = list(to = "bathtubs", factor = 1 / 150),
    "seconds"    = list(to = "centuries", factor = 1 / (60*60*24*365.25*100)),
    "newtons"    = list(to = "bananas", factor = 1 / 1.2),
    "calories"   = list(to = "joules", factor = 4.184),
    "degreesC"   = list(to = "ice creams melted", factor = 1 / 3),
   #MIT weird units 
    "meters"     = list(to = "smoots", factor = 1 / 1.7018),
    "grams"      = list(to = "blue whales", factor = 1 / 150000000),
    "liters"     = list(to = "coffee cups", factor = 1 / 0.24),
    "seconds"    = list(to = "Netflix episodes", factor = 1 / 1500),
    "newtons"    = list(to = "apples", factor = 1 / 1),
    "calories"   = list(to = "gummy bears", factor = 1 / 9),
    "degreesC"   = list(to = "angry chefs", factor = 1 / 45),
    "tweets"     = list(to = "Elon Musks", factor = 1 / 30000),
    "bananas"    = list(to = "Eiffel Towers", factor = 1 / 400000),
   #Lazslo order two pizzas on May 22nd, 2010!
    "bitcoins"   = list(to = "Papa Joe's pizza (in the year 2010)", factor = (1 / 10000) / 2),
    "kilograms"  = list(to = "llamas", factor = 1 / 140),
    "decibels"   = list(to = "baby screams", factor = 1 / 15),
    "lumens"     = list(to = "fireflies", factor = 1 / 0.25),
    "hours"      = list(to = "meetings endured", factor = 1),
   #based on Slovenian IKEA prices 
    "euros"      = list(to = "Swedish meatballs", factor = 1 / 1.7)

In addition, I have decided to add some noise to the convertion, making it even less deterministic 🙂

  chaos_noise <- function(x) x * runif(1, 1 - chaos, 1 + chaos)
  
  base <- base_unit_map[[unit_from]]
  factor <- chaos_noise(base$factor)

and add some useless statistical tests 🙂

  test <- if (chaos == 1) list(statistic = rnorm(1, 0, 10), p.value = runif(1)) else t.test(values, converted)

At the end, the function generates animation (remember, useless animation) and packs everything in markdown report 🙂


  p <- ggplot(df, aes(x = unit, y = value, fill = unit)) +
    geom_boxplot(alpha = 0.6) +
    geom_jitter(width = 0.15, size = 2, alpha = 0.8) +
    labs(
      title = "Wacky unit_converter_confuser()",
      subtitle = paste("Converting", unit_from, "→", unit_to),
      x = "Unit Type", y = "Value"
    ) +
    theme_minimal(base_size = 14) +
    transition_states(time, transition_length = 2, state_length = 1) +
    ease_aes("cubic-in-out")
  
  anim <<- animate(p, nframes = 50, fps = 10, width = 700, height = 500)

The complete code:


library(ggplot2)
library(gganimate)

unit_converter_confuser <- function(values, unit_from = "kilograms", chaos = 0.3,
                                    seed = 42, report_path = "confuser_report.md") {
  set.seed(seed)
  
  # Absurdity of useful and useless mappings
  base_unit_map <- list(
    "meters"     = list(to = "lightyears", factor = 1.057e-16),
    "grams"      = list(to = "elephants", factor = 1 / 5000000),
    "liters"     = list(to = "bathtubs", factor = 1 / 150),
    "seconds"    = list(to = "centuries", factor = 1 / (60*60*24*365.25*100)),
    "newtons"    = list(to = "bananas", factor = 1 / 1.2),
    "calories"   = list(to = "joules", factor = 4.184),
    "degreesC"   = list(to = "ice creams melted", factor = 1 / 3),
    "meters"     = list(to = "smoots", factor = 1 / 1.7018),
    "grams"      = list(to = "blue whales", factor = 1 / 150000000),
    "liters"     = list(to = "coffee cups", factor = 1 / 0.24),
    "seconds"    = list(to = "Netflix episodes", factor = 1 / 1500),
    "newtons"    = list(to = "apples", factor = 1 / 1),
    "calories"   = list(to = "gummy bears", factor = 1 / 9),
    "degreesC"   = list(to = "angry chefs", factor = 1 / 45),
    "tweets"     = list(to = "Elon Musks", factor = 1 / 30000),
    "bananas"    = list(to = "Eiffel Towers", factor = 1 / 400000),
    "bitcoins"   = list(to = "pizzas (2010)", factor = 1 / 10000),
    "kilograms"  = list(to = "llamas", factor = 1 / 140),
    "decibels"   = list(to = "baby screams", factor = 1 / 15),
    "lumens"     = list(to = "fireflies", factor = 1 / 0.25),
    "hours"      = list(to = "meetings endured", factor = 1),
    "euros"      = list(to = "Swedish meatballs", factor = 1 / 1.5)
  )
  
  if (!(unit_from %in% names(base_unit_map))) stop("Unsupported unit_from")
  
  chaos_noise <- function(x) x * runif(1, 1 - chaos, 1 + chaos)
  
  base <- base_unit_map[[unit_from]]
  factor <- chaos_noise(base$factor)
  
  unit_to <- if (chaos > 0.5) sample(unlist(lapply(base_unit_map, `[[`, "to")), 1) else base$to
  unit_from_scramble <- if (chaos > 0.5) paste(sample(strsplit(unit_from, "")[[1]]), collapse = "") else unit_from
  
  if (chaos > 0.7) {
    values <- values + rnorm(length(values), mean = 0, sd = sd(values) * chaos)
  }
  
  converted <- values * factor
  
  df <- data.frame(
    value = c(values, converted),
    unit = rep(c(unit_from_scramble, unit_to), each = length(values)),
    time = rep(1:length(values), times = 2)
  )
  
  test <- if (chaos == 1) list(statistic = rnorm(1, 0, 10), p.value = runif(1)) else t.test(values, converted)
  

  p <- ggplot(df, aes(x = unit, y = value, fill = unit)) +
    geom_boxplot(alpha = 0.6) +
    geom_jitter(width = 0.15, size = 2, alpha = 0.8) +
    labs(
      title = "Wacky unit_converter_confuser()",
      subtitle = paste("Converting", unit_from, "→", unit_to),
      x = "Unit Type", y = "Value"
    ) +
    theme_minimal(base_size = 14) +
    transition_states(time, transition_length = 2, state_length = 1) +
    ease_aes("cubic-in-out")
  
  anim <<- animate(p, nframes = 50, fps = 10, width = 700, height = 500)
  
  
  # Markdown wacky parody Report Generation
  report <- paste0(
    "# Parody Scientific Report\n",
    "## Project: Wacky **unit_converter_confuser()**\n\n",
    "### Conversion: `", unit_from, "` -> `", unit_to, "`\n\n",
    "**Sample size**: ", length(values), "\n",
    "**Conversion factor**: ", signif(factor, 4), "\n\n",
    "### T-Test Results:\n",
    "- t-statistic: ", round(test$statistic, 3), "\n",
    "- p-value: ", format.pval(test$p.value, digits = 3), "\n",
    "- Conclusion: ", ifelse(test$p.value < 0.05, "Statistically significant nonsense!", "Not even the nonsense is significant."), "\n\n",
    "###  Plot included in animation.\n\n",
    "_This report is proudly brought to you by the Society of Confused Analysts._"
  )
  
  writeLines(report, report_path)
  message("Report saved to: ", report_path)
  
  return(invisible(list(
    original = data.frame(value = values, unit = unit_from),
    converted = data.frame(value = converted, unit = unit_to),
    t_test = test,
    report_path = report_path
  )))
}

and example run:

set.seed(2908)
fake_weights <- rnorm(20, mean = 70, sd = 15)
unit_converter_confuser(fake_weights, unit_from = "kilograms", chaos = 0.92)

rendering the useless animation:

and a Markdown report.

As always, the complete code is available on GitHub in  Useless_R_function repository. The sample file in this repository is here (filename: Absurd_Converter.R). Check the repository for future updates.

Happy R-coding and stay healthy!

To leave a comment for the author, please follow the link and comment on their blog: R – TomazTsql.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)