Applied Metaphors: Learning TRIZ, Complexity, Data/Stats/ML using Metaphors
  1. Teaching
  2. Data Analytics for Managers and Creators
  3. Case Studies
  4. Demo:Product Packaging and Elderly People
  • Teaching
    • Data Analytics for Managers and Creators
      • Tools
        • Introduction to R and RStudio
        • Introduction to Radiant
        • Introduction to Orange
      • Descriptive Analytics
        • Data
        • Summaries
        • Counts
        • Quantities
        • Groups
        • Densities
        • Groups and Densities
        • Change
        • Proportions
        • Parts of a Whole
        • Evolution and Flow
        • Ratings and Rankings
        • Surveys
        • Time
        • Space
        • Networks
        • Experiments
        • Miscellaneous Graphing Tools, and References
      • Statistical Inference
        • 🧭 Basics of Statistical Inference
        • 🎲 Samples, Populations, Statistics and Inference
        • Basics of Randomization Tests
        • 🃏 Inference for a Single Mean
        • 🃏 Inference for Two Independent Means
        • 🃏 Inference for Comparing Two Paired Means
        • Comparing Multiple Means with ANOVA
        • Inference for Correlation
        • 🃏 Testing a Single Proportion
        • 🃏 Inference Test for Two Proportions
      • Inferential Modelling
        • Modelling with Linear Regression
        • Modelling with Logistic Regression
        • 🕔 Modelling and Predicting Time Series
      • Predictive Modelling
        • 🐉 Intro to Orange
        • ML - Regression
        • ML - Classification
        • ML - Clustering
      • Prescriptive Modelling
        • 📐 Intro to Linear Programming
        • 💭 The Simplex Method - Intuitively
        • 📅 The Simplex Method - In Excel
      • Workflow
        • Facing the Abyss
        • I Publish, therefore I Am
      • Case Studies
        • Demo:Product Packaging and Elderly People
        • Ikea Furniture
        • Movie Profits
        • Gender at the Work Place
        • Heptathlon
        • School Scores
        • Children's Games
        • Valentine’s Day Spending
        • Women Live Longer?
        • Hearing Loss in Children
        • California Transit Payments
        • Seaweed Nutrients
        • Coffee Flavours
        • Legionnaire’s Disease in the USA
        • Antarctic Sea ice
        • William Farr's Observations on Cholera in London
    • R for Artists and Managers
      • 🕶 Lab-1: Science, Human Experience, Experiments, and Data
      • Lab-2: Down the R-abbit Hole…
      • Lab-3: Drink Me!
      • Lab-4: I say what I mean and I mean what I say
      • Lab-5: Twas brillig, and the slithy toves…
      • Lab-6: These Roses have been Painted !!
      • Lab-7: The Lobster Quadrille
      • Lab-8: Did you ever see such a thing as a drawing of a muchness?
      • Lab-9: If you please sir…which way to the Secret Garden?
      • Lab-10: An Invitation from the Queen…to play Croquet
      • Lab-11: The Queen of Hearts, She Made some Tarts
      • Lab-12: Time is a Him!!
      • Iteration: Learning to purrr
      • Lab-13: Old Tortoise Taught Us
      • Lab-14: You’re are Nothing but a Pack of Cards!!
    • ML for Artists and Managers
      • 🐉 Intro to Orange
      • ML - Regression
      • ML - Classification
      • ML - Clustering
      • 🕔 Modelling Time Series
    • TRIZ for Problem Solvers
      • I am Water
      • I am What I yam
      • Birds of Different Feathers
      • I Connect therefore I am
      • I Think, Therefore I am
      • The Art of Parallel Thinking
      • A Year of Metaphoric Thinking
      • TRIZ - Problems and Contradictions
      • TRIZ - The Unreasonable Effectiveness of Available Resources
      • TRIZ - The Ideal Final Result
      • TRIZ - A Contradictory Language
      • TRIZ - The Contradiction Matrix Workflow
      • TRIZ - The Laws of Evolution
      • TRIZ - Substance Field Analysis, and ARIZ
    • Math Models for Creative Coders
      • Maths Basics
        • Vectors
        • Matrix Algebra Whirlwind Tour
        • content/courses/MathModelsDesign/Modules/05-Maths/70-MultiDimensionGeometry/index.qmd
      • Tech
        • Tools and Installation
        • Adding Libraries to p5.js
        • Using Constructor Objects in p5.js
      • Geometry
        • Circles
        • Complex Numbers
        • Fractals
        • Affine Transformation Fractals
        • L-Systems
        • Kolams and Lusona
      • Media
        • Fourier Series
        • Additive Sound Synthesis
        • Making Noise Predictably
        • The Karplus-Strong Guitar Algorithm
      • AI
        • Working with Neural Nets
        • The Perceptron
        • The Multilayer Perceptron
        • MLPs and Backpropagation
        • Gradient Descent
      • Projects
        • Projects
    • Data Science with No Code
      • Data
      • Orange
      • Summaries
      • Counts
      • Quantity
      • 🕶 Happy Data are all Alike
      • Groups
      • Change
      • Rhythm
      • Proportions
      • Flow
      • Structure
      • Ranking
      • Space
      • Time
      • Networks
      • Surveys
      • Experiments
    • Tech for Creative Education
      • 🧭 Using Idyll
      • 🧭 Using Apparatus
      • 🧭 Using g9.js
    • Literary Jukebox: In Short, the World
      • Italy - Dino Buzzati
      • France - Guy de Maupassant
      • Japan - Hisaye Yamamoto
      • Peru - Ventura Garcia Calderon
      • Russia - Maxim Gorky
      • Egypt - Alifa Rifaat
      • Brazil - Clarice Lispector
      • England - V S Pritchett
      • Russia - Ivan Bunin
      • Czechia - Milan Kundera
      • Sweden - Lars Gustaffsson
      • Canada - John Cheever
      • Ireland - William Trevor
      • USA - Raymond Carver
      • Italy - Primo Levi
      • India - Ruth Prawer Jhabvala
      • USA - Carson McCullers
      • Zimbabwe - Petina Gappah
      • India - Bharati Mukherjee
      • USA - Lucia Berlin
      • USA - Grace Paley
      • England - Angela Carter
      • USA - Kurt Vonnegut
      • Spain-Merce Rodoreda
      • Israel - Ruth Calderon
      • Israel - Etgar Keret
  • Posts
  • Blogs and Talks

On this page

  • Setting up R Packages
  • Setting up plot theme
  • Introduction
  • Data
  • Data Dictionary
  • Analyse / Transform the Data
  • Analyse the Data
  • Research Questions
  • More data transformation
  • First Plot
    • Closing Times Analysis
  • Task and Discussion
  • References
  1. Teaching
  2. Data Analytics for Managers and Creators
  3. Case Studies
  4. Demo:Product Packaging and Elderly People

Demo:Product Packaging and Elderly People

colour palettes
icons
ridge plots

This is the YAML at the top of this Quarto document. Use order to sequence your blog posts, and df_print to tidily print your dataframes in the final HTML.

title: <iconify-icon icon="healthicons:elderly-outline" width="1.2em" height="1.2em"></iconify-icon> Demo:Product Packaging and Elderly People
order: 10
df-print: paged
toc: true
editor: 
  markdown: 
    wrap: sentence

Setting up R Packages

library(tidyverse)
library(mosaic)
library(skimr)
library(ggformula)
library(ggridges)
#
library(crosstable)
library(paletteer)

Setting up plot theme

Show the Code
extrafont::loadfonts(quiet = TRUE)
font <- "Roboto Condensed"
theme_set(new = theme_classic(base_size = 12))

theme_update(
  panel.grid.minor = element_blank(),
  text = element_text(family = font),
  # text elements
  plot.title = element_text( # title
    family = font, # set font family
    size = 16, # set font size
    face = "bold", # bold typeface
    hjust = 0, # left align
    # vjust = 2                #raise slightly
    margin = margin(0, 0, 10, 0)
  ),
  plot.subtitle = element_text( # subtitle
    family = font, # font family
    size = 12, # font size
    hjust = 0,
    margin = margin(2, 0, 5, 0)
  ),
  plot.caption = element_text( # caption
    family = font, # font family
    size = 8, # font size
    hjust = 1
  ), # right align

  axis.title = element_text( # axis titles
    family = font, # font family
    size = 10 # font size
  ),
  axis.text = element_text( # axis text
    family = font, # axis family
    size = 8
  ) # font size
)

Introduction

As a demonstration Data Analysis flow, I will take a dataset and show the various steps involved in the workflow: data inspection, cleaning, setting up a hypothesis, plotting a chart, and responding to the hypothesis.

Note

I will repeat the entire code in every chunk, so that the whole process is visible in one shot at the end. This is not something you should do as a practice.

This is a dataset pertaining to packaging of groceries, and the difficulty that elderly people face with opening or closing those packages. The study also included people who were experiencing hand pain due to ailments such as arthritis.

Data

The data is available here: Juliá-Nehme, Begoña (2023). Usability of Food Packaging in Older Adults. Figshare Dataset. https://doi.org/10.6084/m9.figshare.22637656.v1

And, for you peasants, here too:

opening <- opening %>% janitor::clean_names()
glimpse(opening)
inspect(opening)
Rows: 17
Columns: 17
$ group          <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2
$ age            <dbl> 70, 71, 73, 73, 70, 67, 73, 72, 67, 66, 75, 81, 77, 78,…
$ sex            <dbl> 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0
$ hand_pain      <dbl> 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1
$ hand_illness   <dbl> 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
$ hand_strength  <dbl> 21.0, 37.0, 21.0, 30.0, 21.0, 23.0, 18.0, 12.0, 20.0, 6…
$ pinch_strength <dbl> 6.0, 6.5, 5.5, 7.5, 7.5, 6.3, 4.3, 2.5, 4.7, 1.7, 6.0, …
$ time_jar       <chr> "11", "9", "20", "7", "8", "62", "26", "25", "21", "5",…
$ time_beverage  <dbl> 5, 7, 21, 5, 4, 4, 3, 9, 9, 13, 3, 6, 6, 17, 6, 5, 2
$ time_suace     <chr> "17", "11", "14", "6", "7", "18", "8", "38", "11", "25"…
$ time_juice     <dbl> 15, 8, 13, 6, 7, 8, 6, 18, 10, 6, 9, 8, 17, 27, 11, 17,…
$ time_milk      <dbl> 21, 3, 8, 5, 5, 52, 17, 48, 8, 2, 8, 6, 6, 34, 26, 14, …
$ time_crackers  <dbl> 56, 46, 52, 7, 6, 47, 14, 49, 29, 25, 13, 19, 61, 33, 2…
$ time_cheese    <dbl> 14, 35, 23, 29, 25, 9, 13, 12, 9, 36, 43, 19, 31, 18, 4…
$ time_chickpeas <dbl> 35, 20, 69, 28, 29, 30, 29, 76, 20, 25, 27, 16, 39, 55,…
$ time_bottle    <dbl> 10, 4, 18, 5, 4, 6, 6, 8, 11, 6, 8, 4, 6, 7, 8, 7, 6
$ time_soup      <dbl> 6, 23, 23, 6, 3, 6, 2, 30, 23, 3, 4, 6, 9, 4, 6, 8, 12

categorical variables:  
        name     class levels  n missing
1   time_jar character     14 17       0
2 time_suace character     14 17       0
                                   distribution
1 7 (17.6%), 11 (11.8%), 12 (5.9%) ...         
2 11 (11.8%), 6 (11.8%), 8 (11.8%) ...         

quantitative variables:  
             name   class  min   Q1 median   Q3   max       mean         sd  n
1           group numeric  1.0  1.0    1.0  2.0   2.0  1.4117647  0.5072997 17
2             age numeric 66.0 70.0   73.0 78.0  91.0 74.5294118  6.6437720 17
3             sex numeric  0.0  0.0    1.0  1.0   1.0  0.6470588  0.4925922 17
4       hand_pain numeric  0.0  0.0    1.0  1.0   1.0  0.5294118  0.5144958 17
5    hand_illness numeric  0.0  0.0    0.0  1.0   1.0  0.3529412  0.4925922 17
6   hand_strength numeric  6.0 14.0   20.0 23.0  37.0 19.4529412  7.5407325 17
7  pinch_strength numeric  1.7  4.5    5.5  6.5   9.5  5.4941176  2.0464819 17
8   time_beverage numeric  2.0  4.0    6.0  9.0  21.0  7.3529412  5.1713293 17
9      time_juice numeric  6.0  8.0   10.0 15.0  27.0 11.5294118  5.6802030 17
10      time_milk numeric  2.0  6.0    8.0 21.0  52.0 16.2941176 15.3613342 17
11  time_crackers numeric  6.0 19.0   31.0 47.0  61.0 32.5882353 17.2665096 17
12    time_cheese numeric  9.0 14.0   25.0 35.0  80.0 28.0000000 17.8815547 17
13 time_chickpeas numeric 16.0 27.0   30.0 62.0 128.0 45.8823529 30.6061316 17
14    time_bottle numeric  4.0  6.0    6.0  8.0  18.0  7.2941176  3.3868257 17
15      time_soup numeric  2.0  4.0    6.0 12.0  30.0 10.2352941  8.7644838 17
   missing
1        0
2        0
3        0
4        0
5        0
6        0
7        0
8        0
9        0
10       0
11       0
12       0
13       0
14       0
15       0
## janitor is a good package to make clean names out of weird column names
##
closing <- closing %>% janitor::clean_names()
glimpse(closing)
inspect(closing)
Rows: 17
Columns: 17
$ group          <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2
$ age            <dbl> 70, 71, 73, 73, 70, 67, 73, 72, 67, 66, 75, 81, 77, 78,…
$ sex            <dbl> 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0
$ hand_pain      <dbl> 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1
$ hand_illness   <dbl> 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
$ hand_strength  <dbl> 21.0, 37.0, 21.0, 30.0, 21.0, 23.0, 18.0, 12.0, 20.0, 6…
$ pinch_strength <dbl> 6.0, 6.5, 5.5, 7.5, 7.5, 6.3, 4.3, 2.5, 4.7, 1.7, 6.0, …
$ time_jar       <chr> "11", "9", "20", "7", "8", "62", "26", "25", "21", "5",…
$ time_beverage  <dbl> 5, 7, 21, 5, 4, 4, 3, 9, 9, 13, 3, 6, 6, 17, 6, 5, 2
$ time_suace     <chr> "17", "11", "14", "6", "7", "18", "8", "38", "11", "25"…
$ time_juice     <dbl> 15, 8, 13, 6, 7, 8, 6, 18, 10, 6, 9, 8, 17, 27, 11, 17,…
$ time_milk      <dbl> 21, 3, 8, 5, 5, 52, 17, 48, 8, 2, 8, 6, 6, 34, 26, 14, …
$ time_crackers  <dbl> 56, 46, 52, 7, 6, 47, 14, 49, 29, 25, 13, 19, 61, 33, 2…
$ time_cheese    <dbl> 14, 35, 23, 29, 25, 9, 13, 12, 9, 36, 43, 19, 31, 18, 4…
$ time_chickpeas <dbl> 35, 20, 69, 28, 29, 30, 29, 76, 20, 25, 27, 16, 39, 55,…
$ time_bottle    <dbl> 10, 4, 18, 5, 4, 6, 6, 8, 11, 6, 8, 4, 6, 7, 8, 7, 6
$ time_soup      <dbl> 6, 23, 23, 6, 3, 6, 2, 30, 23, 3, 4, 6, 9, 4, 6, 8, 12

categorical variables:  
        name     class levels  n missing
1   time_jar character     14 17       0
2 time_suace character     14 17       0
                                   distribution
1 7 (17.6%), 11 (11.8%), 12 (5.9%) ...         
2 11 (11.8%), 6 (11.8%), 8 (11.8%) ...         

quantitative variables:  
             name   class  min   Q1 median   Q3   max       mean         sd  n
1           group numeric  1.0  1.0    1.0  2.0   2.0  1.4117647  0.5072997 17
2             age numeric 66.0 70.0   73.0 78.0  91.0 74.5294118  6.6437720 17
3             sex numeric  0.0  0.0    1.0  1.0   1.0  0.6470588  0.4925922 17
4       hand_pain numeric  0.0  0.0    1.0  1.0   1.0  0.5294118  0.5144958 17
5    hand_illness numeric  0.0  0.0    0.0  1.0   1.0  0.3529412  0.4925922 17
6   hand_strength numeric  6.0 14.0   20.0 23.0  37.0 19.4529412  7.5407325 17
7  pinch_strength numeric  1.7  4.5    5.5  6.5   9.5  5.4941176  2.0464819 17
8   time_beverage numeric  2.0  4.0    6.0  9.0  21.0  7.3529412  5.1713293 17
9      time_juice numeric  6.0  8.0   10.0 15.0  27.0 11.5294118  5.6802030 17
10      time_milk numeric  2.0  6.0    8.0 21.0  52.0 16.2941176 15.3613342 17
11  time_crackers numeric  6.0 19.0   31.0 47.0  61.0 32.5882353 17.2665096 17
12    time_cheese numeric  9.0 14.0   25.0 35.0  80.0 28.0000000 17.8815547 17
13 time_chickpeas numeric 16.0 27.0   30.0 62.0 128.0 45.8823529 30.6061316 17
14    time_bottle numeric  4.0  6.0    6.0  8.0  18.0  7.2941176  3.3868257 17
15      time_soup numeric  2.0  4.0    6.0 12.0  30.0 10.2352941  8.7644838 17
   missing
1        0
2        0
3        0
4        0
5        0
6        0
7        0
8        0
9        0
10       0
11       0
12       0
13       0
14       0
15       0

Data Dictionary

Several variables are wrongly encoded here, as can be seen. For instance group, and sex are encoded as <dbl> and need to be converted to factors before analysis. We will write our Data Dictionary based on this understanding, and then convert the variables appropriately. (The full workflow will be shown here for the opening dataset; it follows in identical fashion for the closing dataset.)

NoteQuantitative Variables
  • hand_strength(dbl): Hand Strength, numerical
  • pinch_strength(dbl): Pinch Strength, numerical
  • time_jar (chr) Time to open a jar. Needs to be (dbl)
  • time_beverage(dbl)Time to open a beverage
  • time_suace (chr) Time to open sauce
  • time_juice (dbl) Time to open juice
  • time_milk (dbl) Time to open milk carton
  • time_crackers(dbl)Time to open crackers pack
  • time_cheese (dbl) Time to open cheese packet
  • time_chickpeas (dbl) Time to open chickpeas packet
  • time_bottle (dbl) Time to open a bottle
  • time_soup(dbl) Time to open a a can of soup
NoteQualitative Variables
  • group(dbl): Groups in the study. Two. Make into (fct).
  • sex(dbl): sex of the participant. Make into (fct).
  • hand_pain: Did they suffer from hand pain or not? Binary. Make into (fct).
  • hand_illness: How different from hand_pain? Make into (fct).
NoteObservations

Small dataset of 17 rows. Several time values have been measured across the same set of subjects, resulting is what is called a “repeat measures” experiment. Subjects seem to be in two groups, and with or without hand-pain. Are these the two groups? What is the difference between hand_pain and hand_illness?

Analyse / Transform the Data

We need to first convert all the obvious Qual variables into, well, Qual factors! A few variables are also obviously Quant, and need to be transformed. We can also perform counts based on hand_pain and hand_illness to decide how to deal with them. And we will not modify the original data !!

opening_modified <- opening %>%
  # correct spelling mistake
  rename("time_sauce" = time_suace) %>%
  # If you want to do this fast!
  mutate(across(contains("time"), as.numeric)) %>%
  # Two "NA" entries exist

  mutate(
    hand_pain = as_factor(hand_pain),
    hand_illness = as_factor(hand_illness),
    group = as_factor(group),
    sex = as_factor(sex)
  )
Warning: There were 2 warnings in `mutate()`.
The first warning was:
ℹ In argument: `across(contains("time"), as.numeric)`.
Caused by warning:
! NAs introduced by coercion
ℹ Run `dplyr::last_dplyr_warnings()` to see the 1 remaining warning.
opening_modified
ABCDEFGHIJ0123456789
group
<fct>
age
<dbl>
sex
<fct>
hand_pain
<fct>
hand_illness
<fct>
hand_strength
<dbl>
pinch_strength
<dbl>
time_jar
<dbl>
time_beverage
<dbl>
time_sauce
<dbl>
17011021.06.011517
17100037.06.59711
17311021.05.5202114
17301030.07.5756
17001021.07.5847
16710023.06.362418
17310118.04.32638
17210112.02.525938
16710120.04.721911
1661116.01.751325
Next
12
Previous
1-10 of 17 rows | 1-10 of 17 columns
glimpse(opening_modified)
Rows: 17
Columns: 17
$ group          <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2
$ age            <dbl> 70, 71, 73, 73, 70, 67, 73, 72, 67, 66, 75, 81, 77, 78,…
$ sex            <fct> 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0
$ hand_pain      <fct> 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1
$ hand_illness   <fct> 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
$ hand_strength  <dbl> 21.0, 37.0, 21.0, 30.0, 21.0, 23.0, 18.0, 12.0, 20.0, 6…
$ pinch_strength <dbl> 6.0, 6.5, 5.5, 7.5, 7.5, 6.3, 4.3, 2.5, 4.7, 1.7, 6.0, …
$ time_jar       <dbl> 11, 9, 20, 7, 8, 62, 26, 25, 21, 5, 7, 7, 13, 11, 12, 2…
$ time_beverage  <dbl> 5, 7, 21, 5, 4, 4, 3, 9, 9, 13, 3, 6, 6, 17, 6, 5, 2
$ time_sauce     <dbl> 17, 11, 14, 6, 7, 18, 8, 38, 11, 25, 8, 6, 16, 29, 21, …
$ time_juice     <dbl> 15, 8, 13, 6, 7, 8, 6, 18, 10, 6, 9, 8, 17, 27, 11, 17,…
$ time_milk      <dbl> 21, 3, 8, 5, 5, 52, 17, 48, 8, 2, 8, 6, 6, 34, 26, 14, …
$ time_crackers  <dbl> 56, 46, 52, 7, 6, 47, 14, 49, 29, 25, 13, 19, 61, 33, 2…
$ time_cheese    <dbl> 14, 35, 23, 29, 25, 9, 13, 12, 9, 36, 43, 19, 31, 18, 4…
$ time_chickpeas <dbl> 35, 20, 69, 28, 29, 30, 29, 76, 20, 25, 27, 16, 39, 55,…
$ time_bottle    <dbl> 10, 4, 18, 5, 4, 6, 6, 8, 11, 6, 8, 4, 6, 7, 8, 7, 6
$ time_soup      <dbl> 6, 23, 23, 6, 3, 6, 2, 30, 23, 3, 4, 6, 9, 4, 6, 8, 12

Ab theek hai. Haan, ab theek hai

Analyse the Data

Let us make some counts wrt Qual variables, and histograms of Quant variables and get used to our data.

opening_modified %>% count(sex)
ABCDEFGHIJ0123456789
sex
<fct>
n
<int>
06
111
2 rows
opening_modified %>% count(hand_pain)
ABCDEFGHIJ0123456789
hand_pain
<fct>
n
<int>
08
19
2 rows
opening_modified %>% count(hand_pain, hand_illness)
ABCDEFGHIJ0123456789
hand_pain
<fct>
hand_illness
<fct>
n
<int>
004
014
107
112
4 rows

Reasonably balanced groups. Hand_pain and Hand_illness are not the same thing, as seen from the 4-fold counts above.

# Set graph theme
# theme_set(new = theme_custom())
#
opening_modified %>%
  gf_histogram(~hand_strength)
opening_modified %>%
  gf_histogram(~pinch_strength)
opening_modified %>%
  gf_histogram(~time_jar)
Warning: Removed 1 row containing non-finite outside the scale range
(`stat_bin()`).
opening_modified %>%
  gf_histogram(~time_bottle)

Histograms do not look symmetric, but then we have only 17 observations anyway. Elderly people can’t very well be expected to be normal, bless them.

Research Questions

We can create more than one too, and even iteratively, after we have answered the first one and so on. Let us write two:

Note

Q1. Do opening times for groceries vary between people with hand_pain and those without?

Note

Q1. Do opening times for groceries vary between people of different sex?

More data transformation

As seen, this data is in untidy form: there are several numerical columns that have some “Qual” information embedded in their column names, such as the the kind of package that is being opened. We should transform the data into long form so that all the time numbers are stacked up in one column, and the types of packages are in another column, called grocery. For more info see https://www.garrickadenbuie.com/project/tidyexplain/.

opening_modified %>%
  pivot_longer(
    cols = -c(1:7), # Choose columns to stack (by negation)
    names_to = "operation", # Name of stack column
    values_to = "times" # Name of values column
  )
ABCDEFGHIJ0123456789
group
<fct>
age
<dbl>
sex
<fct>
hand_pain
<fct>
hand_illness
<fct>
hand_strength
<dbl>
pinch_strength
<dbl>
operation
<chr>
times
<dbl>
17011021.06.0time_jar11
17011021.06.0time_beverage5
17011021.06.0time_sauce17
17011021.06.0time_juice15
17011021.06.0time_milk21
17011021.06.0time_crackers56
17011021.06.0time_cheese14
17011021.06.0time_chickpeas35
17011021.06.0time_bottle10
17011021.06.0time_soup6
Next
123456
...
17
Previous
1-10 of 170 rows

Once we do this, we realize that the word “time” in the column operation adds no value, since we want only the grocery involved.

opening_modified %>%
  pivot_longer(
    cols = -c(1:7),
    names_to = "operation",
    values_to = "times"
  ) %>%
  # knock off that "time" word
  tidyr::separate_wider_delim(
    cols = operation,
    delim = "time_",
    # Rename "operation" column as "grocery", drop the silly column now containing only "_time"
    names = c(NA, "grocery")
  )
ABCDEFGHIJ0123456789
group
<fct>
age
<dbl>
sex
<fct>
hand_pain
<fct>
hand_illness
<fct>
hand_strength
<dbl>
pinch_strength
<dbl>
grocery
<chr>
times
<dbl>
17011021.06.0jar11
17011021.06.0beverage5
17011021.06.0sauce17
17011021.06.0juice15
17011021.06.0milk21
17011021.06.0crackers56
17011021.06.0cheese14
17011021.06.0chickpeas35
17011021.06.0bottle10
17011021.06.0soup6
Next
123456
...
17
Previous
1-10 of 170 rows

OK, looking better! Now if we plot times, we can colour or facet by grocery.

First Plot

# Set graph theme
# theme_set(new = theme_custom())
#
opening_modified %>%
  pivot_longer(
    cols = -c(1:7),
    names_to = "operation",
    values_to = "times"
  ) %>%
  # knock off that "time" word
  tidyr::separate_wider_delim(operation,
    delim = "time_",
    names = c(NA, "grocery")
  ) %>%
  ## First Plot
  gf_density_ridges(grocery ~ times,
    fill = "grey70", scale = 0.75
  ) %>%
  gf_facet_grid(hand_pain ~ .)
Picking joint bandwidth of 6.2
Picking joint bandwidth of 5.23
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_density_ridges()`).

Ok! Not bad! We now want to label to do two things:

  • label facets 0 and 1 as “Pain” and “No Pain”.
  • Reorder the groceries so that they are in decreasing order of me(di)an(times).
  • In two steps!!
# Set graph theme
# theme_set(new = theme_custom())
#
opening_modified %>%
  pivot_longer(
    cols = -c(1:7),
    names_to = "operation",
    values_to = "times"
  ) %>%
  # knock off that "time" word
  tidyr::separate_wider_delim(operation,
    delim = "time_",
    names = c(NA, "grocery")
  ) %>%
  # Re-label the factor hand_pain
  # Use base::factor() as this command is more clear to me
  mutate(
    hand_pain =
      base::factor(hand_pain,
        levels = c(0, 1),
        labels = c("No Hand Pain", "Hand Pain")
      )
  ) %>%
  ## First Plot
  gf_density_ridges(grocery ~ times,
    fill = "grey70", scale = 0.75
  ) %>%
  gf_facet_grid(hand_pain ~ .)
Picking joint bandwidth of 6.2
Picking joint bandwidth of 5.23
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_density_ridges()`).

And to reorder the groceries in decreasing order of me(di)an (times):

Warning

This does not seem to be happening at this time. Needs to be checked! Wonder what this chart is thinking…

# Set graph theme
# theme_set(new = theme_custom())
#
opening_modified %>%
  pivot_longer(
    cols = -c(1:7),
    names_to = "operation",
    values_to = "times"
  ) %>%
  # knock off that "time" word
  tidyr::separate_wider_delim(operation,
    delim = "time_",
    names = c(NA, "grocery")
  ) %>%
  # Re-label the factor hand_pain
  # Use base::factor() as this command is more clear to me
  mutate(
    hand_pain =
      base::factor(hand_pain,
        levels = c(0, 1),
        labels = c("No Hand Pain", "Hand Pain")
      )
  ) %>%
  ## First Plot modified

  gf_density_ridges(
    reorder(
      grocery, # reorder the grocery var
      times, # based on times variable
      FUN = median
    ) # taking the median times
    ~ times,
    fill = "grey70", scale = 0.75
  ) %>%
  gf_facet_grid(hand_pain ~ .)
Picking joint bandwidth of 6.2
Picking joint bandwidth of 5.23
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_density_ridges()`).

Almost done! We need to relabel the y-axis name and also add some title and subtitles to our plot. And maybe add a point on each sub-plot to show the median opening times?

opening_modified %>%
  pivot_longer(
    cols = -c(1:7),
    names_to = "operation",
    values_to = "times"
  ) %>%
  # knock off that "time" word
  tidyr::separate_wider_delim(operation,
    delim = "time_",
    names = c(NA, "grocery")
  ) %>%
  # Re-label the factor hand_pain
  # Use base::factor() as this command is more clear to me
  mutate(
    hand_pain =
      base::factor(hand_pain,
        levels = c(0, 1),
        labels = c("No Hand Pain", "Hand Pain")
      )
  ) %>%
  group_by(grocery, hand_pain) %>%
  ## First Plot modified
  gf_density_ridges(
    reorder(
      grocery, # reorder the grocery var
      times, # based on times variable
      FUN = median
    ) # taking the median times
    ~ times,
    fill = "grey70", scale = 0.75
  ) %>%
  ## Add the median points
  gf_summary(
    fun = "median", color = "black",
    size = 1,
    geom = "point"
  ) %>%
  ## Facet by hand_pain
  gf_facet_grid(hand_pain ~ .) %>%
  ## Add titles and labels
  gf_labs(
    title = "Times take by Older People to Open Food Packages",
    x = "Time in seconds",
    y = "Type of Product",
    caption = "Juliá-Nehme, Begoña (2023). Usability of Food Packaging in Older Adults.\n figshare Dataset.\n https://doi.org/10.6084/m9.figshare.22637656.v1"
  )

# %>% gf_theme(theme_custom())

Closing Times Analysis

Since the as.numeric did not work for us in the analysis of opening data, I have found and used another function as_numeric from the sjlabelled package. Sigh.

closing %>%
  mutate(across(starts_with("time"), sjlabelled::as_numeric)) %>%
  pivot_longer(
    cols = -c(1:7), names_to = "operation",
    values_to = "times"
  ) %>%
  separate_wider_delim(operation,
    delim = "time_",
    names = c(NA, "operation")
  ) %>%
  mutate(
    operation = str_replace(string = operation, pattern = "suace", replacement = "sauce"),
    hand_pain = factor(hand_pain,
      levels = c(0, 1),
      labels = c("No Hand Pain", "Hand Pain")
    )
  ) %>%
  group_by(operation, hand_pain) %>%
  gf_density_ridges(reorder(operation, times, FUN = mean) ~ times,
    fill = "grey70", scale = 0.75
  ) %>%
  gf_summary(fun = "mean", color = "black", size = 1, geom = "point") %>%
  gf_facet_grid(hand_pain ~ .) %>%
  gf_labs(
    title = "Times take by Older People to Close Food Packages",
    x = "Time in seconds", y = "Type of Product",
    caption = "Juliá-Nehme, Begoña (2023). Usability of Food Packaging in Older Adults.\n figshare Dataset.\n https://doi.org/10.6084/m9.figshare.22637656.v1"
  )
Picking joint bandwidth of 5.71
Picking joint bandwidth of 4.99

# %>%
#   gf_theme(theme_custom())

Task and Discussion

  • Complete the Data Dictionary.
  • Create the graph shown and discuss the following questions:
  • What is the kind of plot used in the chart? A facetted ridge plot with medians marked using points
  • What variables have been used in the chart?
    • Time on X; Grocery Item on Y; Density on the ridges; Hand Pain for faceting
  • Q1. Do opening times for groceries vary between people with hand_pain and those without?
    • Yes; the people with hand pain take longer to open the packages (meh, but all right!) While medians are not too different across the two groups, the distribution tails extend longer in the case of hand_pain = YES.
  • Why do that lines abruptly stop towards the right side of the upper half of the chart?
    • Because the extreme times are shorter across the board for closing, as compared to opening.

References

  1. Colour in R: https://r-for-artists.netlify.app/labs/04-graphics/04-colors

  2. The paletteer package Over 2500 colour palettes are available in the paletteer package. Can you find tayloRswift? wesanderson? harrypotter? timburton?

Here are the Qualitative Palettes (searchable):

package
palette
length
type
novelty
awtools
a_palette
8
sequential
true
awtools
ppalette
8
qualitative
true
awtools
bpalette
16
qualitative
true
awtools
gpalette
4
sequential
true
awtools
mpalette
9
qualitative
true
awtools
spalette
6
qualitative
true
basetheme
brutal
10
qualitative
true
basetheme
clean
10
qualitative
true
basetheme
dark
10
qualitative
true
basetheme
deepblue
10
qualitative
true
1–10 of 2415 rows
...

And the Quantitative/Continuous palettes (searchable):

package
palette
type
ggthemes
Blue-Green Sequential
sequential
ggthemes
Blue Light
sequential
ggthemes
Orange Light
sequential
ggthemes
Blue
sequential
ggthemes
Orange
sequential
ggthemes
Green
sequential
ggthemes
Red
sequential
ggthemes
Purple
sequential
ggthemes
Brown
sequential
ggthemes
Gray
sequential
1–10 of 319 rows
...

Use the commands:

  • Qual variable-> colour/fill: scale_colour_paletteer_d(name = "Legend Name", palette = "package::palette", dynamic = TRUE/FALSE)

  • Quant variable-> colour/fill: scale_colour_paletteer_c(name = "Legend Name", palette = "package::palette", dynamic = TRUE/FALSE)

  1. If you want those funky icons at the Section Headers, install this Quarto Extension, and then choosing the icons you want from https://iconify.design and using the iconify shortcode syntax shown below.

{{< iconify fluent-emoji exploding-head >}}
{{< iconify fa6-brands apple width=50px height=10px rotate=90deg flip=vertical >}}
{{< iconify simple-icons:quarto >}}
Back to top
Case Studies
Ikea Furniture

License: CC BY-SA 2.0

Website made with ❤️ and Quarto, by Arvind V.

Hosted by Netlify .