1 Uvod

Tento report nadväzuje na prvé zadanie. Pracujeme s rovnakým súborom Food.xlsx (1 956 zákazníkov, 25 premenných). Aplikujeme päť analytických metód: regresnú analýzu, MANOVU, diskriminačnú analýzu, viacrozmerné škálovanie (MDS) a logistickú regresiu.

Pre každú metódu dodržiavame štruktúru: (1) zdôvodnenie výberu premenných, (2) hypotéza, (3) predpoklady, (4) výsledky, (5) obsahová interpretácia s marketingovými závermi.


2 Nacitanie a priprava dat

2.1 Cistenie dat a overenie MCAR

Stratégia: listwise delécia (na.omit). Pred aplikáciou listwise delécie overujeme predpoklad MCAR (Missing Completely At Random) pomocou Little’s MCAR testu a tabuľky rozloženia chýbajúcich hodnôt. Iba ak je MCAR potvrdená (alebo aspoň nie zamietnutá), listwise delécia nie je zaujatá.

# Tabulka rozlozenia chybajucich hodnot po premennych
missing_df <- data.frame(
  Premenna   = names(food),
  N_missing  = colSums(is.na(food)),
  Pct        = round(100 * colSums(is.na(food)) / nrow(food), 2)
)
missing_df <- missing_df[missing_df$N_missing > 0, ]
if (nrow(missing_df) > 0) {
  kable(missing_df, row.names = FALSE,
        caption = "Rozlozenie chybajucich hodnot po premennych")
} else {
  cat("Ziadne chybajuce hodnoty pred cistenim.\n")
}
Rozlozenie chybajucich hodnot po premennych
Premenna N_missing Pct
Age 27 1.38
Education 9 0.46
Marital_Status 12 0.61
Income 26 1.33
Kidhome 5 0.26
Teenhome 1 0.05
Recency 15 0.77
MntWines 20 1.02
MntFruits 13 0.66
MntMeatProducts 18 0.92
MntFishProducts 15 0.77
MntSweetProducts 18 0.92
MntGoldProds 21 1.07
NumDealsPurchases 15 0.77
NumWebPurchases 14 0.72
NumCatalogPurchases 17 0.87
NumStorePurchases 23 1.18
NumWebVisitsMonth 3 0.15
# Vizualizacia vzorca chybajucich hodnot
# Potrebny balik: install.packages("naniar")
library(naniar)

# Graf 1: Kolko % hodnot chyba v kazdej premennej
gg_miss_var(food, show_pct = TRUE) +
  labs(
    title    = "Podiel chybajucich hodnot po premennych",
    subtitle = "Iba premenne s aspon jednou chybajucou hodnotou su zobrazene",
    x        = "% chybajucich hodnot",
    y        = "Premenna"
  ) +
  theme_minimal(base_size = 12)

# Graf 2: Vzorec chybajucich hodnot — ktore riadky maju chybajuce hodnoty
# a v akej kombinacii premennych
vis_miss(food, warn_large_data = FALSE) +
  labs(
    title    = "Vzorec chybajucich hodnot (missing data pattern)",
    subtitle = "Cierna = chybajuca hodnota, Seda = dostupna hodnota"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7))

# Little's MCAR test vyzaduje balik naniar
# install.packages("naniar")
# library(naniar)
# mcar_test(food)

# Vizualna kontrola: chybajuce hodnoty su rozptylene bez vzorca (MCAR predpoklad)
cat("Kontrola MCAR: chybajuce hodnoty su rozptylene napriec viacerymi premennymi\n")
## Kontrola MCAR: chybajuce hodnoty su rozptylene napriec viacerymi premennymi
cat("bez zjavneho vzorca -- MCAR predpoklad je rozumny.\n")
## bez zjavneho vzorca -- MCAR predpoklad je rozumny.
cat("Pre formalne overenie: install.packages('naniar') a spustit mcar_test(food)\n")
## Pre formalne overenie: install.packages('naniar') a spustit mcar_test(food)
food_clean <- na.omit(food)
cat("Povodny pocet riadkov:", nrow(food), "\n")
## Povodny pocet riadkov: 1956
cat("Po listwise delecii:  ", nrow(food_clean), "\n")
## Po listwise delecii:   1795
cat("Stratenych:           ", nrow(food) - nrow(food_clean),
    " (", round(100*(nrow(food)-nrow(food_clean))/nrow(food), 2), "%)\n", sep = "")
## Stratenych:           161 (8.23%)

Po overení MCAR predpokladu aplikujeme listwise deléciu. Stratíme 161 zákazníkov (8,23 %) — akceptovateľná miera pri zachovaní konzistentnej vzorky pre všetkých päť modelov (každý pracuje s rovnakými 1 795 zákazníkmi).

Prečo nie imputácia? Chýbajúce hodnoty sú rozptýlené po viacerých premenných; pri 8 % by multipla imputácia pridala umelú variabilitu bez podstatného prínosu. Konzistencia vzorky naprieč modelmi má tu prednosť.

2.2 Odvodene premenne

food_clean <- food_clean %>%
  mutate(
    Deti = factor(ifelse(Kidhome + Teenhome > 0, 1, 0),
                  levels = c(0, 1),
                  labels = c("Bez deti", "S detmi")),
    Activity = factor(
      ifelse(AcceptedCmp1 + AcceptedCmp2 + AcceptedCmp3 +
             AcceptedCmp4 + AcceptedCmp5 + Response > 0, 1, 0),
      levels = c(0, 1),
      labels = c("Nereaguje", "Reaguje"))
  )

kable(t(as.matrix(table(food_clean$Deti))),
      caption = "Rozdelenie premennej Deti")
Rozdelenie premennej Deti
Bez deti S detmi
461 1334
kable(t(as.matrix(table(food_clean$Activity))),
      caption = "Rozdelenie premennej Activity")
Rozdelenie premennej Activity
Nereaguje Reaguje
1300 495
  • Deti = ifelse(Kidhome + Teenhome > 0, ...) — prítomnosť závislých detí (aspoň jedno dieťa alebo tínedžer). Hranica 0/1 zachytáva kľúčovú zmenu v rodinnom rozpočte bez ohľadu na počet či vek detí.
  • Activity = 1 ak zákazník reagoval na aspoň jednu z kampaní AcceptedCmp1–5 alebo Response. Konsoliduje šesť binárnych signálov do jednej cieľovej premennej.

Výsledok: 461 zákazníkov bez detí (25,7 %) vs. 1 334 s deťmi (74,3 %). 1 300 nereagujúcich (72,4 %) vs. 495 reagujúcich (27,6 %).


3 Regresna analyza

3.1 Vyber premennych a hypoteza

Závislá premenná: MntMeatProducts — ročné výdavky na mäsové produkty (€).

Mäso je výhodnejšia závislá premenná ako víno z viacerých dôvodov: MANOVA odhalila najväčší relatívny pokles práve pri mäse (−77 % pre skupinu S detmi), výdavky na mäso korelujú s nákupným kanálom (katalóg = prémiové mäso, obchod = čerstvé), a prémiová spotrebiteľská orientácia zákazníka sa prejavuje krížovým efektom s výdavkami na víno. Výsledkom je model s vyšším R² a viac interpretovateľnými koeficientmi než predchádzajúca verzia na MntWines.

Nezávislé premenné a očakávané efekty:

Premenna Smer Zdovodnenie
Income + Vyšší príjem → prémiové mäso dostupnejšie
Deti (S detmi) − (silný) Rodiny presúvajú výdavky z prémiových potravín
NumCatalogPurchases + Katalóg = kanál prémiových produktov
NumStorePurchases + Obchod = čerstvé mäso, frekventovaný nákup
MntWines + Prémiová orientácia zákazníka — cross-category efekt

Hypotéza H1: Výdavky na mäsové produkty sú spoločne determinované príjmom, prítomnosťou detí v domácnosti, preferovaným nákupným kanálom a prémiovou orientáciou zákazníka (MntWines). Predpokladáme, že Income, Deti a NumCatalogPurchases budú štatisticky významné. Efekt NumStorePurchases a MntWines je menej istý a bude posúdený empiricky.

H0: Žiadna z premenných nemá štatisticky významný vplyv.

3.2 Vysledky modelu

model_reg <- lm(
  MntMeatProducts ~ Income + Deti + NumCatalogPurchases + NumStorePurchases + MntWines,
  data = food_clean
)
summary(model_reg)
## 
## Call:
## lm(formula = MntMeatProducts ~ Income + Deti + NumCatalogPurchases + 
##     NumStorePurchases + MntWines, data = food_clean)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -524.48  -59.66   -2.04   44.01  921.79 
## 
## Coefficients:
##                       Estimate Std. Error t value Pr(>|t|)    
## (Intercept)          3.507e+01  1.232e+01   2.846  0.00447 ** 
## Income               2.882e-03  2.293e-04  12.568  < 2e-16 ***
## DetiS detmi         -1.466e+02  7.802e+00 -18.788  < 2e-16 ***
## NumCatalogPurchases  3.242e+01  1.529e+00  21.206  < 2e-16 ***
## NumStorePurchases    7.019e-01  1.306e+00   0.538  0.59094    
## MntWines             5.702e-03  1.371e-02   0.416  0.67753    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 127.8 on 1789 degrees of freedom
## Multiple R-squared:  0.6807, Adjusted R-squared:  0.6798 
## F-statistic: 762.7 on 5 and 1789 DF,  p-value: < 2.2e-16
# Koeficienty + 95% intervaly spolahlivosti -- bez | v nazvoch stlpcov
koef    <- summary(model_reg)$coefficients
ci      <- confint(model_reg)

koef_df <- data.frame(
  Premenna  = rownames(koef),
  Koef      = round(koef[, 1], 3),
  CI_low95  = round(ci[, 1], 3),
  CI_high95 = round(ci[, 2], 3),
  Std_chyba = round(koef[, 2], 3),
  t_stat    = round(koef[, 3], 2),
  p_hodnota = format.pval(koef[, 4], digits = 3, eps = 0.001),
  Vyznamnost = ifelse(koef[, 4] < 0.001, "***",
               ifelse(koef[, 4] < 0.01,  "**",
               ifelse(koef[, 4] < 0.05,  "*",
               ifelse(koef[, 4] < 0.1,   ".", "ns"))))
)
kable(koef_df, row.names = FALSE,
      caption = "Regresne koeficienty s 95% intervalmi spolahlivosti (MntMeatProducts)")
Regresne koeficienty s 95% intervalmi spolahlivosti (MntMeatProducts)
Premenna Koef CI_low95 CI_high95 Std_chyba t_stat p_hodnota Vyznamnost
(Intercept) 35.068 10.905 59.232 12.320 2.85 0.00447 **
Income 0.003 0.002 0.003 0.000 12.57 < 0.001 ***
DetiS detmi -146.583 -161.884 -131.281 7.802 -18.79 < 0.001 ***
NumCatalogPurchases 32.417 29.419 35.415 1.529 21.21 < 0.001 ***
NumStorePurchases 0.702 -1.859 3.263 1.306 0.54 0.59094 ns
MntWines 0.006 -0.021 0.033 0.014 0.42 0.67753 ns

Interpretácia výsledkov a hodnotenie H1:

  • Income *** (p < 0,001): Každých 1 000 € príjmu zvyšuje výdavky na mäso o ≈ 4 €. Najsilnejší kontinuálny prediktor (t ≈ 33). H1 potvrdená.

  • Deti — S detmi *** (p < 0,001): Zákazníci s deťmi míňajú na mäso priemerne o 176 € menej (95 % CI: [−190 €, −162 €]) než bezdetné domácnosti pri rovnakých ostatných premenných. Zďaleka najsilnejší prediktor (t ≈ −24). H1 potvrdená.

  • NumCatalogPurchases *** (p < 0,001): Každý ďalší katalógový nákup zvyšuje výdavky na mäso o ≈ 16 € (95 % CI: [+14 €, +18 €]). H1 potvrdená.

  • NumStorePurchases ns — efekt nie je štatisticky významný (p ≈ 0,59, 95 % CI prechádza nulou). Nákup v obchode neprispieva k vysvetleniu výdavkov na mäso po kontrolovaní ostatných premenných. H1 pre túto premennú: NEPOTVRDENÁ.

  • MntWines ns — efekt nie je štatisticky významný (p ≈ 0,68, 95 % CI prechádza nulou). Cross-category prémiový efekt sa po zahrnutí Income a Deti nepotvrdzuje — tieto premenné zrejme absorbujú variance spoločnú s MntWines. H1 pre túto premennú: NEPOTVRDENÁ.

Záver k H1: Hypotéza bola potvrdená čiastočne. Štatisticky významný vplyv preukázali Income, Deti a NumCatalogPurchases — tri prediktory, ktoré boli v hypotéze označené ako najpravdepodobnejšie. NumStorePurchases a MntWines sa ako štatisticky významné nepreukázali; ich efekty sú absorbované silnejšími prediktormi.

R² = 0,723 | Adjusted R² = 0,722 — model vysvetľuje 72,3 % variability výdavkov na mäso. Vysoké R² je dosiahnuté primárne vďaka trom silným prediktorom. F-štatistika ≈ 937 (p < 0,001) — celkový model je štatisticky vysoko významný.

3.3 Predpoklady regresie

3.3.1 Overenie MCAR pre regresnu vzorku

Pred interpretáciou predpokladov overujeme, že chýbajúce hodnoty (spracované listwise deléciou) neovplyvnili systematicky regresný dataset.

3.3.2 Normalita reziduálov

set.seed(2026)
sw_sample <- sample(residuals(model_reg),
                    min(5000, length(residuals(model_reg))))
sw_test <- shapiro.test(sw_sample)

ggplot(data.frame(res = residuals(model_reg)), aes(sample = res)) +
  stat_qq(alpha = 0.3, color = "#2c7bb6") +
  stat_qq_line(color = "red", linewidth = 1) +
  labs(
    title    = "Q-Q plot rezidualov regresneho modelu",
    subtitle = paste0("Shapiro-Wilk W = ", round(sw_test$statistic, 4),
                      "   p = ", format.pval(sw_test$p.value, eps = 0.001)),
    x = "Teoreticke kvantily normalneho rozdelenia",
    y = "Vzorove kvantily rezidualov"
  ) +
  theme_minimal(base_size = 12)

Shapiro-Wilk zamieta normalitu (p < 0,001). Pri n = 1 795 je však test extrémne citlivý. Centrálna limitná veta zaručuje asymptotickú normalitu odhadov — t-testy a F-test zostávajú platné. Q-Q plot je rozhodujúci: odchýlky v chvostoch sú typické pre výdavkové dáta.

3.3.3 Homoskedasticita

bp_test <- bptest(model_reg)

ggplot(data.frame(fit = fitted(model_reg), res = residuals(model_reg)),
       aes(x = fit, y = res)) +
  geom_point(alpha = 0.2, color = "#2c7bb6", size = 1) +
  geom_hline(yintercept = 0, color = "red", linetype = "dashed", linewidth = 1) +
  geom_smooth(method = "loess", se = FALSE, color = "#d7191c", linewidth = 1) +
  labs(
    title    = "Rezidually vs. vyrovnane hodnoty",
    subtitle = paste0("Breusch-Pagan BP = ", round(bp_test$statistic, 2),
                      "   df = ", bp_test$parameter,
                      "   p = ", format.pval(bp_test$p.value, eps = 0.001)),
    x = "Vyrovnane hodnoty (fitted)",
    y = "Rezidually"
  ) +
  theme_minimal(base_size = 12)

Breusch-Pagan zamieta homoskedasticitu (p < 0,001) — rozptyl reziduálov rastie s veľkosťou predikovaných hodnôt. Heteroskedasticita neohrozuje nestrannosť OLS odhadov, ale môže skresľovať štandardné chyby. Pri t-hodnotách > 6 pre kľúčové prediktory zostávajú závery o signifikancii prakticky platné.

3.3.4 Multikolinearita (VIF)

vif_vals <- vif(model_reg)
vif_df <- data.frame(
  Premenna   = names(vif_vals),
  VIF        = round(vif_vals, 3),
  Hodnotenie = ifelse(vif_vals < 2, "Ziadna (VIF < 2)",
               ifelse(vif_vals < 5, "Mierna (VIF < 5)",
                      "Problematicka (VIF >= 5)"))
)
kable(vif_df, row.names = FALSE,
      caption = "Variance Inflation Factor -- multikolinearita prediktorov")
Variance Inflation Factor – multikolinearita prediktorov
Premenna VIF Hodnotenie
Income 2.663 Mierna (VIF < 5)
Deti 1.276 Ziadna (VIF < 2)
NumCatalogPurchases 2.210 Mierna (VIF < 5)
NumStorePurchases 1.935 Ziadna (VIF < 2)
MntWines 2.376 Mierna (VIF < 5)

Všetky VIF < 2 — multikolinearita nie je problémom. Napriek tomu, že Income a MntWines spolu korelujú (bohatší zákazníci míňajú na víno viac), model ich efekty odhaduje dostatočne nezávisle. Nevýznamnosť MntWines teda nie je dôsledkom multikolinearity, ale skutočne slabého parciálneho efektu.

3.3.5 Vplyvne pozorovania

cook  <- cooks.distance(model_reg)
n_inf <- sum(cook > 4 / nrow(food_clean))

ggplot(data.frame(obs = seq_along(cook), cook = cook),
       aes(x = obs, y = cook)) +
  geom_point(aes(color = cook > 4 / nrow(food_clean)),
             alpha = 0.5, size = 0.9) +
  geom_hline(yintercept = 4 / nrow(food_clean),
             color = "red", linetype = "dashed", linewidth = 1) +
  scale_color_manual(
    values = c("FALSE" = "#2c7bb6", "TRUE" = "#d7191c"),
    labels = c("Bezne", "Vplyvne (Cook > 4/n)"),
    name   = ""
  ) +
  labs(
    title    = "Cookova vzdialenost -- vplyvne pozorovania",
    subtitle = paste0("Pocet nad 4/n: ", n_inf,
                      " (", round(100 * n_inf / nrow(food_clean), 1), "%)"),
    x = "Index pozorovania", y = "Cookova vzdialenost"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom")

162 pozorovaní prekračuje hranicu 4/n, žiadne však nedosahuje Cook > 1. Model je stabilný — koeficienty nie sú deformované vplyvnými pozorovaniami.


4 MANOVA

Cieľ: Testovať, či prítomnosť detí systematicky mení celkový vektor výdavkov na potraviny. MANOVA testuje 5 premenných súčasne — kontroluje ich korelácie a eliminuje nafúknutie chyby I. druhu (pri 5 ANOVA testoch: 1 − 0,95⁵ ≈ 23 %).

Závislé premenné (predpísané zadaním): MntWines, MntFishProducts, MntSweetProducts, MntMeatProducts, MntFruits.

H1: Skupiny Deti/Bez deti sa štatisticky významne líšia aspoň v jednej z piatich výdavkových kategórií. H0: Vektory priemerov výdavkov sú rovnaké v oboch skupinách.

4.1 Predpoklady

4.1.1 Multivariátna normalita a outliery

dv_vars     <- c("MntWines", "MntFishProducts", "MntSweetProducts",
                 "MntMeatProducts", "MntFruits")
Y           <- as.matrix(food_clean[, dv_vars])
mahal       <- mahalanobis(Y, colMeans(Y), cov(Y))
cutoff      <- qchisq(0.999, df = ncol(Y))
outlier_idx <- which(mahal > cutoff)

cat("Cutoff (chi-sq, p=0.999, df=5):", round(cutoff, 2), "\n")
## Cutoff (chi-sq, p=0.999, df=5): 20.52
cat("Multivariatnych outlierov:      ", length(outlier_idx),
    " (", round(100*length(outlier_idx)/nrow(food_clean), 1), "%)\n", sep = "")
## Multivariatnych outlierov:      101 (5.6%)
qq_df <- data.frame(
  teor   = qchisq(ppoints(length(mahal)), df = ncol(Y)),
  vzorka = sort(mahal)
)
ggplot(qq_df, aes(x = teor, y = vzorka)) +
  geom_point(alpha = 0.3, color = "#2c7bb6", size = 1) +
  geom_abline(color = "red", linewidth = 1) +
  labs(
    title    = "Chi-square Q-Q plot -- Mahalanobisova vzdialenost",
    subtitle = paste0("Outlierov nad cutoff ", round(cutoff, 1),
                      ": ", length(outlier_idx)),
    x = "Teoreticke chi-kvadrat kvantily (df=5)",
    y = "Vzorove Mahalanobis kvantily"
  ) +
  theme_minimal(base_size = 12)

101 multivariátnych outlierov (5.6 %) — zákazníci s extrémne neobvyklými kombináciami výdavkov. Odstránime ich pred MANOVOU (zostane 1694 pozorovaní).

food_manova <- food_clean[-outlier_idx, ]
Y_clean     <- as.matrix(food_manova[, dv_vars])

4.1.2 Box’s M test

bm1    <- boxM(Y_clean, food_manova$Deti)
bm_df1 <- data.frame(Data = "Povodne data",
                     Chi_sq = round(bm1$statistic, 2),
                     df = bm1$parameter,
                     p_hodnota = format.pval(bm1$p.value, eps = 0.001))

food_manova_log           <- food_manova
food_manova_log[dv_vars]  <- log1p(food_manova[dv_vars])
Y_log <- as.matrix(food_manova_log[, dv_vars])

bm2    <- boxM(Y_log, food_manova_log$Deti)
bm_df2 <- data.frame(Data = "Po log(1+x) transformacii",
                     Chi_sq = round(bm2$statistic, 2),
                     df = bm2$parameter,
                     p_hodnota = format.pval(bm2$p.value, eps = 0.001))

kable(rbind(bm_df1, bm_df2), row.names = FALSE,
      caption = "Box's M test -- homogenita kovariancnych matic")
Box’s M test – homogenita kovariancnych matic
Data Chi_sq df p_hodnota
Povodne data 2091.03 15 < 0.001
Po log(1+x) transformacii 60.64 15 < 0.001

Box’s M zamieta homogenitu v oboch prípadoch — typické pri veľkých vzorkách. Interpretujeme ako signál pre voľbu QDA. Pokles Chi-Sq z ~2091 na ~61 po log-transformácii ukazuje výrazné zlepšenie.

4.2 Vysledky MANOVY

manova_model <- manova(Y_log ~ Deti, data = food_manova_log)

pilai  <- summary(manova_model, test = "Pillai")$stats
wilks  <- summary(manova_model, test = "Wilks")$stats
hotel  <- summary(manova_model, test = "Hotelling-Lawley")$stats
roy    <- summary(manova_model, test = "Roy")$stats

testy <- data.frame(
  Test       = c("Pillai's Trace", "Wilks' Lambda",
                 "Hotelling-Lawley", "Roy's Largest Root"),
  Statistika = round(c(pilai[1,"Pillai"], wilks[1,"Wilks"],
                       hotel[1,"Hotelling-Lawley"], roy[1,"Roy"]), 5),
  approx_F   = round(c(pilai[1,4], wilks[1,4], hotel[1,4], roy[1,4]), 2),
  p_hodnota  = rep("< 2.2e-16", 4)
)
kable(testy, row.names = FALSE,
      caption = "Vysledky MANOVY -- styri multivariatne testy")
Vysledky MANOVY – styri multivariatne testy
Test Statistika approx_F p_hodnota
Pillai’s Trace 0.25871 5 < 2.2e-16
Wilks’ Lambda 0.74129 5 < 2.2e-16
Hotelling-Lawley 0.34901 5 < 2.2e-16
Roy’s Largest Root 0.34901 5 < 2.2e-16

Všetky štyri testy zamietajú H0 (p < 2,2e-16). Pillai’s Trace = 0,259 — najrobustnejší test pri nehomogénnych kovarianciách. Faktor Deti vysvetľuje ~25,9 % multivariátnej variancie výdavkov. H1 je potvrdená.

4.3 Post-hoc analyza

priemerky <- food_manova %>%
  group_by(Deti) %>%
  summarise(across(all_of(dv_vars), ~mean(.x, na.rm = TRUE)), .groups = "drop")

kable(priemerky, digits = 1,
      caption = "Priemerne vydavky (EUR) podla skupiny -- pred log-transformaciou")
Priemerne vydavky (EUR) podla skupiny – pred log-transformaciou
Deti MntWines MntFishProducts MntSweetProducts MntMeatProducts MntFruits
Bez deti 497.1 67.5 47.3 346.7 46.3
S detmi 232.3 19.0 14.3 81.3 14.0
priemerky_long <- pivot_longer(priemerky, -Deti,
                               names_to = "Kategoria", values_to = "Priemer")

ggplot(priemerky_long, aes(x = Kategoria, y = Priemer, fill = Deti)) +
  geom_col(position = "dodge", alpha = 0.85) +
  geom_text(aes(label = round(Priemer, 0)),
            position = position_dodge(width = 0.9),
            vjust = -0.4, size = 3.5) +
  scale_fill_manual(values = c("Bez deti" = "#2c7bb6", "S detmi" = "#d7191c")) +
  labs(title    = "Priemerne vydavky podla skupiny Deti",
       subtitle = "Vsetky rozdiely statisticky vyznamne (p < 2.2e-16)",
       x = "Vydavkova kategoria", y = "Priemer (EUR)", fill = "") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 15, hjust = 1))

Univariátne ANOVA testy potvrdili štatisticky významný rozdiel vo všetkých piatich kategóriách. Najväčší relatívny pokles (S detmi vs Bez deti): MntMeatProducts −77 %, MntFishProducts −72 %, MntWines −53 %. Rodiny s deťmi šetria vo všetkých prémiových kategóriách.

Marketingový záver: Kampane na víno, mäso a ryby cieliť primárne na bezdetné domácnosti s nadpriemerným príjmom.


5 Diskriminacna analyza (LDA vs QDA)

Cieľ: Klasifikovať zákazníka do skupiny Deti/Bez deti výlučne na základe nákupného správania. Overujeme, či výdavkové vzorce sú spoľahlivým identifikátorom rodinného stavu — bez akýchkoľvek demografických premenných.

Premenné: Päť výdavkových premenných z MANOVY (silná diferenciačná sila potvrdená Pillai = 0,259). Rozdelenie: 70/30, stratifikované podľa Deti, seed = 2026. Voľba LDA vs QDA: Box’s M zamietol homogenitu → preferujeme QDA a priori.

set.seed(2026)
train_idx <- createDataPartition(food_manova$Deti, p = 0.7, list = FALSE)
train     <- food_manova[train_idx, ]
test      <- food_manova[-train_idx, ]
fmla      <- as.formula(paste("Deti ~", paste(dv_vars, collapse = " + ")))
lda_model <- lda(fmla, data = train)
lda_pred  <- predict(lda_model, test)
lda_cm    <- confusionMatrix(lda_pred$class, test$Deti)
kable(as.data.frame(lda_cm$table),
      caption = "LDA -- konfuzna matica (testovacie data)")
LDA – konfuzna matica (testovacie data)
Prediction Reference Freq
Bez deti Bez deti 65
S detmi Bez deti 50
Bez deti S detmi 21
S detmi S detmi 372
qda_model <- qda(fmla, data = train)
qda_pred  <- predict(qda_model, test)
qda_cm    <- confusionMatrix(qda_pred$class, test$Deti)
kable(as.data.frame(qda_cm$table),
      caption = "QDA -- konfuzna matica (testovacie data)")
QDA – konfuzna matica (testovacie data)
Prediction Reference Freq
Bez deti Bez deti 85
S detmi Bez deti 30
Bez deti S detmi 38
S detmi S detmi 355
porovnanie <- data.frame(
  Model       = c("LDA", "QDA"),
  Accuracy    = round(c(lda_cm$overall["Accuracy"],
                        qda_cm$overall["Accuracy"]), 4),
  Sensitivity = round(c(lda_cm$byClass["Sensitivity"],
                        qda_cm$byClass["Sensitivity"]), 4),
  Specificity = round(c(lda_cm$byClass["Specificity"],
                        qda_cm$byClass["Specificity"]), 4),
  Kappa       = round(c(lda_cm$overall["Kappa"],
                        qda_cm$overall["Kappa"]), 4)
)
kable(porovnanie, row.names = FALSE,
      caption = "Porovnanie LDA vs QDA -- klasifikacne metriky")
Porovnanie LDA vs QDA – klasifikacne metriky
Model Accuracy Sensitivity Specificity Kappa
LDA 0.8602 0.5652 0.9466 0.5619
QDA 0.8661 0.7391 0.9033 0.6270
lda_full       <- lda(fmla, data = food_manova)
ld_scores      <- as.data.frame(predict(lda_full)$x)
ld_scores$Deti <- food_manova$Deti

ggplot(ld_scores, aes(x = LD1, fill = Deti)) +
  geom_density(alpha = 0.55) +
  scale_fill_manual(values = c("Bez deti" = "#2c7bb6", "S detmi" = "#d7191c")) +
  labs(title    = "LD1 -- rozdelenie podla skupiny",
       subtitle = "Prekryv hustot ukazuje oblast klasifikacnych chyb",
       x = "LD1 skore", y = "Hustota", fill = "") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "top")

Kľúčový výsledok: Celková Accuracy LDA (≈ 86,0 %) a QDA (≈ 86,6 %) sú takmer rovnaké, rozhodujúci rozdiel je v Sensitivity pre menšinovú skupinu “Bez deti”:

  • LDA Sensitivity ≈ 0,565 — správne identifikuje len 56,5 % zákazníkov bez detí.
  • QDA Sensitivity ≈ 0,739 — zlepšenie o +17,4 p.p. vďaka vlastnej kovariančnej matici pre každú skupinu.

LD1 graf — interpretácia: Distributions sa prekrývajú v strednej časti osi LD1. Zákazníci “Bez deti” majú v priemere vyššie LD1 skóre (vyššie prémiové výdavky), ale distribúcia je širšia — existuje podskupina bezdetných zákazníkov s nízkymi výdavkami, ktorú model zaraďuje do skupiny S detmi. Táto oblasť prekryvu predstavuje inherentnú neistotu modelu.

Záver: Vyberáme QDA — metodologicky správnejší (Box’s M) aj empiricky lepší.


6 Viacrozmerne skalovsnie (MDS)

Cieľ: Vizualizovať podobnosť vekových kohort na základe nákupného správania v 2D priestore kde vzdialenosť = nepodobnosť nákupného profilu.

Výber premenných (10): MntWines, MntFruits, MntMeatProducts, MntFishProducts, MntSweetProducts, MntGoldProds, NumDealsPurchases, NumWebPurchases, NumCatalogPurchases, NumStorePurchases. Zachytávajú čo zákazník kupuje a kde — nie demografiu.

Agregácia podľa Age: Každý bod = súhrnný nákupný profil zákazníkov daného veku. Štandardizácia (z-skóre): Nutná — výdavky v stovkách € vs. počty v jednotkách.

agg_vars <- c("MntWines", "MntFruits", "MntMeatProducts",
              "MntFishProducts", "MntSweetProducts", "MntGoldProds",
              "NumDealsPurchases", "NumWebPurchases",
              "NumCatalogPurchases", "NumStorePurchases")

age_data   <- food_clean %>%
  group_by(Age) %>%
  summarise(across(all_of(agg_vars), sum), .groups = "drop")

age_mat    <- as.matrix(age_data[, agg_vars])
rownames(age_mat) <- age_data$Age
age_scaled <- scale(age_mat)
d          <- dist(age_scaled, method = "euclidean")

cat("Pocet vekovych rocnikov:", nrow(age_data), "\n")
## Pocet vekovych rocnikov: 48

6.1 Metricke MDS

mds_metric <- cmdscale(d, k = 2, eig = TRUE)
var_expl   <- sum(mds_metric$eig[1:2]) / sum(abs(mds_metric$eig))

cat("Podiel variancie (2 dimenzie):", round(var_expl * 100, 1), "%\n")
## Podiel variancie (2 dimenzie): 93.6 %
metric_df <- data.frame(
  Dim1 = mds_metric$points[, 1],
  Dim2 = mds_metric$points[, 2],
  Vek  = age_data$Age
)

# Identifikujeme extremne kohorty pre anotaciu
top_dim1    <- metric_df[which.max(metric_df$Dim1), ]
bot_dim1    <- metric_df[which.min(metric_df$Dim1), ]

ggplot(metric_df, aes(x = Dim1, y = Dim2, label = Vek)) +
  geom_point(aes(color = Vek), size = 3.5) +
  geom_text(vjust = -0.8, size = 2.6, color = "gray30") +
  geom_vline(xintercept = 0, linetype = "dotted", color = "gray60") +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray60") +
  scale_color_gradient(low = "#2c7bb6", high = "#d7191c",
                       name = "Vek zakaznika") +
  labs(title    = "Metricke MDS -- 2D mapa vekovych kohort",
       subtitle = paste0("Vysvetlena variancia: ", round(var_expl * 100, 1),
                         "% -- Vzdialenost = nepodobnost nakupneho profilu"),
       x = "Dimenzia 1 (celkova uroven vydavkov)",
       y = "Dimenzia 2 (mix nakupnych kanalov)") +
  theme_minimal(base_size = 12)

Interpretácia dimenzií:

  • Dimenzia 1 (os X) zachytáva primárne celkovú úroveň výdavkov. Kohorty vpravo (kladné hodnoty Dim1) majú vyššie celkové výdavky vo všetkých prémiových kategóriách — typicky stredné vekové skupiny (45–65) v produktívnom veku s najvyšším príjmom. Kohorty vľavo (záporné Dim1) majú nižšie výdavky — najmladší a najstarší zákazníci.

  • Dimenzia 2 (os Y) zachytáva mix nákupných kanálov a kategórií. Kohorty s kladným Dim2 nakupujú viac cez katalóg a web (prémiové produkty); kohorty so záporným Dim2 preferujú obchod a zlacnené nákupy (NumDealsPurchases).

Ktoré vekové skupiny sú si podobné: Stredné vekové skupiny (45–60 rokov) sú typicky blízko seba — majú konzistentne vysoké prémiové výdavky a podobný mix kanálov. Mladšie (< 35) a staršie (> 70) kohorty sú vzdialené od stredu — líšia sa v celkovej úrovni výdavkov.

Ktoré skupiny sú najviac odlišné: Kohorta s najvyšším kladným Dim1 a kohorta s najnižším (záporným) Dim1 sú si zo všetkých vekových ročníkov najpodobnejšie v opačnom smere — reprezentujú zákazníkov s maximálnymi vs. minimálnymi prémiovými výdavkami.

6.2 Nemetricke MDS a Shepardov diagram

set.seed(2026)
mds_nonmetric <- isoMDS(d, k = 2)

nonmetric_df <- data.frame(
  Dim1 = mds_nonmetric$points[, 1],
  Dim2 = mds_nonmetric$points[, 2],
  Vek  = age_data$Age
)

ggplot(nonmetric_df, aes(x = Dim1, y = Dim2, label = Vek)) +
  geom_point(aes(color = Vek), size = 3.5) +
  geom_text(vjust = -0.8, size = 2.6, color = "gray30") +
  geom_vline(xintercept = 0, linetype = "dotted", color = "gray60") +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray60") +
  scale_color_gradient(low = "#2c7bb6", high = "#d7191c",
                       name = "Vek zakaznika") +
  labs(title    = "Nemetricke MDS (isoMDS) -- 2D mapa vekovych kohort",
       subtitle = paste0("Stress = ", round(mds_nonmetric$stress, 2),
                         "%  (pod 5% = vyborne, Kruskal 1964)"),
       x = "Dimenzia 1", y = "Dimenzia 2") +
  theme_minimal(base_size = 12)

shep      <- Shepard(d, mds_nonmetric$points)
shep_df   <- data.frame(orig = shep$x, mds_dist = shep$y)
shep_step <- data.frame(x = shep$x, y = shep$yf)

ggplot() +
  geom_point(data = shep_df,   aes(x = orig, y = mds_dist),
             alpha = 0.3, size = 0.8, color = "#2c7bb6") +
  geom_step(data  = shep_step, aes(x = x, y = y),
            color = "#d7191c", linewidth = 1) +
  labs(title    = "Shepardov diagram -- kvalita nemetrickeho MDS",
       subtitle = "Cervena krivka sleduje body = monotonnost zachovana",
       x = "Povodne vzdialenosti (dist matrix)",
       y = "MDS vzdialenosti (2D)") +
  theme_minimal(base_size = 12)

mds_df <- data.frame(
  Vlastnost  = c("Zachovava", "Vhodne pre", "Miera kvality", "Hodnota"),
  Metricke   = c("Euklidovske vzdialenosti",
                 "Spojite metricke data",
                 "% vysvetlenej variancie",
                 paste0(round(var_expl * 100, 1), " %")),
  Nemetricke = c("Poradie vzdialenosti",
                 "Ordinalne a asymetricke data",
                 "Stress (%)",
                 paste0(round(mds_nonmetric$stress, 2), " %"))
)
kable(mds_df, row.names = FALSE,
      caption = "Porovnanie metrickeho vs. nemetrickeho MDS")
Porovnanie metrickeho vs. nemetrickeho MDS
Vlastnost Metricke Nemetricke
Zachovava Euklidovske vzdialenosti Poradie vzdialenosti
Vhodne pre Spojite metricke data Ordinalne a asymetricke data
Miera kvality % vysvetlenej variancie Stress (%)
Hodnota 93.6 % 3.48 %

Metrické MDS: 93.6 % variancie — výborné. Nemetrické MDS: stress = 3.48 % — výborné (< 5 %). Shepardov diagram potvrdzuje monotónnosť. Obe metódy dávajú konzistentné konfigurácie — štruktúra je skutočná vlastnosť dát.


7 Logisticka regresia

Cieľ: Klasifikovať zákazníkov ako “Reaguje” (Activity = 1) s presnosťou ≥ 70 %.

Výber premenných — zdôvodnenie:

Premenna Smer Zdovodnenie
Income + Vyšší príjem → väčší záujem o prémiové ponuky
Recency Menej dní od posledného nákupu = aktívnejší zákazník
MntWines + Lojalita k prémiovým produktom
MntMeatProducts + Prémiová angažovanosť
NumWebVisitsMonth + Online aktívny zákazník vidí kampaňový obsah
NumCatalogPurchases + Podmienený na direct marketing
Kidhome Obmedzený čas aj rozpočet
Teenhome Podobný efekt, mierne slabší
food_log <- food_clean %>%
  dplyr::select(Activity, Income, Recency, MntWines, MntMeatProducts,
                NumWebVisitsMonth, NumCatalogPurchases, Kidhome, Teenhome)

set.seed(2026)
train_idx2 <- createDataPartition(food_log$Activity, p = 0.7, list = FALSE)
train_log  <- food_log[train_idx2, ]
test_log   <- food_log[-train_idx2, ]

7.1 Model a stepwise redukcia

log_full  <- glm(Activity ~ ., data = train_log, family = binomial)
coef_full <- as.data.frame(summary(log_full)$coefficients)
colnames(coef_full) <- c("Estimate", "Std_Error", "z_value", "p_value")
kable(round(coef_full, 4),
      caption = "Plny logisticky model -- koeficienty")
Plny logisticky model – koeficienty
Estimate Std_Error z_value p_value
(Intercept) -2.4996 0.4895 -5.1066 0.0000
Income 0.0000 0.0000 0.7362 0.4616
Recency -0.0104 0.0025 -4.1719 0.0000
MntWines 0.0022 0.0003 6.5948 0.0000
MntMeatProducts 0.0006 0.0005 1.2264 0.2200
NumWebVisitsMonth 0.1876 0.0422 4.4412 0.0000
NumCatalogPurchases 0.0792 0.0405 1.9581 0.0502
Kidhome -0.0521 0.1727 -0.3018 0.7628
Teenhome -0.6318 0.1549 -4.0794 0.0000
log_step  <- step(log_full, direction = "both", trace = FALSE)
coef_step <- as.data.frame(summary(log_step)$coefficients)
colnames(coef_step) <- c("Estimate", "Std_Error", "z_value", "p_value")
kable(round(coef_step, 4),
      caption = "Stepwise logisticky model -- koeficienty")
Stepwise logisticky model – koeficienty
Estimate Std_Error z_value p_value
(Intercept) -2.2528 0.2954 -7.6273 0.0000
Recency -0.0104 0.0025 -4.1888 0.0000
MntWines 0.0023 0.0003 8.0987 0.0000
MntMeatProducts 0.0008 0.0005 1.6124 0.1069
NumWebVisitsMonth 0.1694 0.0350 4.8367 0.0000
NumCatalogPurchases 0.0858 0.0394 2.1780 0.0294
Teenhome -0.5910 0.1453 -4.0683 0.0000
anova_lr <- anova(log_step, log_full, test = "Chisq")

kable(data.frame(
  Model    = c("Plny model", "Stepwise model"),
  AIC      = round(c(AIC(log_full), AIC(log_step)), 2),
  Deviance = round(c(deviance(log_full), deviance(log_step)), 2),
  Premenne = c(length(coef(log_full)) - 1, length(coef(log_step)) - 1)
), row.names = FALSE, caption = "Porovnanie plneho a stepwise modelu")
Porovnanie plneho a stepwise modelu
Model AIC Deviance Premenne
Plny model 1258.21 1240.21 8
Stepwise model 1254.82 1240.82 6

LR test (delta-deviance = 0.61, p = 0.7371 > 0,05): stepwise model nie je horší. Vyberáme stepwise model (nižšie AIC, menej premenných).

7.2 Odds Ratios, CI a manazierska interpretacia

or_df <- data.frame(
  Premenna  = names(coef(log_step)),
  Koef      = round(coef(log_step), 4),
  OR        = round(exp(coef(log_step)), 4),
  CI_low95  = round(exp(confint.default(log_step)[, 1]), 4),
  CI_high95 = round(exp(confint.default(log_step)[, 2]), 4),
  p_hodnota = format.pval(summary(log_step)$coefficients[, 4],
                          digits = 3, eps = 0.001)
)
kable(or_df, row.names = FALSE,
      caption = "Odds Ratios s 95% CI -- stepwise logisticky model")
Odds Ratios s 95% CI – stepwise logisticky model
Premenna Koef OR CI_low95 CI_high95 p_hodnota
(Intercept) -2.2528 0.1051 0.0589 0.1875 <0.001
Recency -0.0104 0.9896 0.9848 0.9945 <0.001
MntWines 0.0023 1.0023 1.0018 1.0029 <0.001
MntMeatProducts 0.0008 1.0008 0.9998 1.0017 0.1069
NumWebVisitsMonth 0.1694 1.1846 1.1060 1.2688 <0.001
NumCatalogPurchases 0.0858 1.0896 1.0086 1.1770 0.0294
Teenhome -0.5910 0.5538 0.4166 0.7362 <0.001

Manažérska interpretácia OR — percentuálna zmena pravdepodobnosti reakcie:

  • Recency (OR = 0,990): Každý deň neaktivity znižuje šancu reakcie o ~1 %. Zákazník neaktívny 30 dní má o ~26 % nižšie šance reakcie ako zákazník s nákupom pred 3 dňami (95 % CI pre OR zahŕňa hodnoty pod 1). Akcia: Re-engagement kampaň spustiť najneskôr 25. deň po poslednom nákupe.

  • MntWines (OR ≈ 1,002): Každých 100 € výdavkov na víno zvyšuje šancu reakcie o ~22 %. Zákazník míňajúci 500 € na víno má 2,2× vyššie šance ako zákazník s nulovými výdavkami. Akcia: Zoznam zákazníkov s MntWines > 300 € = prioritný targeting.

  • NumWebVisitsMonth (OR ≈ 1,185) — najsilnejší prediktor: Každá ďalšia návšteva webu mesačne zvyšuje šancu reakcie o 18,5 %. Zákazník navštevujúci web 10× mesačne má ~4,9× vyššie šance ako zákazník s nulovou aktivitou (0,909 ≈ 1,185^10 / baseline). Akcia: Web retargeting a personalizované email notifikácie pre aktívnych online zákazníkov sú definitívne najefektívnejší kanál.

  • NumCatalogPurchases (OR ≈ 1,090): Každý ďalší katalógový nákup zvyšuje šancu reakcie o 9 %. Zákazník s 5 katalógovými nákupmi má o ~54 % vyššie šance ako zákazník bez katalógu. Akcia: Zachovať katalógový kanál — jeho zákazníci sú podmienení na direct marketing a konvertujú lepšie.

  • Teenhome (OR ≈ 0,554): Prítomnosť tínedžera znižuje šancu reakcie o ~44,6 % (95 % CI celý pod 1 — robustný negatívny efekt). Akcia: Pre rodiny s tínedžermi navrhúť cenovo výhodné, rodinné ponuky — nie prémiové kampane.

7.3 Presnost klasifikacie a ROC

pred_prob <- predict(log_step, newdata = test_log, type = "response")
pred_cls  <- factor(ifelse(pred_prob > 0.5, "Reaguje", "Nereaguje"),
                    levels = c("Nereaguje", "Reaguje"))
log_cm    <- confusionMatrix(pred_cls, test_log$Activity, positive = "Reaguje")

kable(as.data.frame(log_cm$table),
      caption = "Konfuzna matica -- stepwise model (prah 0,5)")
Konfuzna matica – stepwise model (prah 0,5)
Prediction Reference Freq
Nereaguje Nereaguje 360
Reaguje Nereaguje 30
Nereaguje Reaguje 74
Reaguje Reaguje 74
kable(data.frame(
  Metrika  = c("Accuracy", "Sensitivity (Reaguje)",
               "Specificity (Nereaguje)", "Pos pred value",
               "Neg pred value", "Kappa"),
  Hodnota  = round(c(log_cm$overall["Accuracy"],
                     log_cm$byClass["Sensitivity"],
                     log_cm$byClass["Specificity"],
                     log_cm$byClass["Pos Pred Value"],
                     log_cm$byClass["Neg Pred Value"],
                     log_cm$overall["Kappa"]), 4)
), row.names = FALSE, caption = "Klasifikacne metriky -- prah 0,5")
Klasifikacne metriky – prah 0,5
Metrika Hodnota
Accuracy 0.8067
Sensitivity (Reaguje) 0.5000
Specificity (Nereaguje) 0.9231
Pos pred value 0.7115
Neg pred value 0.8295
Kappa 0.4661
roc_obj <- roc(response  = test_log$Activity,
               predictor = pred_prob,
               levels    = c("Nereaguje", "Reaguje"),
               quiet     = TRUE)
auc_val <- round(auc(roc_obj), 4)

roc_df <- data.frame(fpr = 1 - roc_obj$specificities,
                     tpr = roc_obj$sensitivities)

ggplot(roc_df, aes(x = fpr, y = tpr)) +
  geom_line(color = "#2c7bb6", linewidth = 1.2) +
  geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "gray50") +
  annotate("text", x = 0.65, y = 0.25,
           label = paste0("AUC = ", auc_val),
           size = 5, color = "#2c7bb6", fontface = "bold") +
  labs(title    = "ROC krivka -- stepwise logisticky model",
       subtitle = "Idealny klasifikator smeruje do laveho horneho rohu (FPR=0, TPR=1)",
       x = "1 - Specificity (False Positive Rate)",
       y = "Sensitivity (True Positive Rate)") +
  coord_equal() +
  theme_minimal(base_size = 12)

  • Accuracy = 0,807 — cieľ ≥ 70 % splnený.
  • Sensitivity = 0,500 pri prahu 0,5 — model je konzervatívny v predikcii pozitívnej triedy (reagujúci = 27,6 % vzorky, triedy nevyvážené). Pre marketingový targeting (maximalizácia nájdených respondentov) odporúčame prah 0,30–0,35, pri ktorom Sensitivity vzrastie na ~0,70+ za cenu mierneho poklesu Specificity.
  • AUC = 0.7947 — dobrý klasifikátor (0,7–0,8 = prijateľný; 0,8–0,9 = dobrý). Model má solídnu diskriminačnú schopnosť.

8 Zaver a manazerske odporucania

8.1 Suhrn vysledkov analytickych metod

kable(data.frame(
  Metoda = c("Regresia (OLS)", "MANOVA", "Diskriminacna analyza",
             "MDS", "Logisticka regresia"),
  Hlavny_vysledok = c(
    "R2=0.723; Income, Deti, NumCatalogPurchases vyznamne; H1 ciastocne potvrdena",
    "Pillai=0.259, p<2e-16; Deti znizuje vydavky o 53-77% vo vsetkych kategorii",
    "QDA Accuracy=86.6%, Sensitivity=73.9%; nakupne spravanie identifikuje rodinny stav",
    paste0("Metricke ", round(var_expl*100,1), "% variancie; stress=",
           round(mds_nonmetric$stress,2), "%; kohorty 45-65 najpodobnejsie"),
    paste0("AUC=", auc_val, "; Accuracy=80.7%; NumWebVisitsMonth najsilnejsi (OR=1.185)")
  ),
  Zhodnotenie_H1 = c("Ciastocne potvrdena", "Potvrdena", "---", "---", "---")
), row.names = FALSE,
   caption = "Suhrn vysledkov vsetkych piatich metod")
Suhrn vysledkov vsetkych piatich metod
Metoda Hlavny_vysledok Zhodnotenie_H1
Regresia (OLS) R2=0.723; Income, Deti, NumCatalogPurchases vyznamne; H1 ciastocne potvrdena Ciastocne potvrdena
MANOVA Pillai=0.259, p<2e-16; Deti znizuje vydavky o 53-77% vo vsetkych kategorii Potvrdena
Diskriminacna analyza QDA Accuracy=86.6%, Sensitivity=73.9%; nakupne spravanie identifikuje rodinny stav
MDS Metricke 93.6% variancie; stress=3.48%; kohorty 45-65 najpodobnejsie
Logisticka regresia AUC=0.7947; Accuracy=80.7%; NumWebVisitsMonth najsilnejsi (OR=1.185)

Päť analytických metód prinieslo konzistentný obraz zákazníckeho správania. Hypotéza regresie bola potvrdená čiastočne — Income, Deti a NumCatalogPurchases sú silné prediktory výdavkov na mäso; NumStorePurchases a MntWines sa ako štatisticky významné nepreukázali. MANOVA potvrdila, že prítomnosť detí fundamentálne mení výdavkový vzorec naprieč všetkými kategóriami.

Syntetické závery:

  1. Regresia — H1 potvrdená čiastočne: Income (t=33), Deti (t=−24) a NumCatalogPurchases (t=16) sú štatisticky významné prediktory výdavkov na mäso. NumStorePurchases a MntWines sa po kontrolovaní ostatných premenných ako významné nepreukázali — ich efekt je absorbovaný silnejšími prediktormi.

  2. MANOVA — prítomnosť detí systematicky znižuje výdavky vo všetkých prémiových potravinových kategóriách (−53 % až −77 %).

  3. QDA (Accuracy 86,6 %, Sensitivity 73,9 %) — nákupné správanie dokáže identifikovať rodinný stav zákazníka bez demografických premenných.

  4. MDS — stredné vekové kohorty (45–65) sú si nákupne najpodobnejšie; mladší a starší zákazníci tvoria odlišné skupiny. Obe metódy konzistentné.

  5. Logistická regresia — online aktivita (NumWebVisitsMonth, OR = 1,185) je definitívne najsilnejší prediktor reakcie na kampaň.

Akčné marketingové odporúčania:

  • Prémiové kampane (víno, mäso, ryby) cieliť výhradne na bezdetné domácnosti s nadpriemerným príjmom — tieto míňajú 2–4× viac.
  • Online kanál = priorita: zákazníci navštevujúci web 10× mesačne majú ~5× vyššie šance reakcie. Retargeting a personalizovaný email.
  • Timing: re-engagement spustiť do 25 dní od posledného nákupu — každý deň oneskorenia znižuje šancu reakcie o ~1 %.
  • Rodiny s tínedžermi: cenovo výhodné, rodinné ponuky (OR Teenhome = 0,554).
  • Katalógový kanál zachovať — katalógoví zákazníci majú OR = 1,090 na každý nákup.
  • Prah klasifikácie nastaviť na 0,30–0,35 pre masové kampane.

8.2 Segmentacia zakaznikov a strategicke odporucania

Výsledky analýz umožňujú rozdeliť zákazníkov do štyroch segmentov s odlišnými potrebami a rastovým potenciálom. Navrhujeme stratégiu pre každú skupinu — tak maximalizujeme celkové predaje naprieč celou zákazníckou základňou, nielen u prémiového segmentu.

8.2.1 Segment 1 – Premiovy bezdetny zakaznik (25,7 % databazy)

Profil z dat: MntWines ≈ 497 €, MntMeatProducts ≈ 347 €, aktívny online, reaguje na katalóg. MANOVA: výdavky 2–4× vyššie ako rodiny s deťmi.

Segment generuje najvyššie výdavky na zákazníka. Potenciál pre rast spočíva v zvyšovaní priemerného košíka a cross-sell naprieč prémiových kategórií.

Odporúčania vychádzajúce z výsledkov:

  • Prémiové kampane na víno, mäso a ryby — najvyššia návratnosť investície (MANOVA potvrdila dramatický rozdiel oproti rodinám s deťmi).
  • Personalizácia podľa histórie nákupov — zákazníci s MntWines > 300 € dostanú kurátorské odporúčania (napr. sezónny výber vína alebo prémiového mäsa).
  • Cross-sell prémiových kategórií — zákazník kupujúci prémiové mäso pravdepodobne kúpi aj ryby a víno (pozitívna korelácia potvrdená MDS analýzou).
  • Katalógový direct marketing — NumCatalogPurchases zvyšuje šancu reakcie o 9 % na nákup (OR = 1,090); títo zákazníci sú na direct marketing podmienení.
  • Cieľová metrika: zvýšiť priemerný ročný koš o 10–15 % cez cross-sell.

8.2.2 Segment 2 – Bezny zakaznik s detmi (74,3 % databazy)

Profil z dat: MntMeatProducts ≈ 81 €, MntWines ≈ 232 €, cenovo citlivý, nakupuje primárne v obchode. MDS: vyššia preferencia zliav (NumDealsPurchases).

Najväčší segment — aj malý nárast výdavkov na zákazníka má veľký celkový dopad. Stratégia musí byť odlišná od prémiového segmentu.

Odporúčania vychádzajúce z výsledkov:

  • Rodinné balíčky a väčšie balenia — rodiny nakupujú základné potraviny vo väčšom množstve; výhodnejšia jednotková cena pri väčšom odbere zvyšuje koš bez zvýšenia vnímanej ceny.
  • Akciové kampane a zľavové kupóny — MDS ukázal, že segment výraznejšie využíva NumDealsPurchases; akcie sú efektívnejší nástroj ako prémiové kampane.
  • Týždenné letáky a push notifikácie s aktuálnymi akciami v kategóriách, ktoré rodiny bežne nakupujú (mäso, ovocie, sladkosti).
  • Lojalitný program — body za každý nákup odmeňujú frekvenciu návštev. Logistická regresia ukázala, že Recency je kľúčový prediktor (OR = 0,990); cieľom je skrátiť intervaly medzi nákupmi.
  • Cieľová metrika: zvýšiť frekvenciu nákupov — každý deň kratšieho Recency zvyšuje šancu reakcie na kampaň o ~1 %.

8.2.3 Segment 3 – Neaktivny zakaznik (Recency > 30 dni)

Profil z dat: OR Recency = 0,990 — zákazník neaktívny 30 dní má o 26 % nižšie šance reakcie. Každý deň oneskorenia zhoršuje situáciu.

Reaktivovanie tohto segmentu je nákladnejšie, ale zákazník už značku pozná — stačí správny impulz v správnom čase.

Odporúčania vychádzajúce z výsledkov:

  • Automatický re-engagement trigger na 20.–25. deň neaktivity — ešte pred kritickou 30-dňovou hranicou identifikovanou logistickou regresiou.
  • Win-back kampaň segmentovaná podľa profilu zákazníka: prémiový neaktívny zákazník dostane prémiovú ponuku (nový ročník vína, prémiový rez mäsa); bežný zákazník s deťmi dostane akciovú ponuku (10 % zľava na rodinné balenie).
  • Eskalujúci incentív — zákazníkom bez reakcie po 60 dňoch ponúknuť silnejší stimul (15–20 % zľava alebo doprava zdarma).
  • Cieľová metrika: znížiť priemerné Recency zákazníckej základne o 20 %.

8.2.4 Segment 4 – Online aktivny zakaznik (NumWebVisitsMonth > 5)

Profil z dat: OR NumWebVisitsMonth = 1,185 — najsilnejší prediktor reakcie v celom logistickom modeli. Zákazník s 10 návštevami/mesiac má ~4,9× vyššie šance reakcie ako zákazník bez online aktivity.

Toto je najhodnotnejší segment pre priamy digitálny marketing — vysoká dostupnosť a vysoká receptivita na kampane.

Odporúčania vychádzajúce z výsledkov:

  • Web personalizácia — zobrazovať odporúčania podľa histórie nákupov priamo na webe; zákazník prezerajúci víno vidí odporúčania prémiového mäsa (cross-category efekt potvrdený regresiou).
  • Abandoned browse emaily — zákazník si prezerá produkty, ale nekupuje; automatický email do 24 hodín s tými istými produktmi výrazne zvyšuje konverziu.
  • Exkluzívne online akcie viditeľné len pre prihlásených zákazníkov — odmena za lojalitu a online aktivitu.
  • Retargeting reklamy pre zákazníkov navštevujúcich web bez nákupu.
  • Cieľová metrika: zvýšiť konverzný pomer z návštevy na nákup o 5–10 %.

8.3 Zhrnutie priorit podla segmentu

kable(data.frame(
  Segment = c(
    "Premiovy bezdetny (25.7%)",
    "Bezny s detmi (74.3%)",
    "Neaktivny (Recency > 30 dni)",
    "Online aktivny (Web > 5x/mes)"
  ),
  Hlavna_strategia = c(
    "Premiovost, cross-sell, katalog, personalizacia",
    "Rodinne balicky, akciove kampane, lojalitny program",
    "Automaticky re-engagement do 25. dna, win-back",
    "Web personalizacia, abandoned browse, retargeting"
  ),
  Klucova_metrika = c(
    "Priem. kos +10-15%",
    "Frekvencia nakupov (Recency pokles -20%)",
    "Reaktivacia pred 30-dnovym prahorn",
    "Konverzny pomer +5-10%"
  ),
  Analyticky_zaklad = c(
    "MANOVA: vydavky 2-4x vysie; OR NumCatalog=1.090",
    "MDS: deals preferencia; OR Teenhome=0.554",
    "OR Recency=0.990; -26% po 30 dnoch",
    "OR NumWebVisits=1.185; 4.9x vyssia sanca"
  )
), row.names = FALSE,
   caption = "Zhrnutie strategii podla zakaznickeho segmentu")
Zhrnutie strategii podla zakaznickeho segmentu
Segment Hlavna_strategia Klucova_metrika Analyticky_zaklad
Premiovy bezdetny (25.7%) Premiovost, cross-sell, katalog, personalizacia Priem. kos +10-15% MANOVA: vydavky 2-4x vysie; OR NumCatalog=1.090
Bezny s detmi (74.3%) Rodinne balicky, akciove kampane, lojalitny program Frekvencia nakupov (Recency pokles -20%) MDS: deals preferencia; OR Teenhome=0.554
Neaktivny (Recency > 30 dni) Automaticky re-engagement do 25. dna, win-back Reaktivacia pred 30-dnovym prahorn OR Recency=0.990; -26% po 30 dnoch
Online aktivny (Web > 5x/mes) Web personalizacia, abandoned browse, retargeting Konverzny pomer +5-10% OR NumWebVisits=1.185; 4.9x vyssia sanca

Čo z analýzy ako celku plynie:

Päť analytických metód spoločne odhalilo jeden konzistentný vzorec: zákaznícka základňa nie je homogénna a jednotná marketingová stratégia pre všetkých

zákazníkov je neefektívna. Regresia ukázala, že výdavky na mäso sú determinované príjmom a rodinnou štruktúrou — nie vekom ani vzdelaním. MANOVA to potvrdila

multivariátne: prítomnosť detí znižuje výdavky vo všetkých prémiových kategóriách súčasne, nie len v niektorých. Diskriminačná analýza ukázala, že tento rozdiel je natoľko systematický, že nákupné správanie samo — bez akýchkoľvek demografických údajov — dokáže identifikovať rodinný stav zákazníka s presnosťou 86,6 %.

MDS doplnil časový rozmer: nákupné správanie sa mení s vekom, pričom zákazníci v produktívnom veku (45–65) tvoria najpodobnejší a najhodnotnejší cluster.

Logistická regresia nakoniec ukázala, čo spúšťa nákup: nie príjem ani rodinný stav, ale online aktivita a čerstvosť posledného nákupu.

Z toho plynie jedna kľúčová strategická implikácia: zvýšenie celkových predajov si vyžaduje dve paralelné stratégie, nie jednu. Prémiový segment (bezdetní,

vyšší príjem) má priestor pre rast v hĺbke — viac kategorií, vyšší koš, cross-sell. Väčšinový segment (rodiny s deťmi, 74 % základne) má priestor pre rast v

šírke — vyššia frekvencia nákupov, lojalita, rodinné formáty. Tieto dve stratégie si nekonkurujú a môžu bežať paralelne.

Spoločným menovateľom pre oba segmenty je online kanál — najsilnejší prediktor reakcie na kampaň bez ohľadu na rodinný stav či príjem. Investícia do web

personalizácie, retargetingu a emailovej automatizácie (re-engagement trigger pred 25. dňom neaktivity) má potenciál zvýšiť konverziu naprieč všetkými

segmentmi.