Descripció del conjunt de dades i preprocessament

1. Pregunta del estudi

Com influeix el dia de la setmana i l’hora del dia en el tipus i quantitat de begudes comprades, així com en els ingressos generats?

Aquesta pregunta és rellevant perquè permet:

  • Identificar patrons de consum segons temporalitat
  • Optimitzar la gestió d’inventari i personal
  • Entendre les preferències dels clients segons el moment del dia/setmana
  • Millorar l’estratègia de preus i promocions

Les variables disponibles al dataset permeten respondre aquesta pregunta de manera exhaustiva, ja que tenim informació sobre:

  • Moment temporal (hora, dia setmana, mes)
  • Tipus de beguda
  • Preu/import de cada transacció

2.Descripció del Conjunt de Dades

2.1 Font de les Dades

Les dades provenen de Kaggle i representen transaccions reals d’una cafeteria durant l’any 2024.

2.2 Variables del Dataset

# Exemple d'importació (modifiqueu segons calgui)
 dades <- read_csv("coffe.csv")
## Rows: 3547 Columns: 11
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (6): cash_type, coffee_name, Time_of_Day, Weekday, Month_name, Date
## dbl  (4): hour_of_day, money, Weekdaysort, Monthsort
## time (1): Time
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dim(dades)
## [1] 3547   11
glimpse(dades)
## Rows: 3,547
## Columns: 11
## $ hour_of_day <dbl> 10, 12, 12, 13, 13, 15, 16, 18, 19, 19, 19, 10, 10, 11, 14…
## $ cash_type   <chr> "card", "card", "card", "card", "card", "card", "card", "c…
## $ money       <dbl> 38.7, 38.7, 38.7, 28.9, 38.7, 33.8, 38.7, 33.8, 38.7, 33.8…
## $ coffee_name <chr> "Latte", "Hot Chocolate", "Hot Chocolate", "Americano", "L…
## $ Time_of_Day <chr> "Morning", "Afternoon", "Afternoon", "Afternoon", "Afterno…
## $ Weekday     <chr> "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "F…
## $ Month_name  <chr> "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "M…
## $ Weekdaysort <dbl> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7…
## $ Monthsort   <dbl> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3…
## $ Date        <chr> "01/03/2024", "01/03/2024", "01/03/2024", "01/03/2024", "0…
## $ Time        <time> 15:50:00, 19:22:00, 20:18:00, 46:33:00, 48:14:00, 39:47:0…
Variable Tipus Descripció Valors possibles / rang
hour_of_day numèrica Hora del dia en què es fa la compra 0–23
money numèrica Import pagat per la compra (preu total del tiquet) ≥ 0 (p. ex. 0–50)
coffee_name categòrica Tipus de beguda adquirida Latte, Americano, Hot Chocolate, etc.
Weekday categòrica Dia de la setmana Mon–Sun (segons dataset: Fri, Sat, etc.)
Month_name categòrica Mes de l’any Jan–Dec (p. ex. Mar)
Weekdaysort numèrica Codificació numèrica de l’ordre dels dies 1–7
Monthsort numèrica Codificació numèrica dels mesos 1–12
Date text Data completa de la transacció Format dd/mm/aaaa
Time text Hora exacta de la transacció Format hh:mm.ss

No utilitzarem les columnes cash_type, Weekdaysort Monthsort (perque son redundant, ja tenim les categories del nom del mes i dies de la setmana) i , perque les considerem extres per respondre a la nostra pregunta.

2.3 Dimensions

# Modificacio de les dades perque siguin de tipus temps´
dades$Date <- as.Date(dades$Date, "%d/%m/%Y") 
glimpse(dades)
## Rows: 3,547
## Columns: 11
## $ hour_of_day <dbl> 10, 12, 12, 13, 13, 15, 16, 18, 19, 19, 19, 10, 10, 11, 14…
## $ cash_type   <chr> "card", "card", "card", "card", "card", "card", "card", "c…
## $ money       <dbl> 38.7, 38.7, 38.7, 28.9, 38.7, 33.8, 38.7, 33.8, 38.7, 33.8…
## $ coffee_name <chr> "Latte", "Hot Chocolate", "Hot Chocolate", "Americano", "L…
## $ Time_of_Day <chr> "Morning", "Afternoon", "Afternoon", "Afternoon", "Afterno…
## $ Weekday     <chr> "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "F…
## $ Month_name  <chr> "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "M…
## $ Weekdaysort <dbl> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7…
## $ Monthsort   <dbl> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3…
## $ Date        <date> 2024-03-01, 2024-03-01, 2024-03-01, 2024-03-01, 2024-03-0…
## $ Time        <time> 15:50:00, 19:22:00, 20:18:00, 46:33:00, 48:14:00, 39:47:0…
dades$datetime <- dades$Date + dades$Time
glimpse(dades)
## Rows: 3,547
## Columns: 12
## $ hour_of_day <dbl> 10, 12, 12, 13, 13, 15, 16, 18, 19, 19, 19, 10, 10, 11, 14…
## $ cash_type   <chr> "card", "card", "card", "card", "card", "card", "card", "c…
## $ money       <dbl> 38.7, 38.7, 38.7, 28.9, 38.7, 33.8, 38.7, 33.8, 38.7, 33.8…
## $ coffee_name <chr> "Latte", "Hot Chocolate", "Hot Chocolate", "Americano", "L…
## $ Time_of_Day <chr> "Morning", "Afternoon", "Afternoon", "Afternoon", "Afterno…
## $ Weekday     <chr> "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "Fri", "F…
## $ Month_name  <chr> "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "Mar", "M…
## $ Weekdaysort <dbl> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7…
## $ Monthsort   <dbl> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3…
## $ Date        <date> 2024-03-01, 2024-03-01, 2024-03-01, 2024-03-01, 2024-03-0…
## $ Time        <time> 15:50:00, 19:22:00, 20:18:00, 46:33:00, 48:14:00, 39:47:0…
## $ datetime    <date> 2024-03-02, 2024-03-02, 2024-03-02, 2024-03-03, 2024-03-0…
##El fragment de temps (dates) de quan a quan s'han pres les mesures:
floor_date(dades$Date, 'month')[1]
## [1] "2024-03-01"
last(floor_date(dades$Date, 'month'))
## [1] "2025-03-01"

Nombre d’observacions: 3,547 transaccions Període temporal: Març 2024 - Març 2025 (aproximadament 1 any) Unitat d’anàlisi: Cada fila representa una transacció individual

El conjunt de dades conté 3547 registres de compres fetes a la cafeteria. Segons les dates que hi apareixen, les vendes van des del 2024-03-01 fins al 2025-03-23. Aquest perríode ens permet observar com varien les compres al llarg dels dies i de les hores, i veure si hi ha moments en què la cafeteria ven més.

2.4 Variables Derivades Creades

Durant la preparació de dades hem creat:

  • datetime: Combinació de data i hora per anàlisis temporals més precises
  • Conversió de Date a format Date proper de R
  • Assegurar que money sigui numèrica

Metodologia estadística utilitzada

En aquest apartat descriurem el plantejament de les preguntes d’anàlisi, la formulació de les hipòtesis estadístiques i la selecció dels mètodes de inferencia que aplicarem més endavant.

1. Plantejament de les preguntes

Per reduir la pregunta general de l’estudi, es consideren les següents preguntes específiques:

  • L’import mitjà varia entre les diferents hores de dia? (variable hour_of_day)

  • Hi ha diferències en l’import mitjà de les transaccions segons el dia de la setmana? (variable Weekdaysort)

  • Quina seria la variancia del import mitja per el tipus de beguda? (variable coffee_name)

2. Formulació de les hipòtesis estadístiques

A partir de les preguntes anteriors, hem formulat les seguents hipotesis:

2.2 Hipòtesis segons l’hora del dia (hour_of_day)

Hipòtesi nul·la (H₀): La despesa mitjana per transacció (money) és la mateixa per a totes les hores del dia.

Hipòtesi alternativa (H₁): Existeixen diferències en la despesa mitjana per transacció entre almenys dues hores del dia.

2.3 Hipòtesis segons el dia de la setmana (Weekdaysort)

Hipòtesi nul·la (H₀): La despesa mitjana per transacció (money) és la mateixa per a tots els dies de la setmana.

Hipòtesi alternativa (H₁): Almenys un dia de la setmana presenta una despesa mitjana per transacció diferent.

2.4 Hipòtesis segons el tipus de beguda (coffee_name)

Hipòtesi nul·la (H₀): La despesa mitjana per transacció (money) és la mateixa per a tots els tipus de beguda.

Hipòtesi alternativa (H₁): Existeixen diferències en la despesa mitjana per transacció entre almenys dos tipus de beguda.

3. Selecció dels mètodes estadístics

Com que compararem la mitjana de money entre tres o més grups (hores del dia, dies de la setmana o tipus de beguda) s’utilitzara una anàlisi de la variància ANOVA.

Comprovació i discussió de les assumpcions

1. Assumpcions dels models utilitzats

Per aplicar els contrastos de hipotesis del test ANOVA, hem de tenir en compte les assumpcions del model (tot i que aquestes condicions no sempre es compleixen estrictament en dades reals).

  • Independència de les observacions: Cada fila del conjunt de dades correspon a una transacció individual. No es disposa d’informació sobre clients, per tant considerem que son independents.

  • Normalitat de la variable resposta: ANOVA assumeix una distribució aproximadament normal de la variable resposta (money) dins de cada grup.

  • Homogeneïtat de les variàncies: Assumim que la variància de la variable resposta és similar entre els grups comparats.

2. Fem els contrastos de hipotesis

2.1 Segons la hora de dia hour_of_day

anova_hour <- aov(money ~ hour_of_day, data = dades)
summary(anova_hour)
##               Df Sum Sq Mean Sq F value Pr(>F)    
## hour_of_day    1   3468    3468     152 <2e-16 ***
## Residuals   3545  80900      23                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

p < 0.05 => Tenim prou evidencies per rebutjar la hipotesi nul·la. ### 2.2 Segons el dia de la setmana Weekday

anova_weekday <- aov(money ~ Weekday, data = dades)
summary(anova_weekday)
##               Df Sum Sq Mean Sq F value Pr(>F)
## Weekday        6    121   20.11   0.845  0.535
## Residuals   3540  84247   23.80

p = 0.535 > 0.05 => NO tenim prou evidencia per rebutjar la hipotesi nul·la.

2.3 Segons tipus de la beguda coffee_name

anova_coffee <- aov(money ~ coffee_name, data = dades)
summary(anova_coffee)
##               Df Sum Sq Mean Sq F value Pr(>F)    
## coffee_name    7  73122   10446    3287 <2e-16 ***
## Residuals   3539  11246       3                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

p < 0.05 => Tenim prou evidencies per rebutjar la hipotesi nul·la.

Resultats (taules, figures, estadístics)

1. Exploració Inicial de les Dades

A continuació es mostren les primeres taula i diversos gràfics per explorar els patrons principals del conjunt de dades en relació amb la pregunta d’estudi.

1.1 Resum Estadístic General

# Estadístiques bàsiques
summary(dades$money)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   18.12   27.92   32.82   31.65   35.76   38.70
summary(dades$hour_of_day)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    6.00   10.00   14.00   14.19   18.00   22.00
table(dades$coffee_name)
## 
##           Americano Americano with Milk          Cappuccino               Cocoa 
##                 564                 809                 486                 239 
##             Cortado            Espresso       Hot Chocolate               Latte 
##                 287                 129                 276                 757
# Mitjana d’ingressos per hora
aggregate(money ~ hour_of_day, data = dades, mean)
##    hour_of_day    money
## 1            6 29.88000
## 2            7 32.34114
## 3            8 29.86332
## 4            9 30.01769
## 5           10 31.09305
## 6           11 29.86961
## 7           12 30.78680
## 8           13 31.23893
## 9           14 31.88356
## 10          15 31.67805
## 11          16 32.48863
## 12          17 32.31966
## 13          18 32.85596
## 14          19 33.85135
## 15          20 33.01136
## 16          21 32.80995
## 17          22 32.16956
# Mitjana d’ingressos per dia de la setmana
aggregate(money ~ Weekday, data = dades, mean)
##   Weekday    money
## 1     Fri 31.58395
## 2     Mon 31.91746
## 3     Sat 31.34791
## 4     Sun 31.82831
## 5     Thu 31.55176
## 6     Tue 31.76290
## 7     Wed 31.50092

Observacions inicials:

-Preus: Oscil·len entre 18.12€ i 38.70€, amb una mitjana al voltant dels 32€ -Hores operatives: La cafeteria opera majoritàriament entre les 7h i les 22h -Begudes més populars: Cal analitzar la distribució

Es mostra com es reparteixen les compres al llarg del dia i com varia la despesa segons el dia de la setmana. Podem veure que hi ha hores i dies amb més ventes que altres.

1.2 Ingressos totals per tipus de beguda

library(ggplot2)

ggplot(dades, aes(x = coffee_name, y = money, fill = coffee_name)) +
  geom_bar(stat = "summary", fun = "sum") +
  labs(title = "Ingressos totals per tipus de beguda",
       x = "Tipus de beguda",
       y = "Total ingressos") +
  theme_minimal()

Aquest gràfic ajuda a veure quines begudes generen més ingressos. Podem veure que hi ha una variació clara en la venta de les diferents begudes.

1.3 Detecció de valors inusuals

# Boxplot per detectar valors extrems
boxplot(dades$money, main = "Detecció de valors inusuals en 'money'")

# Observacions potencialment extremes (Top 1%)
subset(dades, money > quantile(money, 0.99))
## # A tibble: 0 × 12
## # ℹ 12 variables: hour_of_day <dbl>, cash_type <chr>, money <dbl>,
## #   coffee_name <chr>, Time_of_Day <chr>, Weekday <chr>, Month_name <chr>,
## #   Weekdaysort <dbl>, Monthsort <dbl>, Date <date>, Time <time>,
## #   datetime <date>

Observem si hi ha tiquets amb imports molt més alts del normal.

1.4 Distribució d’Ingressos per Transacció

ggplot(dades, aes(x = money)) +
  geom_histogram(bins = 30, fill = "#8B4513", color = "white") +
  theme_minimal() +
  labs(
    title = "Distribució dels Imports per Transacció",
    x = "Import (€)",
    y = "Freqüència"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Interpretació:

-Es detecten 4-5 pics principals corresponents als diferents preus de begudes -Els preus semblen estar agrupats al voltant de valors específics (probablement els diferents tipus de begudes) -No s’observen valors aberrants significatius

1.6 Vendes per Hora del Dia

vendes_hora <- dades %>%
  group_by(hour_of_day) %>%
  summarise(
    num_vendes = n(),
    ingressos_totals = sum(money, na.rm = TRUE)
  )

ggplot(vendes_hora, aes(x = hour_of_day, y = num_vendes)) +
  geom_col(fill = "#D2691E") +
  geom_line(color = "red", size = 1) +
  theme_minimal() +
  scale_x_continuous(breaks = 6:22) +
  labs(
    title = "Nombre de Vendes per Hora del Dia",
    x = "Hora",
    y = "Nombre de Transaccions"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Patrons identificats:

  • Pic matinal: Entre les 8h-11h (hora d’esmorzar)
  • Pic de tarda: Entre les 14h-17h (després de dinar)
  • Pic nocturn modest: Al voltant de les 19h-21h
  • Hores vall: 6-7h i després de les 20h

Connexió amb la pregunta d’estudi: Aquest patró temporal és clau per entendre quan concentrar recursos i personal.

2. Anàlisi Descriptiva

En aquesta secció presentem estadístiques i visualitzacions que ajuden a respondre la pregunta d’estudi:

Quina és la relació entre el dia de la setmana, l’hora i el tipus de beguda amb la quantitat gastada?

2.1 Estadístiques descriptives bàsiques

# Estadístiques bàsiques d’import i hora
summary(dades[, c("hour_of_day", "money")])
##   hour_of_day        money      
##  Min.   : 6.00   Min.   :18.12  
##  1st Qu.:10.00   1st Qu.:27.92  
##  Median :14.00   Median :32.82  
##  Mean   :14.19   Mean   :31.65  
##  3rd Qu.:18.00   3rd Qu.:35.76  
##  Max.   :22.00   Max.   :38.70
# Desviació estàndard
sd_hour <- sd(dades$hour_of_day, na.rm = TRUE)
sd_money <- sd(dades$money, na.rm = TRUE)
sd_hour
## [1] 4.23401
sd_money
## [1] 4.877754

Aquest, ens dona una idea general de com es distribueixen les hores de compra i quins preus són més habituals. La mitjan i la mediana ens indiquen quines són les tendències generals, la desviació estàndard ens diu a quin punt les dades estan concentrades o disperses.

2.2 Comparació de diners gastats per dia de la setmana

aggregate(money ~ Weekday, data = dades, FUN = function(x) c(mean = mean(x), median = median(x), sd = sd(x)))
##   Weekday money.mean money.median  money.sd
## 1     Fri  31.583947    32.820000  4.913948
## 2     Mon  31.917463    32.820000  4.511083
## 3     Sat  31.347915    32.820000  5.003080
## 4     Sun  31.828305    32.820000  4.878133
## 5     Thu  31.551765    32.820000  5.187470
## 6     Tue  31.762902    32.820000  4.738134
## 7     Wed  31.500920    32.820000  4.939150
library(ggplot2)

ggplot(dades, aes(x = Weekday, y = money)) +
  geom_boxplot(fill = "lightblue") +
  labs(title = "Distribució de diners gastats per dia de la setmana",
       x = "Dia",
       y = "Import (money)") +
  theme_minimal()

Aquesta comparació entre dies, ens ajuda a veure si hi ha diferència en la despesa segons el dia de la setmana.

2.3 Detecció de punts anòmals en el consum

boxplot(dades$money, main = "Valors inusuals de diners gastats")

subset(dades, money > quantile(money, 0.99))  # top 1% de valors
## # A tibble: 0 × 12
## # ℹ 12 variables: hour_of_day <dbl>, cash_type <chr>, money <dbl>,
## #   coffee_name <chr>, Time_of_Day <chr>, Weekday <chr>, Month_name <chr>,
## #   Weekdaysort <dbl>, Monthsort <dbl>, Date <date>, Time <time>,
## #   datetime <date>

2.4 Estadístiques Descriptives Detallades

# Resum per dia de la setmana
resum_setmana <- dades %>%
  group_by(Weekday) %>%
  summarise(
    Transaccions = n(),
    Ingressos_Total = sum(money, na.rm = TRUE),
    Import_Mitjà = mean(money, na.rm = TRUE),
    Import_Mediana = median(money, na.rm = TRUE),
    Desviacio_Std = sd(money, na.rm = TRUE)
  ) %>%
  arrange(match(Weekday, c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")))

knitr::kable(resum_setmana, 
             caption = "Estadístiques per Dia de la Setmana",
             digits = 2)
Estadístiques per Dia de la Setmana
Weekday Transaccions Ingressos_Total Import_Mitjà Import_Mediana Desviacio_Std
Mon 544 17363.10 31.92 32.82 4.51
Tue 572 18168.38 31.76 32.82 4.74
Wed 500 15750.46 31.50 32.82 4.94
Thu 510 16091.40 31.55 32.82 5.19
Fri 532 16802.66 31.58 32.82 4.91
Sat 470 14733.52 31.35 32.82 5.00
Sun 419 13336.06 31.83 32.82 4.88

Hipòtesis emergents:

1.Hi ha una clara diferència en el volum de vendes segons l’hora del dia 2.El tipus de beguda està correlacionat amb el moment del dia 3.Els caps de setmana poden tenir un patró de consum diferent dels dies laborables

2.5 Gràfic entre anova i hora del dia

2.5.1 Boxplot per hora del dia

p1 <- ggplot(dades, aes(x = factor(hour_of_day), y = money)) +
  geom_boxplot(fill = "#D2691E", alpha = 0.7) +
  labs(title = "Distribució de l'import per hora del dia",
       x = "Hora del dia",
       y = "Import (€)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

El gràfic permet observar diferències clares en la distribució dels imports segons l’hora del dia. Algunes hores presenten una mediana més elevada i una major dispersió, fet que suggereix que l’hora del dia podria tenir un efecte significatiu sobre l’import de les vendes. Aquest resultat justifica l’aplicació d’un ANOVA per contrastar formalment les diferències entre hores.

2.5.2 Mitjanes amb intervals de confiança per hora

mitjanes_hora <- dades %>%
  group_by(hour_of_day) %>%
  summarise(
    mitjana = mean(money, na.rm = TRUE),
    sd = sd(money, na.rm = TRUE),
    n = n(),
    se = sd / sqrt(n),
    ic_inf = mitjana - 1.96 * se,
    ic_sup = mitjana + 1.96 * se
  )

p2 <- ggplot(mitjanes_hora, aes(x = hour_of_day, y = mitjana)) +
  geom_line(color = "#8B4513", size = 1) +
  geom_point(size = 3, color = "#D2691E") +
  geom_errorbar(aes(ymin = ic_inf, ymax = ic_sup), 
                width = 0.3, color = "#8B4513", alpha = 0.6) +
  labs(title = "Import mitjà per hora amb intervals de confiança (95%)",
       x = "Hora del dia",
       y = "Import mitjà (€)") +
  theme_minimal()

S’observa una variació clara de l’import mitjà al llarg del dia, amb franges horàries on la mitjana és notablement superior. Els intervals de confiança permeten visualitzar la incertesa associada a cada estimació i suggereixen que algunes diferències entre hores no es deuen únicament a la variabilitat aleatòria, reforçant la plausibilitat d’un efecte significatiu de l’hora del dia sobre l’import.

2.5.3 Visualització dels residus del model ANOVA (hora)

m_hour <- aov(money ~ factor(hour_of_day), data = dades)

dades_residus_hora <- tibble(
  ajustats = fitted(m_hour),
  residus = residuals(m_hour)
)

p3 <- ggplot(dades_residus_hora, aes(x = ajustats, y = residus)) +
  geom_point(alpha = 0.5, color = "#8B4513") +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  geom_smooth(method = "loess", se = FALSE, color = "blue") +
  labs(title = "Residus vs Valors ajustats (hora del dia)",
       x = "Valors ajustats",
       y = "Residus") +
  theme_minimal()

El núvol de punts no mostra patrons sistemàtics evidents ni una forma de ventall pronunciada, la qual cosa indica que l’assumpció d’homocedasticitat es compleix de manera raonable. Això suggereix que el model ANOVA és adequat des del punt de vista de la variància dels errors.

2.5.4 Q-Q plot pels residus (hora)

p4 <- ggplot(dades_residus_hora, aes(sample = residus)) +
  stat_qq(color = "#8B4513") +
  stat_qq_line(color = "red") +
  labs(title = "Q-Q Plot - Normalitat dels residus (hora del dia)",
       x = "Quantils teòrics",
       y = "Quantils observats") +
  theme_minimal()

Els punts segueixen aproximadament la línia diagonal, amb petites desviacions als extrems. Aquest comportament indica que l’assumpció de normalitat dels residus és raonablement satisfactòria, especialment tenint en compte la mida de la mostra.

2.6 Gràfics per anova - weekday

2.6.1 Boxplot per dia de la setmana

dades_ordenat <- dades %>%
  mutate(Weekday = factor(Weekday, 
                         levels = c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")))

p5 <- ggplot(dades_ordenat, aes(x = Weekday, y = money)) +
  geom_boxplot(fill = "#A0522D", alpha = 0.7) +
  labs(title = "Distribució de l'import per dia de la setmana",
       x = "Dia de la setmana",
       y = "Import (€)") +
  theme_minimal()

El boxplot mostra una distribució força similar dels imports entre els diferents dies de la setmana, amb lleugeres diferències en la mediana i la dispersió. Aquest gràfic suggereix que l’efecte del dia de la setmana podria ser més moderat que l’efecte de l’hora del dia, fet que serà contrastat amb l’ANOVA corresponent.

2.6.2 Mitjanes amb intervals de confiança per dia

mitjanes_dia <- dades_ordenat %>%
  group_by(Weekday) %>%
  summarise(
    mitjana = mean(money, na.rm = TRUE),
    sd = sd(money, na.rm = TRUE),
    n = n(),
    se = sd / sqrt(n),
    ic_inf = mitjana - 1.96 * se,
    ic_sup = mitjana + 1.96 * se
  )

p6 <- ggplot(mitjanes_dia, aes(x = Weekday, y = mitjana)) +
  geom_col(fill = "#A0522D", alpha = 0.7) +
  geom_errorbar(aes(ymin = ic_inf, ymax = ic_sup), 
                width = 0.3, color = "black") +
  geom_text(aes(label = round(mitjana, 2)), vjust = -0.5, size = 3) +
  labs(title = "Import mitjà per dia amb intervals de confiança (95%)",
       x = "Dia de la setmana",
       y = "Import mitjà (€)") +
  theme_minimal()

Les mitjanes diàries presenten diferències relativament petites, amb intervals de confiança que se solapen en diversos casos. Això indica que, visualment, les diferències entre dies són menys marcades, tot i que l’ANOVA permetrà determinar si aquestes diferències són estadísticament significatives.

2.7 Gràfics per anova - coffee_name

2.7.1 Boxplot per tipus de beguda

p7 <- ggplot(dades, aes(x = reorder(coffee_name, money, median), y = money)) +
  geom_boxplot(aes(fill = coffee_name), alpha = 0.7, show.legend = FALSE) +
  coord_flip() +
  labs(title = "Distribució de l'import per tipus de beguda",
       x = "Tipus de beguda",
       y = "Import (€)") +
  theme_minimal()

Aquest gràfic evidencia diferències clares en la distribució dels imports segons el tipus de beguda. Algunes begudes presenten medians més elevades i una major dispersió, fet coherent amb una estructura de preus diferenciada entre productes.

2.7.2 Mitjanes amb intervals de confiança per tipus de beguda

mitjanes_beguda <- dades %>%
  group_by(coffee_name) %>%
  summarise(
    mitjana = mean(money, na.rm = TRUE),
    sd = sd(money, na.rm = TRUE),
    n = n(),
    se = sd / sqrt(n),
    ic_inf = mitjana - 1.96 * se,
    ic_sup = mitjana + 1.96 * se
  ) %>%
  arrange(mitjana)

p8 <- ggplot(mitjanes_beguda, aes(x = reorder(coffee_name, mitjana), y = mitjana)) +
  geom_col(fill = "#CD853F", alpha = 0.7) +
  geom_errorbar(aes(ymin = ic_inf, ymax = ic_sup), 
                width = 0.3, color = "black") +
  coord_flip() +
  labs(title = "Import mitjà per tipus de beguda amb IC (95%)",
       x = "Tipus de beguda",
       y = "Import mitjà (€)") +
  theme_minimal()

Les mitjanes dels imports per tipus de beguda mostren diferències substancials, amb intervals de confiança que en molts casos no se solapen. Això suggereix un efecte fort del tipus de beguda sobre l’import de la transacció, fet esperable donada la naturalesa del producte.

2.7.3 Residus del model ANOVA (tipus de beguda)

m_coffee <- aov(money ~ coffee_name, data = dades)

dades_residus_coffee <- tibble(
  ajustats = fitted(m_coffee),
  residus = residuals(m_coffee),
  beguda = dades$coffee_name
)

p9 <- ggplot(dades_residus_coffee, aes(x = ajustats, y = residus)) +
  geom_point(aes(color = beguda), alpha = 0.5, show.legend = FALSE) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  geom_smooth(method = "loess", se = FALSE, color = "blue") +
  labs(title = "Residus vs Valors ajustats (tipus de beguda)",
       x = "Valors ajustats",
       y = "Residus") +
  theme_minimal()

Tot i una major dispersió associada a certs tipus de beguda, no s’observen patrons sistemàtics clars en els residus. Això indica que el model ANOVA és raonablement adequat també per analitzar l’efecte del tipus de beguda.

2.8 Comparació visual dels tres models

# 10. Comparació de la variabilitat explicada
models_r2 <- tibble(
  Model = c("Hora del dia", "Dia setmana", "Tipus beguda"),
  R2 = c(
    summary(aov(money ~ factor(hour_of_day), data = dades))[[1]][1,2] / 
      sum(summary(aov(money ~ factor(hour_of_day), data = dades))[[1]][,2]),
    summary(aov(money ~ Weekday, data = dades))[[1]][1,2] / 
      sum(summary(aov(money ~ Weekday, data = dades))[[1]][,2]),
    summary(aov(money ~ coffee_name, data = dades))[[1]][1,2] / 
      sum(summary(aov(money ~ coffee_name, data = dades))[[1]][,2])
  )
)

p10 <- ggplot(models_r2, aes(x = reorder(Model, R2), y = R2)) +
  geom_col(fill = c("#8B4513", "#A0522D", "#CD853F"), alpha = 0.8) +
  geom_text(aes(label = paste0(round(R2 * 100, 1), "%")), 
            hjust = -0.2, size = 4) +
  coord_flip() +
  ylim(0, 1) +
  labs(title = "Comparació de variància explicada (R²) dels models ANOVA",
       x = "Model",
       y = "Proporció de variància explicada (R²)") +
  theme_minimal()

El model basat en el tipus de beguda explica una proporció de variància clarament superior, seguit pel model de l’hora del dia. El dia de la setmana presenta el menor poder explicatiu. Aquest resultat indica que el preu del producte és el principal factor determinant de l’import de la transacció, mentre que els factors temporals tenen un efecte secundari.

# ==============================================================================
# MOSTRAR TOTS ELS GRÀFICS
# ==============================================================================

# Combinació de gràfics amb patchwork
print("Gràfics ANOVA - Hora del dia:")
## [1] "Gràfics ANOVA - Hora del dia:"
(p1 | p2) / (p3 | p4)
## `geom_smooth()` using formula = 'y ~ x'

print("\nGràfics ANOVA - Dia de la setmana:")
## [1] "\nGràfics ANOVA - Dia de la setmana:"
(p5 | p6)

print("\nGràfics ANOVA - Tipus de beguda:")
## [1] "\nGràfics ANOVA - Tipus de beguda:"
(p7 | p8) / p9
## `geom_smooth()` using formula = 'y ~ x'

print("\nComparació de models:")
## [1] "\nComparació de models:"
p10

# També pots guardar els gràfics
# ggsave("anova_hora.png", (p1 | p2) / (p3 | p4), width = 12, height = 10)
# ggsave("anova_weekday.png", (p5 | p6), width = 10, height = 5)
# ggsave("anova_beguda.png", (p7 | p8) / p9, width = 12, height = 10)
# ggsave("comparacio_models.png", p10, width = 8, height = 5) 

Interpretació, conclusions, limitacions i possibles línies futures

1. Conclusions Principals

  • Patrons Temporals Clars:

  • Tres pics principals de vendes: matí (8-11h), tarda (14-17h) i nit primerenca (19-21h)

  • Els matins són el moment de màxima activitat

  • Preferències de Begudes:

  • Americano domina en nombre de vendes

  • Les preferències varien segons el moment del dia (cafès senzills al matí, més elaborats a la tarda)

  • Ingressos:

  • Els ingressos són relativament constants entre dies laborables

  • Hi ha variabilitat mensual que cal explorar més

  • Preus Estratificats:

  • El dataset mostra 4-5 nivells de preu clars, corresponents als diferents tipus de begudes

2. Limitacions Identificades

  • Cobertura Temporal:

Cal verificar si tenim dades completes per cada mes Alguns mesos poden tenir més dades que altres

  • Variables Absents:

No tenim informació sobre:

Condicions meteorològiques Esdeveniments especials o festius Nombre de clients (vs. transaccions) Cost de producció per calcular benefici net

  • Qualitat de Dades:

Tots els pagaments són amb targeta (cash_type = “card”). No hi ha valors perduts evidents, però cal verificar inconsistències.

  • Mida de Mostra:

Tot i tenir 3,547 observacions, alguns segments (hores específiques, dies concrets) poden tenir poca representació.

3. Pròximes Passes Proposades

Valor Aplicat: Els resultats d’aquesta anàlisi poden ajudar a:

Optimitzar la dotació de personal segons hores punta Gestionar millor l’inventari segons preferències temporals Dissenyar promocions específiques per hores/dies de menys activitat Millorar l’oferta de productes segons moment del dia