Analiza koszyka zakupowego (market basket analysis) jest jedną z najczęściej stosowanych technik eksploracji danych w handlu detalicznym. Jej celem jest odkrycie ukrytych wzorców współwystępowania produktów w transakcjach zakupowych. Wyniki takiej analizy pozwalają lepiej rozumieć zachowania klientów i podejmować bardziej trafne decyzje biznesowe, takie jak optymalizacja układu sklepowego, tworzenie promocji krzyżowych czy rekomendacje produktowe.
Głównym narzędziem stosowanym w analizie koszyka zakupowego są reguły asocjacyjne (association rules). Reguła asocjacyjna ma postać:
\[\{A\} \Rightarrow \{B\}\]
co oznacza: „jeśli klient kupuje produkt A, to z dużym prawdopodobieństwem kupi również produkt B”.
Do oceny jakości reguł asocjacyjnych stosuje się trzy podstawowe miary:
Support (wsparcie) – określa, jak często dany zbiór produktów pojawia się we wszystkich transakcjach. Wartość 0.05 oznacza, że produkty te współwystąpiły w 5% wszystkich paragonów: \[\text{support}(A \Rightarrow B) = \frac{|\text{transakcje zawierające A i B}|}{|\text{wszystkie transakcje}|}\]
Confidence (pewność) – określa, jak często reguła jest prawdziwa, czyli jaki odsetek transakcji zawierających A zawiera również B. Wartość 0.8 oznacza, że w 80% przypadków, gdy klient kupił A, kupił też B: \[\text{confidence}(A \Rightarrow B) = \frac{|\text{transakcje zawierające A i B}|}{|\text{transakcje zawierające A}|}\]
Lift (dźwignia) – mierzy siłę zależności między A i B w odniesieniu do losowego współwystępowania. Lift = 1 oznacza brak zależności (produkty kupowane niezależnie), lift > 1 oznacza pozytywną zależność (produkty kupowane razem częściej niż losowo), lift < 1 oznacza zależność negatywną: \[\text{lift}(A \Rightarrow B) = \frac{\text{confidence}(A \Rightarrow B)}{\text{support}(B)}\]
Najszerzej stosowanym algorytmem do wyznaczania reguł asocjacyjnych jest algorytm Apriori (Agrawal & Srikant, 1994). Opiera się on na właściwości antymonotoniczności: jeśli dany zbiór elementów jest rzadki (nie spełnia minimalnego progu wsparcia), to żaden jego nadzbiór również nie będzie spełniał tego progu. Dzięki temu algorytm efektywnie ogranicza przestrzeń poszukiwań i nie sprawdza wszystkich możliwych kombinacji produktów.
Działanie algorytmu przebiega dwuetapowo:
minsupp).minconf).W analizie wykorzystano zbiór danych Groceries
dostępny w pakiecie arules. Jest to klasyczny, rzeczywisty
zbiór danych często wykorzystywany w dydaktyce i badaniach dotyczących
reguł asocjacyjnych. Zawiera dane transakcyjne z jednego miesiąca
działalności małego sklepu spożywczego.
# Wczytanie niezbędnych pakietów.
# Pakiet 'arules' dostarcza algorytm Apriori i format danych transakcyjnych.
# Pakiet 'arulesViz' umożliwia wizualizację odkrytych reguł.
library(arules)
library(arulesViz)
# Wczytanie zbioru danych Groceries.
data("Groceries")# Funkcja summary() dla obiektu klasy 'transactions' zwraca:
# - liczbę transakcji i produktów
# - rozkład długości transakcji (ile produktów na paragon)
# - listę najczęściej kupowanych produktów wraz z ich częstością
summary(Groceries)## transactions as itemMatrix in sparse format with
## 9835 rows (elements/itemsets/transactions) and
## 169 columns (items) and a density of 0.02609146
##
## most frequent items:
## whole milk other vegetables rolls/buns soda
## 2513 1903 1809 1715
## yogurt (Other)
## 1372 34055
##
## element (itemset/transaction) length distribution:
## sizes
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
## 2159 1643 1299 1005 855 645 545 438 350 246 182 117 78 77 55 46
## 17 18 19 20 21 22 23 24 26 27 28 29 32
## 29 14 14 9 11 4 6 1 1 1 1 3 1
##
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 2.000 3.000 4.409 6.000 32.000
##
## includes extended item information - examples:
## labels level2 level1
## 1 frankfurter sausage meat and sausage
## 2 sausage sausage meat and sausage
## 3 liver loaf sausage meat and sausage
Zbiór danych Groceries zawiera 9845 transakcji oraz 169
unikalnych produktów. Każda transakcja odpowiada jednemu paragonowi
zakupowemu i zawiera listę kupionych artykułów. Dane obejmują zakupy
dokonane w ciągu jednego miesiąca. Najczęściej kupowanymi produktami są
whole mil other vegatebles oraz rolls/buns
# Wypisanie podstawowych wymiarów zbioru danych.
# nrow() zwraca liczbę wierszy, czyli transakcji.
# ncol() zwraca liczbę kolumn, czyli unikalnych produktów (pozycji asortymentowych).
cat("Liczba transakcji:", nrow(Groceries), "\n")## Liczba transakcji: 9835
## Liczba unikalnych produktów: 169
# Wykres słupkowy przedstawiający 20 produktów o największej łącznej liczbie
# wystąpień we wszystkich transakcjach.
# type = "absolute" oznacza, że oś Y pokazuje bezwzględną liczbę transakcji
# (a nie procent) – łatwiej to zinterpretować na początku analizy.
itemFrequencyPlot(
Groceries,
topN = 20,
type = "absolute",
col = "steelblue",
main = "20 najczęściej kupowanych produktów",
ylab = "Liczba transakcji",
xlab = ""
)Powyższy wykres przedstawia 20 produktów najczęściej pojawiających się w transakcjach. Zdecydowanie najczęściej kupowanym artykułem jest pełne mleko, które pojawia się w 2500 transakcjach. Kolejne miejsca zajmują inne warzywa (other vegetables) oraz bułki i pieczywo(rolls/buns). Wyraźna różnica między pierwszym a pozostałymi produktami sugeruje wyjątkową rolę mleka w codziennych zakupach klientów tego sklepu.
# Ten wykres pokazuje tę samą informację co poprzedni, ale w wartościach względnych.
# type = "relative" – oś Y pokazuje odsetek wszystkich transakcji, w których
# dany produkt się pojawił (wartość od 0 do 1, gdzie 1 = 100%).
# Pozwala to ocenić, jak "popularny" jest produkt w stosunku do całej bazy.
itemFrequencyPlot(
Groceries,
topN = 20,
type = "relative",
col = "coral",
main = "Względna częstotliwość 20 najczęstszych produktów",
ylab = "Odsetek transakcji",
xlab = ""
)Patrząc na częstotliwości względne, pełne mleko pojawia się w blisko ok. 25–26% wszystkich transakcji, co czyni je zdecydowanie najpopularniejszym produktem w zbiorze. Inne warzywa pojawiają się w około ok. 19% transakcji. Warto zauważyć, że nawet najczęstszy produkt obecny jest tylko w co czwartym paragonie – jest to typowe dla danych zakupowych, gdzie klienci kupują zróżnicowany asortyment.
Zbiór Groceries jest już w formacie transakcyjnym
(transactions), który jest natywnie obsługiwany przez pakiet
arules. Nie wymaga zatem konwersji ani szerokiego
przetwarzania wstępnego. Warto jednak zbadać rozkład długości
transakcji, który może wpłynąć na dobór parametrów algorytmu.
# Funkcja size() zwraca wektor liczb – ile produktów zawierała każda transakcja.
# Na jego podstawie obliczamy podstawowe statystyki opisowe.
transakcje_dl <- size(Groceries)
cat("Minimalna liczba produktów w transakcji:", min(transakcje_dl), "\n")## Minimalna liczba produktów w transakcji: 1
## Maksymalna liczba produktów w transakcji: 32
## Średnia liczba produktów w transakcji: 4.41
## Mediana liczby produktów w transakcji: 3
.
Przeciętna transakcja zawiera średnio 4,41 produktów mediana wynosi zaś 3 produkty, choć zdarzają się paragony zawierające nawet 32 pozycji. Niska mediana wskazuje, że większość klientów robi stosunkowo małe zakupy.
# Histogram wizualizuje rozkład długości transakcji.
# breaks = 30 – liczba przedziałów histogramu (więcej = dokładniejszy wykres).
# Czerwona przerywana linia (abline) oznacza wartość średniej –
# pomaga zobaczyć, czy rozkład jest symetryczny czy skośny.
hist(
transakcje_dl,
breaks = 30,
col = "lightblue",
border = "white",
main = "Rozkład liczby produktów w transakcjach",
xlab = "Liczba produktów",
ylab = "Liczba transakcji"
)
abline(v = mean(transakcje_dl), col = "red", lwd = 2, lty = 2)
legend("topright", legend = paste("Średnia:", round(mean(transakcje_dl), 2)),
col = "red", lty = 2, lwd = 2)Rozkład długości transakcji jest prawostronnie skośny – słupki są skupione po lewej stronie (małe transakcje), a prawy ogon wykresu jest długi (nieliczne duże zakupy). Oznacza to, że większość klientów kupuje od 1 do 5 produktów, ale zdarzają się paragony z kilkunastoma lub kilkudziesięcioma pozycjami. Taki rozkład jest typowy dla danych zakupowych z supermarketów.
Przed uruchomieniem algorytmu należy ustalić dwa kluczowe progi:
supp (minimalne wsparcie) – określa,
jak często para/grupa produktów musi się pojawiać w transakcjach, aby
była w ogóle brana pod uwagę. Zbyt wysoki próg pomija rzadkie, ale
interesujące zależności; zbyt niski tworzy miliony reguł. Przy
9835 transakcjach, supp = 0.01 oznacza, że
produkty muszą się pojawić razem co najmniej w ~98 transakcjach.conf (minimalna pewność) – określa
minimalną „trafność” reguły. conf = 0.25 oznacza, że reguła
musi być prawdziwa w co najmniej 25% przypadków.minlen = 2 – wyklucza reguły
jednoelementowe (sam produkt bez kontekstu), które nie mają sensu w
analizie asocjacyjnej.# Uruchomienie algorytmu Apriori.
# Wynik zapisujemy do obiektu 'reguly' klasy 'rules'.
# Algorytm wypisze w konsoli informacje o postępie obliczeń –
# pojawi się np. "writing ... rules" i liczba znalezionych reguł.
reguly <- apriori(
Groceries,
parameter = list(
supp = 0.01,
conf = 0.25,
minlen = 2
)
)## Apriori
##
## Parameter specification:
## confidence minval smax arem aval originalSupport maxtime support minlen
## 0.25 0.1 1 none FALSE TRUE 5 0.01 2
## maxlen target ext
## 10 rules TRUE
##
## Algorithmic control:
## filter tree heap memopt load sort verbose
## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
##
## Absolute minimum support count: 98
##
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[169 item(s), 9835 transaction(s)] done [0.00s].
## sorting and recoding items ... [88 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 4 done [0.00s].
## writing ... [170 rule(s)] done [0.00s].
## creating S4 object ... done [0.00s].
# Podsumowanie wyników – pokazuje m.in.:
# - całkowitą liczbę reguł
# - rozkład długości reguł (ile reguł 2-elementowych, 3-elementowych itd.)
# - statystyki miar jakości (min, średnia, max dla support, confidence, lift)
summary(reguly)## set of 170 rules
##
## rule length distribution (lhs + rhs):sizes
## 2 3
## 96 74
##
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.000 2.000 2.000 2.435 3.000 3.000
##
## summary of quality measures:
## support confidence coverage lift
## Min. :0.01007 Min. :0.2517 Min. :0.01729 Min. :0.9932
## 1st Qu.:0.01159 1st Qu.:0.2973 1st Qu.:0.03101 1st Qu.:1.5215
## Median :0.01454 Median :0.3587 Median :0.04291 Median :1.7784
## Mean :0.01822 Mean :0.3703 Mean :0.05187 Mean :1.8747
## 3rd Qu.:0.02097 3rd Qu.:0.4253 3rd Qu.:0.05857 3rd Qu.:2.1453
## Max. :0.07483 Max. :0.5862 Max. :0.25552 Max. :3.2950
## count
## Min. : 99.0
## 1st Qu.:114.0
## Median :143.0
## Mean :179.2
## 3rd Qu.:206.2
## Max. :736.0
##
## mining info:
## data ntransactions support confidence
## Groceries 9835 0.01 0.25
## call
## apriori(data = Groceries, parameter = list(supp = 0.01, conf = 0.25, minlen = 2))
# Funkcja length() zwraca liczbę reguł w obiekcie 'reguly'.
cat("Liczba odkrytych reguł:", length(reguly), "\n")## Liczba odkrytych reguł: 170
Algorytm Apriori przy zadanych parametrach odkrył łącznie 170 reguł asocjacyjnych. Większość z nich to reguły około 2 elementowe. Maksymalna wartość lift wynosi 3,29, co świadczy o tym, że niektóre produkty są ze sobą silnie powiązane.
# Funkcja sort() sortuje reguły według wybranej miary (tu: lift, malejąco).
# Funkcja inspect() wyświetla reguły w czytelnej formie tabelarycznej:
# kolumny to: lhs (lewa strona), rhs (prawa strona), support, confidence, coverage, lift, count.
# [1:15] – pokazujemy tylko 15 pierwszych (najlepszych) reguł.
inspect(sort(reguly, by = "lift")[1:15])## lhs rhs support
## [1] {citrus fruit, other vegetables} => {root vegetables} 0.01037112
## [2] {tropical fruit, other vegetables} => {root vegetables} 0.01230300
## [3] {beef} => {root vegetables} 0.01738688
## [4] {citrus fruit, root vegetables} => {other vegetables} 0.01037112
## [5] {tropical fruit, root vegetables} => {other vegetables} 0.01230300
## [6] {other vegetables, whole milk} => {root vegetables} 0.02318251
## [7] {whole milk, curd} => {yogurt} 0.01006609
## [8] {other vegetables, yogurt} => {root vegetables} 0.01291307
## [9] {other vegetables, yogurt} => {tropical fruit} 0.01230300
## [10] {other vegetables, rolls/buns} => {root vegetables} 0.01220132
## [11] {tropical fruit, whole milk} => {root vegetables} 0.01199797
## [12] {root vegetables, rolls/buns} => {other vegetables} 0.01220132
## [13] {root vegetables, yogurt} => {other vegetables} 0.01291307
## [14] {whole milk, yogurt} => {tropical fruit} 0.01514997
## [15] {pip fruit} => {tropical fruit} 0.02043721
## confidence coverage lift count
## [1] 0.3591549 0.02887646 3.295045 102
## [2] 0.3427762 0.03589222 3.144780 121
## [3] 0.3313953 0.05246568 3.040367 171
## [4] 0.5862069 0.01769192 3.029608 102
## [5] 0.5845411 0.02104728 3.020999 121
## [6] 0.3097826 0.07483477 2.842082 228
## [7] 0.3852140 0.02613116 2.761356 99
## [8] 0.2974239 0.04341637 2.728698 127
## [9] 0.2833724 0.04341637 2.700550 121
## [10] 0.2863962 0.04260295 2.627525 120
## [11] 0.2836538 0.04229792 2.602365 118
## [12] 0.5020921 0.02430097 2.594890 120
## [13] 0.5000000 0.02582613 2.584078 127
## [14] 0.2704174 0.05602440 2.577089 149
## [15] 0.2701613 0.07564820 2.574648 201
eguły przedstawione w tabeli zostały posortowane według wartości miary lift, która informuje o sile zależności pomiędzy produktami. Im wyższa wartość lift, tym silniejsza jest współzależność między elementami reguły – oznacza to, że produkty występują razem w transakcjach częściej, niż wynikałoby to z ich niezależnych częstości występowania.
Najwyższą wartość lift (3,29) osiąga reguła:
{citrus fruit, other vegetables} ⇒ {root vegetables}.
Oznacza to, że jeśli w koszyku zakupowym znajdują się cytrusy oraz inne warzywa, to prawdopodobieństwo zakupu warzyw korzeniowych jest ponad trzykrotnie wyższe, niż gdyby produkty te były kupowane całkowicie niezależnie. Reguła ta charakteryzuje się confidence na poziomie 0,36, co oznacza, że w około 36% transakcji zawierających cytrusy i inne warzywa pojawiają się również warzywa korzeniowe.
Podobnie wysokie wartości lift obserwujemy dla reguł:
{tropical fruit, other vegetables} ⇒ {root vegetables} (lift ≈ 3,14),
{beef} ⇒ {root vegetables} (lift ≈ 3,04).
Wskazuje to na silną współzależność pomiędzy zakupem warzyw korzeniowych a innymi produktami spożywczymi, szczególnie warzywami oraz niektórymi produktami białkowymi. Może to sugerować, że produkty te są często wykorzystywane razem w przygotowywaniu posiłków.
Interesujące zależności widoczne są również w odwrotnym kierunku. Na przykład reguła:
{citrus fruit, root vegetables} ⇒ {other vegetables}
osiąga confidence równy 0,59, co oznacza, że w niemal 60% przypadków, gdy klienci kupują cytrusy i warzywa korzeniowe, w koszyku pojawiają się również inne warzywa. Sugeruje to, że zakupy tych produktów mają często charakter komplementarny.
Warto również zwrócić uwagę na reguły związane z produktami mlecznymi, np.:
{whole milk, curd} ⇒ {yogurt} (lift ≈ 2,76),
co wskazuje, że klienci kupujący mleko i twaróg relatywnie często nabywają także jogurt. Może to odzwierciedlać wspólne preferencje konsumentów dotyczące produktów mlecznych.
Ogólnie uzyskane reguły sugerują, że wiele zidentyfikowanych zależności dotyczy produktów komplementarnych, które są wykorzystywane razem w przygotowywaniu posiłków. Tego typu informacje mogą być wykorzystywane w praktyce handlowej, np. przy projektowaniu promocji łączonych, rekomendacji produktów lub optymalizacji rozmieszczenia towarów w sklepie.
# To samo, ale sortowanie według pewności (confidence).
# Reguły o wysokiej confidence to takie, gdzie "jeśli A to prawie na pewno B".
# Uwaga: wysoka confidence niekoniecznie oznacza interesującą regułę –
# jeśli produkt B jest bardzo popularny (np. whole milk),
# to wiele reguł będzie miało go po prawej stronie z wysoką pewnością.
inspect(sort(reguly, by = "confidence")[1:10])## lhs rhs support
## [1] {citrus fruit, root vegetables} => {other vegetables} 0.01037112
## [2] {tropical fruit, root vegetables} => {other vegetables} 0.01230300
## [3] {curd, yogurt} => {whole milk} 0.01006609
## [4] {other vegetables, butter} => {whole milk} 0.01148958
## [5] {tropical fruit, root vegetables} => {whole milk} 0.01199797
## [6] {root vegetables, yogurt} => {whole milk} 0.01453991
## [7] {other vegetables, domestic eggs} => {whole milk} 0.01230300
## [8] {yogurt, whipped/sour cream} => {whole milk} 0.01087951
## [9] {root vegetables, rolls/buns} => {whole milk} 0.01270971
## [10] {pip fruit, other vegetables} => {whole milk} 0.01352313
## confidence coverage lift count
## [1] 0.5862069 0.01769192 3.029608 102
## [2] 0.5845411 0.02104728 3.020999 121
## [3] 0.5823529 0.01728521 2.279125 99
## [4] 0.5736041 0.02003050 2.244885 113
## [5] 0.5700483 0.02104728 2.230969 118
## [6] 0.5629921 0.02582613 2.203354 143
## [7] 0.5525114 0.02226741 2.162336 121
## [8] 0.5245098 0.02074225 2.052747 107
## [9] 0.5230126 0.02430097 2.046888 125
## [10] 0.5175097 0.02613116 2.025351 133
Reguły o najwyższej pewności mają po prawej stronie najczęściej produkt whole milk, lub other vegatables. Wynika to z jego wysokiej popularności w zbiorze – skoro pojawia się w ~25% wszystkich transakcji, naturalnie trafia do wielu reguł jako „domyślny” następnik. Dlatego sama wysoka confidence nie wystarczy do oceny jakości reguły – konieczne jest spojrzenie łączne na wszystkie trzy miary.
Wizualizacje pomagają zobaczyć strukturę całego zbioru reguł, a nie tylko pojedyncze wiersze tabeli. Każdy wykres poniżej pokazuje ten sam zestaw reguł z innej perspektywy.
# Każda reguła to jeden punkt na wykresie.
# Oś X = support (jak często produkty współwystępują)
# Oś Y = confidence (jak pewna jest reguła)
# Kolor punktu = lift (im ciemniejszy/intensywniejszy, tym wyższy lift)
# Reguły w lewym górnym rogu mają niskie wsparcie, ale wysoką pewność i lift –
# są rzadkie, ale silne. To często najbardziej interesujące reguły.
plot(
reguly,
method = "scatterplot",
measure = c("support", "confidence"),
shading = "lift",
main = "Reguły asocjacyjne: support vs confidence (kolor = lift)"
)Wykres rozrzutu przedstawia wszystkie 170 odkrytych reguł. Widoczna jest typowa zależność: reguły o wysokim lift (ciemniejszy kolor) skupiają się w lewej górnej części wykresu – mają niższe wsparcie (rzadziej się pojawiają), ale wyższą pewność i silniejsze zależności. Reguły o wysokim wsparciu (prawa strona wykresu) mają zazwyczaj niższy lift, co oznacza że produkty te współwystępują często, ale niekoniecznie zaskakująco.
# Wykres grupuje reguły według lewej strony (LHS) i prawej strony (RHS).
# Bąbelki na przecięciu wierszy i kolumn oznaczają istnienie reguły.
# Rozmiar bąbelka = support (im większy, tym częściej ta kombinacja się pojawia)
# Kolor bąbelka = lift (im intensywniejszy, tym silniejsza zależność)
# Pokazujemy tylko 20 reguł z najwyższym lift, żeby wykres był czytelny.
plot(
sort(reguly, by = "lift")[1:20],
method = "grouped",
main = "Grupy reguł – 20 najlepszych wg lift"
)## Available control parameters (with default values):
## k = 20
## aggr.fun = function (x, ...) UseMethod("mean")
## rhs_max = 10
## lhs_label_items = 2
## col = c("#EE0000FF", "#EEEEEEFF")
## groups = NULL
## engine = ggplot2
## verbose = FALSE
Wykres grupowy pozwala szybko zobaczyć, które produkty po lewej stronie (LHS) prowadzą do których po prawej (RHS). Duże, intensywnie zabarwione bąbelki wskazują na reguły z wysokim wsparciem i wysokim lift jednocześnie – najbardziej wartościowe z praktycznego punktu widzenia.
# Graf sieciowy – jeden z najbardziej intuicyjnych sposobów wizualizacji reguł.
# Węzły (kółka) = produkty
# Strzałki = kierunek reguły (od LHS do RHS)
# Grubość/kolor krawędzi = wartość lift
# engine = "htmlwidget" tworzy interaktywny wykres – można przybliżać,
# oddalać i przeciągać węzły myszką w wygenerowanym raporcie HTML.
# Pokazujemy 20 reguł z najwyższym lift.
plot(
sort(reguly, by = "lift")[1:20],
method = "graph",
engine = "htmlwidget"
)Graf reguł w formie interaktywnej pozwala eksplorować powiązania między produktami. Węzły z wieloma połączeniami (tzw. hubs) to produkty centralne – pojawiają się w wielu regułach jednocześnie. W zbiorze Groceries takim centralnym węzłem jest zazwyczaj whole milk lub other vegetables.
# Wykres równoległy dobrze sprawdza się dla reguł wieloelementowych
# (np. {A, B} → {C}), gdzie mamy więcej niż 2 produkty w regule.
# Każda linia = jedna reguła, przebiegająca przez "kolumny" = pozycje w regule.
# Grubość linii = support (grubsza = częstsza reguła)
# Kolor = lift
plot(
sort(reguly, by = "lift")[1:15],
method = "paracoord",
main = "Wykres równoległy – 15 reguł o najwyższym lift"
)Wykres równoległy wizualizuje strukturę reguł wieloelementowych. Grubsze linie odpowiadają regułom o wyższym wsparciu. Można odczytać, że reguły z najwyższym lift często łączą mleko
Możemy zawęzić analizę do reguł dotyczących konkretnego produktu. Poniżej sprawdzamy, co prowadzi do zakupu pełnego mleka (whole milk) – czyli jakie produkty po lewej stronie reguły skutkują mlekiem po prawej.
# subset() filtruje reguły według podanego warunku.
# rhs %in% "whole milk" – wybieramy tylko reguły, gdzie prawa strona to "whole milk"
# (czyli reguły postaci: {coś} => {whole milk})
# Następnie sortujemy według lift i pokazujemy 10 najlepszych.
reguly_mleko <- subset(reguly, rhs %in% "whole milk")
inspect(sort(reguly_mleko, by = "lift")[1:10])## lhs rhs support confidence
## [1] {curd, yogurt} => {whole milk} 0.01006609 0.5823529
## [2] {other vegetables, butter} => {whole milk} 0.01148958 0.5736041
## [3] {tropical fruit, root vegetables} => {whole milk} 0.01199797 0.5700483
## [4] {root vegetables, yogurt} => {whole milk} 0.01453991 0.5629921
## [5] {other vegetables, domestic eggs} => {whole milk} 0.01230300 0.5525114
## [6] {yogurt, whipped/sour cream} => {whole milk} 0.01087951 0.5245098
## [7] {root vegetables, rolls/buns} => {whole milk} 0.01270971 0.5230126
## [8] {pip fruit, other vegetables} => {whole milk} 0.01352313 0.5175097
## [9] {tropical fruit, yogurt} => {whole milk} 0.01514997 0.5173611
## [10] {other vegetables, yogurt} => {whole milk} 0.02226741 0.5128806
## coverage lift count
## [1] 0.01728521 2.279125 99
## [2] 0.02003050 2.244885 113
## [3] 0.02104728 2.230969 118
## [4] 0.02582613 2.203354 143
## [5] 0.02226741 2.162336 121
## [6] 0.02074225 2.052747 107
## [7] 0.02430097 2.046888 125
## [8] 0.02613116 2.025351 133
## [9] 0.02928317 2.024770 149
## [10] 0.04341637 2.007235 219
Reguły prowadzące do zakupu pełnego mleka (whole milk) wskazują, że produkt ten często pojawia się w koszykach zawierających inne artykuły spożywcze, szczególnie z kategorii produktów mlecznych oraz świeżej żywności.
Najwyższą wartość lift osiąga reguła:
{curd, yogurt} ⇒ {whole milk}
z confidence = 0,58 i lift = 2,28. Oznacza to, że klienci kupujący twaróg i jogurt są ponad 2,2 razy bardziej skłonni do zakupu pełnego mleka niż przeciętny klient.
Podobną zależność obserwujemy w regule:
{other vegetables, butter} ⇒ {whole milk}
gdzie confidence wynosi 0,57, a lift ≈ 2,24. Wskazuje to, że mleko często pojawia się w koszykach zawierających warzywa oraz masło, co może odzwierciedlać zakupy produktów wykorzystywanych wspólnie w przygotowywaniu posiłków.
Ogólnie analizowane reguły sugerują, że pełne mleko jest produktem komplementarnym, który często współwystępuje z innymi produktami spożywczymi kupowanymi w ramach codziennych zakupów. ## Reguły dotyczące warzyw
# Analogicznie – filtrujemy reguły, gdzie następnikiem są "other vegetables".
reguly_warzywa <- subset(reguly, rhs %in% "other vegetables")
inspect(sort(reguly_warzywa, by = "lift")[1:10])## lhs rhs support
## [1] {citrus fruit, root vegetables} => {other vegetables} 0.01037112
## [2] {tropical fruit, root vegetables} => {other vegetables} 0.01230300
## [3] {root vegetables, rolls/buns} => {other vegetables} 0.01220132
## [4] {root vegetables, yogurt} => {other vegetables} 0.01291307
## [5] {yogurt, whipped/sour cream} => {other vegetables} 0.01016777
## [6] {root vegetables, whole milk} => {other vegetables} 0.02318251
## [7] {onions} => {other vegetables} 0.01423488
## [8] {pork, whole milk} => {other vegetables} 0.01016777
## [9] {whole milk, whipped/sour cream} => {other vegetables} 0.01464159
## [10] {pip fruit, whole milk} => {other vegetables} 0.01352313
## confidence coverage lift count
## [1] 0.5862069 0.01769192 3.029608 102
## [2] 0.5845411 0.02104728 3.020999 121
## [3] 0.5020921 0.02430097 2.594890 120
## [4] 0.5000000 0.02582613 2.584078 127
## [5] 0.4901961 0.02074225 2.533410 100
## [6] 0.4740125 0.04890696 2.449770 228
## [7] 0.4590164 0.03101169 2.372268 140
## [8] 0.4587156 0.02216573 2.370714 100
## [9] 0.4542587 0.03223183 2.347679 144
## [10] 0.4493243 0.03009659 2.322178 133
Reguły prowadzące do zakupu innych warzyw (other vegetables) wskazują, że produkt ten często pojawia się w koszykach zawierających inne warzywa lub owoce.
Przykładowo reguła {citrus fruit, root vegetables} ⇒ {other vegetables} osiga confidence = 0,59 oraz lift ≈ 3,03, co oznacza, że klienci kupujący cytrusy i warzywa korzeniowe są ponad trzykrotnie bardziej skłonni do zakupu innych warzyw niż przeciętny klient.
Podobną zależność obserwujemy w regule {tropical fruit, root vegetables} ⇒ {other vegetables}, gdzie confidence wynosi ok. 0,58, a lift ≈ 3,02.
Wyniki te sugerują, że zakupy warzyw i owoców często mają komplementarny charakter, a klienci kupujący jedną kategorię świeżych produktów mają tendencję do wybierania również innych warzyw w tej samej transakcji.
# Zawężamy zestaw reguł do tych, które jednocześnie spełniają:
# lift > 2 – produkty współwystępują ponad 2x częściej niż losowo
# confidence > 0.4 – reguła jest prawdziwa w ponad 40% przypadków
# To tzw. "mocne reguły" – najbardziej wiarygodne i zaskakujące jednocześnie.
mocne_reguly <- subset(reguly, lift > 2 & confidence > 0.4)
cat("Liczba mocnych reguł (lift > 2, conf > 0.4):", length(mocne_reguly), "\n")## Liczba mocnych reguł (lift > 2, conf > 0.4): 29
## lhs rhs support
## [1] {citrus fruit, root vegetables} => {other vegetables} 0.01037112
## [2] {tropical fruit, root vegetables} => {other vegetables} 0.01230300
## [3] {root vegetables, rolls/buns} => {other vegetables} 0.01220132
## [4] {root vegetables, yogurt} => {other vegetables} 0.01291307
## [5] {yogurt, whipped/sour cream} => {other vegetables} 0.01016777
## [6] {root vegetables, whole milk} => {other vegetables} 0.02318251
## [7] {onions} => {other vegetables} 0.01423488
## [8] {pork, whole milk} => {other vegetables} 0.01016777
## [9] {whole milk, whipped/sour cream} => {other vegetables} 0.01464159
## [10] {pip fruit, whole milk} => {other vegetables} 0.01352313
## [11] {curd, yogurt} => {whole milk} 0.01006609
## [12] {root vegetables} => {other vegetables} 0.04738180
## [13] {other vegetables, butter} => {whole milk} 0.01148958
## [14] {tropical fruit, root vegetables} => {whole milk} 0.01199797
## [15] {citrus fruit, whole milk} => {other vegetables} 0.01301474
## [16] {root vegetables, yogurt} => {whole milk} 0.01453991
## [17] {tropical fruit, yogurt} => {other vegetables} 0.01230300
## [18] {other vegetables, domestic eggs} => {whole milk} 0.01230300
## [19] {chicken} => {other vegetables} 0.01789527
## [20] {whole milk, butter} => {other vegetables} 0.01148958
## [21] {hamburger meat} => {other vegetables} 0.01382816
## [22] {whole milk, domestic eggs} => {other vegetables} 0.01230300
## [23] {tropical fruit, whole milk} => {other vegetables} 0.01708185
## [24] {whipped/sour cream} => {other vegetables} 0.02887646
## [25] {yogurt, whipped/sour cream} => {whole milk} 0.01087951
## [26] {root vegetables, rolls/buns} => {whole milk} 0.01270971
## [27] {pip fruit, other vegetables} => {whole milk} 0.01352313
## [28] {tropical fruit, yogurt} => {whole milk} 0.01514997
## [29] {other vegetables, yogurt} => {whole milk} 0.02226741
## confidence coverage lift count
## [1] 0.5862069 0.01769192 3.029608 102
## [2] 0.5845411 0.02104728 3.020999 121
## [3] 0.5020921 0.02430097 2.594890 120
## [4] 0.5000000 0.02582613 2.584078 127
## [5] 0.4901961 0.02074225 2.533410 100
## [6] 0.4740125 0.04890696 2.449770 228
## [7] 0.4590164 0.03101169 2.372268 140
## [8] 0.4587156 0.02216573 2.370714 100
## [9] 0.4542587 0.03223183 2.347679 144
## [10] 0.4493243 0.03009659 2.322178 133
## [11] 0.5823529 0.01728521 2.279125 99
## [12] 0.4347015 0.10899847 2.246605 466
## [13] 0.5736041 0.02003050 2.244885 113
## [14] 0.5700483 0.02104728 2.230969 118
## [15] 0.4266667 0.03050330 2.205080 128
## [16] 0.5629921 0.02582613 2.203354 143
## [17] 0.4201389 0.02928317 2.171343 121
## [18] 0.5525114 0.02226741 2.162336 121
## [19] 0.4170616 0.04290798 2.155439 176
## [20] 0.4169742 0.02755465 2.154987 113
## [21] 0.4159021 0.03324860 2.149447 136
## [22] 0.4101695 0.02999492 2.119820 121
## [23] 0.4038462 0.04229792 2.087140 168
## [24] 0.4028369 0.07168277 2.081924 284
## [25] 0.5245098 0.02074225 2.052747 107
## [26] 0.5230126 0.02430097 2.046888 125
## [27] 0.5175097 0.02613116 2.025351 133
## [28] 0.5173611 0.02928317 2.024770 149
## [29] 0.5128806 0.04341637 2.007235 219
Po zastosowaniu zaostrzonych progów (lift > 2 i confidence > 0.4) pozostaje 29 reguł. Wszystkie dotyczą produktów z kategorii inne warzywa mleko, co potwierdza, że to właśnie te kategorie wykazują najsilniejsze wzajemne zależności zakupowe.
# Wyświetlamy 5 reguł z najwyższym lift z pełnymi wartościami wszystkich miar.
# Kolumna 'count' to bezwzględna liczba transakcji, w których reguła wystąpiła.
inspect(sort(reguly, by = "lift")[1:5])## lhs rhs support
## [1] {citrus fruit, other vegetables} => {root vegetables} 0.01037112
## [2] {tropical fruit, other vegetables} => {root vegetables} 0.01230300
## [3] {beef} => {root vegetables} 0.01738688
## [4] {citrus fruit, root vegetables} => {other vegetables} 0.01037112
## [5] {tropical fruit, root vegetables} => {other vegetables} 0.01230300
## confidence coverage lift count
## [1] 0.3591549 0.02887646 3.295045 102
## [2] 0.3427762 0.03589222 3.144780 121
## [3] 0.3313953 0.05246568 3.040367 171
## [4] 0.5862069 0.01769192 3.029608 102
## [5] 0.5845411 0.02104728 3.020999 121
Poniżej przedstawiono szczegółową interpretację najsilniejszych odkrytych reguł:
Reguła 1: {citrus fruit, other vegetables} ⇒ {root vegetables}
Support = 0.0104 – ta kombinacja produktów pojawia się w około 1,04% wszystkich transakcji.
Confidence = 0.359 – w około 35,9% przypadków, gdy klient kupuje cytrusy oraz inne warzywa, w koszyku pojawiają się również warzywa korzeniowe.
Lift = 3.295 – produkty te są kupowane razem ponad 3,3 razy częściej, niż wynikałoby to z ich niezależnego występowania.
Reguła 2: {tropical fruit, other vegetables} ⇒ {root vegetables}
Support = 0.0123 – kombinacja ta występuje w około 1,23% wszystkich transakcji.
Confidence = 0.343 – w około 34,3% przypadków, gdy klient kupuje owoce tropikalne oraz inne warzywa, kupuje także warzywa korzeniowe.
Lift = 3.145 – oznacza to, że produkty te są kupowane razem ponad 3,1 razy częściej, niż gdyby ich zakupy były całkowicie niezależne.
Obie reguły wskazują na silną współzależność między zakupem owoców i warzyw, co może sugerować, że klienci dokonujący zakupów świeżych produktów często wybierają różne rodzaje warzyw w ramach jednej transakcji, prawdopodobnie z myślą o przygotowaniu posiłków.
Przeprowadzona analiza koszyka zakupowego z wykorzystaniem algorytmu
Apriori na zbiorze danych Groceries pozwoliła na
wyciągnięcie następujących wniosków:
Najczęstsze produkty w transakcjach to pełne mleko, inne warzywa oraz pieczywo – produkty codziennego użytku, które naturalnie pojawiają się w wielu koszykach zakupowych.
Algorytm Apriori przy progach
minsupp = 0.01 i minconf = 0.25 wygenerował
170 reguł asocjacyjnych, z których 29 spełnia zaostrzone kryteria
jakości (lift > 2 i confidence > 0.4).
Najsilniejsze zależności (najwyższy lift) dotyczą produktów z kategorii warzyw, owoców i nabiału – co sugeruje, że pewne segmenty klientów charakteryzują się spójnymi, zdrowotnymi preferencjami żywieniowymi.
Zastosowania praktyczne odkrytych reguł mogą obejmować:
Ograniczenia analizy: Wyniki zależą od
przyjętych progów – inne wartości minsupp i
minconf dałyby inny zestaw reguł. Ponadto reguły
asocjacyjne wykrywają korelacje, nie przyczynowość – samo
współwystępowanie produktów nie oznacza, że jeden zakup powoduje
drugi.
# Wyświetlenie informacji o wersji R i załadowanych pakietach –
# standardowy element raportów naukowych, zapewniający odtwarzalność wyników.
sessionInfo()## R version 4.4.0 (2024-04-24 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 19045)
##
## Matrix products: default
##
##
## locale:
## [1] LC_COLLATE=Polish_Poland.utf8 LC_CTYPE=Polish_Poland.utf8
## [3] LC_MONETARY=Polish_Poland.utf8 LC_NUMERIC=C
## [5] LC_TIME=Polish_Poland.utf8
##
## time zone: Europe/Warsaw
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] arulesViz_1.5.4 arules_1.7-10 Matrix_1.7-0
##
## loaded via a namespace (and not attached):
## [1] viridis_0.6.5 sass_0.4.9 utf8_1.2.4 generics_0.1.3
## [5] tidyr_1.3.1 lattice_0.22-6 digest_0.6.35 magrittr_2.0.3
## [9] evaluate_0.23 grid_4.4.0 RColorBrewer_1.1-3 iterators_1.0.14
## [13] fastmap_1.2.0 foreach_1.5.2 jsonlite_1.8.8 ggrepel_0.9.6
## [17] seriation_1.5.8 gridExtra_2.3 purrr_1.0.2 fansi_1.0.6
## [21] viridisLite_0.4.2 scales_1.4.0 tweenr_2.0.3 codetools_0.2-20
## [25] jquerylib_0.1.4 registry_0.5-1 cli_3.6.2 rlang_1.1.7
## [29] graphlayouts_1.2.3 polyclip_1.10-7 visNetwork_2.1.4 tidygraph_1.3.1
## [33] withr_3.0.0 cachem_1.1.0 yaml_2.3.8 tools_4.4.0
## [37] memoise_2.0.1 dplyr_1.1.4 ggplot2_4.0.2 ca_0.71.1
## [41] TSP_1.2.6 vctrs_0.6.5 R6_2.5.1 lifecycle_1.0.4
## [45] htmlwidgets_1.6.4 MASS_7.3-60.2 ggraph_2.2.2 pkgconfig_2.0.3
## [49] pillar_1.9.0 bslib_0.7.0 gtable_0.3.6 glue_1.7.0
## [53] Rcpp_1.0.12 ggforce_0.5.0 xfun_0.52 tibble_3.2.1
## [57] tidyselect_1.2.1 rstudioapi_0.16.0 knitr_1.50 farver_2.1.2
## [61] htmltools_0.5.8.1 igraph_2.2.2 labeling_0.4.3 rmarkdown_2.27
## [65] compiler_4.4.0 S7_0.2.1
Raport wygenerowany w R Markdown. Dane: zbiór Groceries, pakiet arules (Hahsler et al.).