Cel projektu
Nasza agencja “C jak Cudowni” została poproszona o przeanalizowanie danych sprzedażowych kawiarni CafePG z roku 2020. Celem było przeanalizowanie przyzwyczajeń zakupowych klientów kawiarni, zrozumienie trendów sprzedażowych, ustalenie produktów i kategorii produktów, które przynoszą największy i najmniejszy przychód. Na podstawie tych danych poczyniono rekomendacje co do stworzenia kombinacji produktów, które kupują klienci, w celu zaproponowania nowych zestawów do menu i maksymalizacji zysków. W podsumowaniu przekazano również zalecenia względem utrzymania lub rezygnacji ze sprzedaży pewnej kategorii produktów ze względu na płynące z nich przychody.
Czyszczenie danych
Poniższe kroki zostały wykonane w celu weryfikacji poprawności oraz poprawienia jakości analizowanych danych. Poprawiono błędy językowe, błędne zaszeregowanie do kategorii, wprowadzono dodatkowe zmienne w celu dokładniejszej analizy, zmieniono niejasną nazwę kategorii MSC na poprawną, zweryfikowano braki danych oraz dokonano walidacji danych, zmieniono format danych według potrzeb.
Weryfikacja poprawności i kompletności danych
Identyfikacja wyników odstających
#weryfikacja outlierów
cafe_pg%>%
ggplot(aes(x = category, y = total)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7)) +
geom_boxplot()
W pierwszym kroku wykryto wartość bardzo odstającą. Zastosowano filtr na zmiennej total<7500 w celu lepszej wizualizacji reszty danych.
#weryfikacja outlierów
cafe_pg%>%
filter(total<7500)%>%
ggplot(aes(x = category, y = total)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7)) +
geom_boxplot()
Wykres obrazuje, że główna koncentracja wartości zmiennej total zawiera się poniżej 1000. W związku z tym przyjmujemy założenie, że total>1000 związany jest z nietypowymi sytuacjami, najprawdopodobniej są to zakupy grupowe.
W celu lepszej analizy różnic w zakupach indywidualnych względem grupowych wprowadzono kategorię zakupów grupowych, gdzie total jest większy niż 1000.
cafe_pg <- cafe_pg %>%
mutate(groups = ifelse(total> 1000, 1, 0))
Weryfikacja, czy występują brakujące obserwacje - nie występują.
sum(is.na.data.frame(cafe_pg))
## [1] 0
Walidacja nazw kategorii
Występuje 54 obserwacje w których nazwa kategorii nie zgadza się z zadanymi kategoriami.
summary((cafe_pg$category %in% c('BEVERAGE', 'FOOD', 'LIQUOR', 'LIQUOR & TOBACCO', 'MERCHANDISE', 'MISC', 'TOBACCO','WINES')))
## Mode FALSE TRUE
## logical 54 145776
cafe_pg %>%
group_by(category) %>%
summarise(count = n()) %>%
arrange(-count)
## # A tibble: 8 × 2
## category count
## <chr> <int>
## 1 FOOD 57023
## 2 BEVERAGE 43573
## 3 TOBACCO 36496
## 4 LIQUOR 6201
## 5 MISC 1187
## 6 WINES 809
## 7 MERCHANDISE 487
## 8 LIQUOR & TPBACCO 54
Zidentyfikowano, ze wynika to z literówki w nazwie kategorii ‘LIQUOR & TOBACCO’ i poprawiono te nazwy.
Skorygowanie błędnej nazwy.
cafe_pg <- cafe_pg %>%
mutate(category = replace (category,category=='LIQUOR & TPBACCO','LIQUOR & TOBACCO'))
Po poprawieniu literówki wszystkie kategorie są poprawne.
summary((cafe_pg$category %in% c('BEVERAGE', 'FOOD', 'LIQUOR', 'LIQUOR & TOBACCO', 'MERCHANDISE', 'MISC', 'TOBACCO','WINES')))
## Mode TRUE
## logical 145830
Zmiany językowe
Skorygowanie błędnego zapisu polskich znaków w nazwach produktów.
cafe_pg$`item desc` <- gsub("á", "", cafe_pg$`item desc`)
Zmiany kategorii
Dodanie oznaczeń liczbowych dla produktu w danej kategorii, co pozwoli na sprawniejszą analizę produktów oferowanych przez CafePG i znalezienie błędów typu kieliszek wina skategoryzowany jako TOBACCO.
cafe_pg <- cafe_pg %>%
group_by(category) %>%
mutate(position_in_category = dense_rank(tolower(`item desc`))) %>%
ungroup()
options(max.print = 100)
position_counts <- cafe_pg %>%
filter(!is.na(position_in_category)) %>%
group_by(category, position_in_category, `item desc`) %>%
summarize(count = n())
print(position_counts %>% filter(category == "MISC"))
## # A tibble: 48 × 4
## # Groups: category, position_in_category [48]
## category position_in_category `item desc` count
## <chr> <int> <chr> <int>
## 1 MISC 1 1 AXE TWIST 6
## 2 MISC 2 ADD CHICKEN BACON 4
## 3 MISC 3 ADD GROUND MEAT 3
## 4 MISC 4 ADD HERB ROAST CHICKEN 158
## 5 MISC 5 ADD ON S 379
## 6 MISC 6 ADD POTATO WEDGES 34
## 7 MISC 7 ADD TRADITIONAL MEAT FEAST 8
## 8 MISC 8 DARK RUM (SM) 2
## 9 MISC 9 ENG BREAKFAST TEA 4
## 10 MISC 10 FISH FINGER 2
## # ℹ 38 more rows
Uporządkowanie kategorii MISC do właściwych kategorii.
Zostanie tylko jedna pozycja w kategorii MISC “PARTY CHARGES @ 500/-” co jest racjonalne ze względu na to, że opłaty administracyjnej nie da się przyporządkować do konkretnej kategorii.
cafe_pg$category[cafe_pg$category == "MISC" & cafe_pg$position_in_category %in% c(1,9,15,24,34,42,43,45)] <- "BEVERAGE"
cafe_pg$category[cafe_pg$category == "MISC" & cafe_pg$position_in_category %in% c(2, 3,4,5,6,7,10,12,14,18,20,21,23,26,27,29,31,35,36,37,38,39,40,41,46,47)] <- "FOOD"
cafe_pg$category[cafe_pg$category == "MISC" & cafe_pg$position_in_category %in% c(8,11,17,16)] <- "LIQUOR"
cafe_pg$category[cafe_pg$category == "MISC" & cafe_pg$position_in_category %in% c(22,30)] <- "MERCHANDISE"
cafe_pg$category[cafe_pg$category == "MISC" & cafe_pg$position_in_category %in% c(13,19,25,27,28,32,44,48)] <- "TOBACCO"
Uporządkowanie towarów błędnie skategoryzowanych
Dodatkowo, wykryto kilka błędnie przypisanych tytoni i również je przeniesiono do właściwej kategorii.
cafe_pg$category[cafe_pg$`item desc` == "SWEET MELON FLAVOUR SINGLE"] <- "TOBACCO"
cafe_pg$category[cafe_pg$`item desc` == "MIXED FLAVOUR SINGLE"] <- "TOBACCO"
Zmiana kategorii dla LATE HARVEST SULA CHENIN z TOBACCO na WINES.
cafe_pg$category[cafe_pg$`item desc` == "LATE HARVEST SULA CHENIN (GLS)"] <- "WINES"
cafe_pg$category[cafe_pg$`item desc` == "LATE HARVEST SULA CHENIN (BTL)"] <- "WINES"
Zmiana kategorii J.PCHENET SPARKLING ROSE (BTL) z FOOD na WINES.
cafe_pg$category[cafe_pg$`item desc` == "J.PCHENET SPARKLING ROSE (BTL)"] <- "WINES"
Ponowne przypisanie i sprawdzenie numerów pozycji w kategoriach - przede wszystkim MISC.
cafe_pg <- cafe_pg %>%
group_by(category) %>%
mutate(position_in_category = dense_rank(tolower(`item desc`))) %>%
ungroup()
options(max.print = 10)
position_counts <- cafe_pg %>%
filter(!is.na(position_in_category)) %>%
group_by(category, position_in_category, `item desc`) %>%
summarize(count = n())
print(position_counts %>% filter(category == "MISC"))
## # A tibble: 1 × 4
## # Groups: category, position_in_category [1]
## category position_in_category `item desc` count
## <chr> <int> <chr> <int>
## 1 MISC 1 PARTY CHARGES @ 500/- 1
W związku z tym, że w kategorii MISC została jedna pozycja “Party charges” zamieniono nazwę kategorii MISC na PARTY CHARGES.
cafe_pg <- cafe_pg %>%
mutate(category = replace (category,category=='MISC','PARTY CHARGES'))
Zmiana formatu zmiennych i dodanie zmiennych potrzebnych do analizy zmian w czasie
Wyciągnięcie z pełnej daty z godziną samej godziny w celu analizy zakupów godzinowych. Utworzenie zmiennych dla dni i miesięcy.
cafe_pg$date <- as.Date(cafe_pg$date, format="%Y-%m-%d")
cafe_pg$time <- as_hms(cafe_pg$time)
cafe_pg <- cafe_pg %>%
mutate(dzientyg = wday(cafe_pg$date, label=TRUE, abbr=FALSE))
cafe_pg <- cafe_pg %>%
mutate(miesiac = month(cafe_pg$date, label=TRUE, abbr=FALSE))
cafe_pg <- cafe_pg %>%
mutate(hour_minute_second = format(time, format = "%H:%M:%S"),
godzina = hour(time))
Analiza opisowa
Analiza Statystyczna Kategorii Produktów:
Sporządzono tabele opisującą wartości “total” według poszczególnych kategorii. W kategorii MISC obecnie znajduje się tylko jedna obserwacja jak opisano wyżej. Największą średnią wielkością sprzedaży charakteryzuje się kategoria LIQUOR & TOBACCO, gdzie minimalna wartość transakcji wyniosła 644. Najniższe średnie wartości sprzedaży odnotowano w kategorii BEVERAGE, gdzie mediana wynosi 105.19, czyli połowa wartości w kategorii BEVERAGE jest niższa od 105.19, a druga połowa wyższa. Przejdźmy do pojęcia skośności, która wskazuje, czy większość zmian zmiennej “total” znajduje się poniżej średniej czy powyżej. W przypadku, gdy więcej obserwacji jest poniżej średniej, wtedy rozkład zmiennej jest prawostronny. Wszystkie kategorie charakteryzują się dodatnim współczynnikiem skośności, a więc rozkładem prawostronnym.| category | średnia | odchylenie | wariancja | minimum | maximum | Q1 | mediana | Q3 | Skośność | Kurtoza |
|---|---|---|---|---|---|---|---|---|---|---|
| BEVERAGE | 126.67 | 87.46 | 0.69 | 30 | 2735 | 74.25 | 105.19 | 142.31 | 3.55 | 33.30 |
| FOOD | 172.69 | 79.25 | 0.46 | 0 | 3267 | 136.13 | 167.06 | 191.81 | 4.27 | 73.29 |
| LIQUOR | 341.17 | 294.04 | 0.86 | 122 | 5250 | 157.50 | 295.31 | 393.75 | 4.31 | 35.33 |
| LIQUOR & TOBACCO | 788.18 | 281.17 | 0.36 | 644 | 1980 | 660.00 | 660.00 | 660.00 | 2.22 | 4.68 |
| MERCHANDISE | 256.20 | 211.34 | 0.82 | 27 | 1654 | 100.13 | 224.70 | 300.00 | 2.54 | 9.45 |
| PARTY CHARGES | 14231.25 | NA | NA | 14231 | 14231 | 14231.25 | 14231.25 | 14231.25 | NA | NA |
| TOBACCO | 398.08 | 121.43 | 0.31 | 88 | 2970 | 323.40 | 330.00 | 462.00 | 3.49 | 32.79 |
| WINES | 441.95 | 421.88 | 0.95 | 1 | 4536 | 220.50 | 252.00 | 441.00 | 3.81 | 23.29 |
Analiza szczegółowa:
BEVERAGE: Średnia wartość produktów w kategorii BEVERAGE wynosi 126.67, co stanowi miarę centralną reprezentującą wartość oczekiwaną. Jednakże, istotnym aspektem jest odchylenie standardowe, które wynosi 87.46. Oznacza to, że ceny napojów w tej kategorii wahają się średnio o tę wartość wokół średniej. Wartość skośności (3.55) wskazuje na asymetrię w prawo, co sugeruje, że istnieją pewne produkty w tej kategorii o wyższych cenach, co potwierdza także wysoka kurtoza (33.30), świadcząca o obecności ekstremalnych cen.
FOOD: W kategorii FOOD średnia wartość produktów wynosi 172.69, a odchylenie standardowe 79.25. Średnia ta jest centralną miarą reprezentującą cenę oczekiwaną, natomiast odchylenie standardowe wskazuje na średnią zmienność cen wokół tej wartości. Wysoka skośność (4.27) sugeruje obecność wyższych cen, co potwierdza także kurtoza (73.29), wskazująca na występowanie ekstremalnych wartości cenowych.
LIQUOR: Kategoria LIQUOR charakteryzuje się średnią wartością produktów na poziomie 341.17, jednak odchylenie standardowe (294.04) wskazuje na dużą zmienność cen w tej kategorii. Skośność (4.31) i kurtoza (35.33) potwierdzają występowanie skrajnych wartości cenowych, co oznacza, że niektóre produkty w tej kategorii są znacznie droższe niż inne.
LIQUOR & TOBACCO: W przypadku kategorii LIQUOR & TOBACCO, średnia wartość wynosi 788.18, a niskie odchylenie standardowe (281.17) wskazuje na stosunkowo niską zmienność cen w porównaniu z wartością średnią. Skośność (2.22) wskazuje na pewną asymetrię w prawo, co może oznaczać obecność produktów o wyższych cenach. Wysoka kurtoza (4.68) sugeruje obecność ekstremalnych cen.
MERCHANDISE: Kategoria MERCHANDISE prezentuje średnią wartość produktów na poziomie 256.20, a odchylenie standardowe 211.34 wskazuje na znaczną zmienność cen w tej kategorii. Skośność (2.54) i kurtoza (9.45) potwierdzają obecność wyższych wartości cenowych, co może być istotne dla analizy rynku tego rodzaju produktów.
TOBACCO: Produkty tytoniowe charakteryzują się średnią wartością wynoszącą 398.08, a odchylenie standardowe 121.43 wskazuje na umiarkowaną zmienność cen. Skośność (3.49) i kurtoza (32.79) sygnalizują obecność produktów o wyższych cenach, a także możliwość występowania ekstremalnych wartości cenowych.
WINES: W kategorii WINES średnia wartość produktów wynosi 441.95, a wysokie odchylenie standardowe (421.88) wskazuje na znaczną zmienność cen. Skośność (3.81) i kurtoza (23.29) potwierdzają obecność wyższych wartości cenowych oraz możliwość występowania ekstremalnych wartości w tej kategorii.
Podsumowując, odchylenie standardowe stanowi kluczową miarę w analizie zmienności cen produktów w poszczególnych kategoriach, a jego wartość informuje o rozproszeniu cen wokół średniej. Wysokie odchylenie standardowe sugeruje większe wahania cenowe, co może być istotne w kontekście strategii cenowej oraz zrozumienia dynamiki rynku dla poszczególnych kategorii produktów.
Analiza najpopularniejszych produktów i kategorii
Celem poniższej analizy jest zbadanie, który produkt oraz jaka kategoria są najczęściej wybierane przez klientów restauracji CafePG. Wzięto pod uwagę zarówno częstość wyboru (count) jak i ogólnie zamówioną ilość (quantity). Wyniki przedstawiono poniżej.
5 najpopularniejszych produktów ogółem
par(mfrow=c(3,1))
ggplot(cafe_pg %>%
group_by(`item desc`)%>%
summarise(count = n(), total_quantity = sum(quantity))%>%
arrange(desc(count))%>%
head(5),
aes(x = reorder(`item desc`, -total_quantity), y = total_quantity)) +
geom_bar(stat = "identity", fill = "skyblue") +
geom_text(aes(label = total_quantity), vjust = -0.5, color = "black", size = 3) +
labs(title = "Najpopularniejsze Produkty Ogółem", x = "Produkt", y = "Liczba") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7))
Popularnosc każdej z kategorii
ggplot(cafe_pg %>%
group_by(category) %>%
summarise(count = n(), total_quantity = sum(quantity)) %>%
arrange(desc(count)),
aes(x = reorder(category, -total_quantity), y = total_quantity)) +
geom_bar(stat = "identity", fill = "skyblue") +
geom_text(aes(label = total_quantity), vjust = -0.5, color = "black", size = 3) +
labs(title = "Popularność poszczególnych kategorii", x = "Kategoria", y = "Liczba") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7))
Najpopularniejszy produkt wg kategorii (z uwzglednieniem quantity)
gt(cafe_pg %>%
group_by(category, `item desc`) %>%
summarise(count = n(), total_quantity = sum(quantity), .groups = "drop_last") %>%
group_by(category) %>%
slice_max(order_by = count, n = 1)) %>%
tab_spanner(
label = "Najpopularniejsze produkty w danej kategorii",
columns = c(count, total_quantity)
) %>%
fmt_number(columns = c(count, total_quantity), decimals = 0) %>%
tab_header(
title = "Popularność wg kategorii",
subtitle = "Z uwzględnieniem wartości count, czyli ile razy zamówiono dany produkt na rachunku oraz total_quantity z uwzględnieniem ilości zamówionych produktów na jednym rachunku.",
) %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body()
)
| Popularność wg kategorii | ||
| Z uwzględnieniem wartości count, czyli ile razy zamówiono dany produkt na rachunku oraz total_quantity z uwzględnieniem ilości zamówionych produktów na jednym rachunku. | ||
| item desc | Najpopularniejsze produkty w danej kategorii | |
|---|---|---|
| count | total_quantity | |
| BEVERAGE | ||
| CAPPUCCINO | 5,495 | 7,144 |
| FOOD | ||
| OCEAN SPECIAL SHAKE | 4,895 | 5,914 |
| LIQUOR | ||
| CARLSBERG | 1,716 | 3,380 |
| LIQUOR & TOBACCO | ||
| BEER HOOKAH | 40 | 49 |
| MERCHANDISE | ||
| OCEAN SPECIAL T-SHIRTS | 34 | 37 |
| PARTY CHARGES | ||
| PARTY CHARGES @ 500/- | 1 | 23 |
| TOBACCO | ||
| NIRVANA HOOKAH SINGLE | 8,553 | 8,686 |
| WINES | ||
| VLN CAB SAUV (GLS) | 146 | 216 |
Najbardziej dochodowe produkty
ggplot(cafe_pg %>%
group_by(`item desc`) %>%
summarise(total1 = sum(total)) %>%
arrange(desc(total1)) %>%
head(5), aes(x = reorder(`item desc`, -total1), y = total1)) +
geom_bar(stat = "identity", fill = "skyblue") +
geom_text(aes(label = sprintf("%.2f", round(total1, 2))), vjust = -0.5, color = "black", size = 3) +
labs(title = "Najbardziej dochodowe produkty", x = "Produkt", y = "Przychód (tys.)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7)) +
scale_y_continuous(labels = scales::number_format(scale = 1e-3))
Najpopularniejsza kategoria to FOOD. Najpopularniejszy produkt ogółem to NIRVANA HOOKAH SINGLE.
Analiza produktów pod względem cen
Znalezienie najdroższego przedmiotu ogółem i w każdej kategorii.
TOP10 najdroższych produktów oferowanych przez CafePG.
highest_price_product <- cafe_pg %>%
arrange(desc(rate)) %>%
distinct(`item desc`, .keep_all = TRUE) %>%
slice_head(n = 10) %>%
select(`item desc`, rate)
print(highest_price_product)
## # A tibble: 10 × 2
## `item desc` rate
## <chr> <dbl>
## 1 GOSSIPS CHARD AUS (BTL) 2100
## 2 MATEUS ROSE PORTUGAL(BTL) 2000
## 3 2 OCEAN PINOTAGE (BTL) 1900
## 4 J.PCHENET SPARKLING ROSE (BTL) 1700
## 5 MAISON PIERRE SAUV MARSAN 1700
## 6 FLAVOR 1000 GMS 1470
## 7 HOEGAARDEN LTR MUGS (2+1) 1300
## 8 STELLA 1LTR 2+1 1300
## 9 SULA BRUT (BTL) 1200
## 10 SCHNEIDER BUCKET - 6 1200
Najdroższy przedmiot ogółem to butelka australijskiego wina Gossip Chard.
Weryfikacja najdroższego produktu w pozostałych kategoriach
Pominięto kategorię PARTY CHARGES, ponieważ tam występuje tylko opłata administracyjna za zorganizowanie przyjęcia.
highest_products_by_category <- cafe_pg %>%
filter(category %in% c("BEVERAGE", "FOOD", "LIQUOR", "LIQUOR & TOBACCO", "MERCHANDISE", "TOBACCO","WINES")) %>%
group_by(category) %>%
arrange(desc(rate)) %>%
slice_head(n = 1) %>%
ungroup() %>%
select(category, `item desc`, rate)
print(highest_products_by_category)
## # A tibble: 7 × 3
## category `item desc` rate
## <chr> <chr> <dbl>
## 1 BEVERAGE "RED SANGRIA (CARAFE) " 800
## 2 FOOD "SCHNEIDER 2+1" 600
## 3 LIQUOR "HOEGAARDEN LTR MUGS (2+1)" 1300
## 4 LIQUOR & TOBACCO "4 DOM BEER + 1SPL SHEESHA" 750
## 5 MERCHANDISE "FLAVOR 1000 GMS" 1470
## 6 TOBACCO "VALENTINE SPECIAL SHEESHA" 500
## 7 WINES "GOSSIPS CHARD AUS (BTL)" 2100
Najdroższy przedmiot w każdej kategorii to: 1. BEVERAGE - karafka czerwonej Sangrii za 800 2. FOOD - Schneider w zestawie 2+1 za 600 3. LIQUOR - litrowy HOEGAARDEN w zestawie 2+1 4. LIQUOR & TOBACCO - zestaw dla grupki znajomych 4 DOM BEER + 1SPL SHEESHA za 750 5. MERCHANDISE - kilogramowy uszlachetniacz do tytoniu FLAVOR 1000 GMS za 1470 6. TOBACCO - zdecydowanie króluje walentynkowa mieszanka dla zakochanych <3 za 500 7. WINES - butelka australijskiego wina Gossip Chard za 2100
Badanie udziału kategorii w przychodach
Poniżej zaprezentowano wykres ukazujący udział kategorii w przychodach. CafePG ma największe przychody ze sprzedaży produktów tytoniowych - ponad 40% wszystkich przychodów. Najmniejsze przychody (poniżej 2%) generuje sprzedaż wina, gadżetów, kombinacji wyrobów tytoniowych z alkoholami oraz opłaty związane z organizacją imprez.
# Summarizing total sales per category
category_sales <- cafe_pg %>%
group_by(category) %>%
summarise(total_sales = sum(total))
# Calculating the total sales across all categories
whole_sales <- sum(category_sales$total_sales)
# Calculating the percentage of total sales for each category
category_sales <- category_sales %>%
mutate(percentage_of_total = ((total_sales / whole_sales) * 100),
percentage_label = sprintf("%.2f%%", percentage_of_total))
# Reordering the categories based on percentage_of_total
category_sales <- category_sales %>%
mutate(category = reorder(category, -percentage_of_total))
# Plotting the data with formatted labels
ggplot(category_sales, aes(x = category, y = percentage_of_total, fill = category)) +
geom_bar(stat = "identity", fill = "skyblue") +
theme_minimal() +
geom_text(aes(label = percentage_label), vjust = -0.5, color = "black", size = 3) +
labs(title = "Procentowy udział kategorii w przychodach", x = "Kategoria", y = "Przychód") +
scale_y_continuous(labels = function(x) sprintf("%.2f%%", x)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7))
Największe dochody przynosi sprzedaż w kategorii TOBACCO.
Badanie ruchu klientów: dzienny, godzinowy, miesięczny
Badając ruch klientów w poszczególnych miesiącach widać, że najbardziej dochodowym miesiącem był październik, natomiast najmniej dochodowym luty. W podziale na dni tygodnia, średnio największe zarobki osiągano w czwartki, a najniższe w poniedziałki i wtorki. Analizując liczbę otwartych rachunków ogółem w wybranych okresach, można wywnioskować że wrzesień jest miesiącem, w którym w 2020 roku było najwięcej gości. Najniższą aktywność restauracja odnotowała w lutym, gdzie liczba otwartych rachunków była najniższa. Najwięcej rachunków odnotowano w czwartki, a najmniej we wtorki. Analizując godzinową aktywność, najwięcej zamówień odnotowano około godziny 20, a między 10-17 zaobserwować można stopniowy wzrost aktywności, co widać po wzrastającej liczbie zamówień.
# Analiza miesięczna
monthly_summary <- cafe_pg %>%
group_by(miesiac) %>%
summarise(avg_value = sum(total),avg_bills = n_distinct(`bill number`))
# Analiza dzienna
daily_summary <- cafe_pg %>%
group_by(dzientyg) %>%
mutate(total1 = sum(total))%>%
summarise(avg_value = mean(`total1`),avg_bills = n_distinct(`bill number`))
# Analiza godzinowa
hourly_summary <- cafe_pg %>%
group_by(godzina) %>%
summarise(avg_bills = n_distinct(`bill number`))
Ruch klientów: miesięczny
ggplot(monthly_summary, aes(x = factor(miesiac), y = avg_value)) +
geom_bar(stat = "identity", fill = "skyblue") +
geom_text(aes(label = round(avg_value, 0)), vjust = -0.5, color = "black", size = 3)+
labs(title = "Wartość przychodu w danych miesiącach", x = "Miesiąc", y = "Przychód (tys.)")+
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7))+
scale_y_continuous(labels = scales::number_format(scale = 1e-3))
ggplot(monthly_summary, aes(x = factor(miesiac), y = avg_bills)) +
geom_bar(stat = "identity", fill = "black") +
geom_text(aes(label = avg_bills), vjust = -0.5, color = "black", size = 3)+
geom_text(aes(label = avg_bills), vjust = -0.5, color = "black", size = 3)+
labs(title = "Liczba rachunków w danych miesiącach", x = "Miesiąc", y = "liczba rachunków")+
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.7))
Ruch klientów: dzienny
ggplot(daily_summary, aes(x = factor(dzientyg), y = avg_value)) +
geom_bar(stat = "identity", fill = "skyblue") +
labs(title = "Średnia wartość zarobków na dzień", x = "Dzień", y = "Średnia wartość (tys.)") +
scale_y_continuous(labels = scales::number_format(scale = 1e-3))
ggplot(daily_summary, aes(x = factor(dzientyg), y = avg_bills)) +
geom_bar(stat = "identity", fill = "black") +
geom_text(aes(label = avg_bills), vjust = -0.5, color = "black", size = 3)+
labs(title = "Liczba rachunków na dzień", x = "Dzień", y = "liczba rachunków")
Ruch klientów: godzinowy
ggplot(hourly_summary, aes(x = godzina, y = avg_bills)) +
geom_line() +
labs(title = "Liczba rachunków godzinowo", x = "Godzina", y = "liczba rachunków")+
theme_minimal()
Dzienne trendy sprzedaży
Analiza dziennych trendów sprzedaży w CafePG rzuca światło na ciekawe zjawiska. Co ciekawe, średnia sprzedaż jedzenia, napojów i tytoniu utrzymuje się na stabilnym poziomie każdego dnia, choć warto zauważyć pewne subtelne różnice. Szczególnie interesujące są maksymalne średnie sprzedaże w poszczególne dni tygodnia.
daily_summary_TREND <- cafe_pg %>%
filter(category != "PARTY CHARGES") %>%
group_by(dzientyg, category) %>%
summarise(avg_total = mean(total), num_bills = n_distinct(`bill number`))
# Find the rows with maximum values for each category
max_values <- daily_summary_TREND %>%
group_by(category) %>%
filter(avg_total == max(avg_total))
ggplot(daily_summary_TREND, aes(x = dzientyg, y = avg_total, color = category, group = category)) +
geom_line(size = 1) +
geom_point(data = max_values, aes(x=dzientyg,y=avg_total), pch = 19, size = 3, color = "black") +
geom_text(data = max_values, aes(x = dzientyg, y = avg_total, label = sprintf("%.2f", avg_total)), vjust = -0.8, hjust = 0.5, size = 3) +
labs(title = "Dzienne trendy sprzedaży",
x = "Dni tygodnia",
y = "Średnia z total",
color = "Category") +
scale_color_manual(values = c("BEVERAGE" = "#696969", "FOOD" = "orange", "LIQUOR" = "darkgreen", "LIQUOR & TOBACCO" = "black", "MERCHANDISE" = "navy", "TOBACCO" = "red", "WINES" = "darkorchid")) +
scale_y_continuous(limits = c(0, max(daily_summary_TREND$avg_total) + 100)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 1))
Nasze dania cieszą się największym zainteresowaniem w piątki osiągając średnią sprzedaż na poziomie 176,22. Jest to prawdopodobnie związane z wyraźnym odprężeniem, jakiego ludzie szukają po intensywnym tygodniu pracy, decydując się na relaksujące spotkania w naszej kawiarni. Piątkowe popołudnie to nie tylko jedzenie. Średnia sprzedaż napojów w tym dniu osiąga 129,38, co sugeruje, że nasi goście pragną wykwintnych smaków i doświadczeń kulinarnych z ulubionymi napojami.
Największe zainteresowanie tytoniem przypada w czwartki, gdzie średnia sprzedaż wynosi imponujące 404,76. To może być związane z charakterystycznym dla tego dnia rytuałem relaksu po cięższym początku tygodnia.
W piątki notujemy najwyższą średnią sprzedaż alkoholi na poziomie 358,51, co sugeruje, że nasza kawiarnia staje się miejscem wybieranym na spotkania towarzyskie podczas wieczoru przedweekendowego. Wino zaś najczęściej sprzedajmy w sobotę i osiąga największą średnią sprzedaż na poziomie 493,66, co można wiązać z tradycją lampki wina do sobotniego obiadu.
Najbardziej imponującą średnią sprzedażą charakteryzuje się kategoria “alkohole i tytonie” w środę, osiągając 820,78. To może być związane z potrzebą środowego odstresowania, gdzie klienci decydują się na połączenie napojów i tytoniu.
Gadżety również najczęściej sprzedają się w piątek ze średnią sprzedażą 292,56
Podsumowując, nasza kawiarnia oferuje różnorodne doświadczenia dostosowane do preferencji naszych gości w zależności od dnia tygodnia. Dzięki tej analizie możemy lepiej zrozumieć, co przyciąga naszych klientów i jak możemy dalej dostosować naszą ofertę, aby spełniać ich oczekiwania.
Trendy dla klientów indywidualnych
Analiza sprzedaży dla klientów indywidualnych ujawnia interesujące trendy. Średnia sprzedaż jedzenia, napojów i tytoniu utrzymuje się na zbliżonym poziomie każdego dnia, z pewnymi wyjątkami.
daily_summary_TREND_groups0 <- cafe_pg %>%
filter(category != "PARTY CHARGES", groups == 0) %>%
group_by(dzientyg, category) %>%
summarise(avg_total = mean(total), num_bills = n_distinct(`bill number`))
# Find the rows with maximum values for each category
max_values2 <- daily_summary_TREND_groups0 %>%
group_by(category) %>%
filter(avg_total == max(avg_total))
ggplot(daily_summary_TREND_groups0, aes(x = dzientyg, y = avg_total, color = category, group = category)) +
geom_line(size = 1) +
geom_point(data = max_values2, aes(x = dzientyg, y = avg_total), pch = 19, size = 3, color = "black") +
geom_text(data = max_values2, aes(x = dzientyg, y = avg_total, label = sprintf("%.2f", avg_total)), vjust = -0.8, hjust = 0.5, size = 3) +
labs(title = "Dzienne trendy sprzedaży dla klientów indywidualnych",
x = "Dni tygodnia",
y = "Średnia z total",
color = "Category") +
scale_color_manual(values = c("BEVERAGE" = "#696969", "FOOD" = "orange", "LIQUOR" = "darkgreen", "LIQUOR & TOBACCO" = "black", "MERCHANDISE" = "navy", "TOBACCO" = "red", "WINES" = "darkorchid")) +
scale_y_continuous(limits = c(0, max(daily_summary_TREND_groups0$avg_total) + 100)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 1))
W piątki napoje osiągają najwyższą średnią sprzedaż 128,84, co może wynikać z chęci relaksu klientów po tygodniu pracy. Tego samego dnia sprzedaż jedzenia wynosi 175,41, co sugeruje, że piątkowe spotkania przyciągają gości zainteresowanych zarówno napojami, jak i kulinariami.
W czwartki tytoń cieszy się zwiększonym zainteresowaniem, osiągając średnią sprzedaż na poziomie 400,66. To może być rezultat tradycji relaksu w środku tygodnia.
W kategorii alkoholi, wina są popularne w niedziele 327,48, prawdopodobnie ze względu na ich towarzyski charakter podczas niedzielnego obiadu. Alkohole notują największą średnią sprzedaż w środy 310,43, co może wynikać z tendencji do środowych spotkań towarzyskich.
Największą średnią sprzedażą w kategorii “alkohole i tytonie” charakteryzuje się sobota (766,88), co prawdopodobnie jest efektem weekendowej atmosfery, gdzie klienci korzystają z chwili relaksu.
Podsumowując, analiza trendów sprzedaży pomaga dostosować ofertę kawiarni do preferencji klientów w zależności od dnia tygodnia, tworząc unikalne doświadczenia dla każdej grupy produktowej.
Trendy dla klientów grupowych
CafePG odwiedzają również grupy tworząc interesujące trendy. Przede wszystkim widać jak chaotyczne trendy tworzą grupy.
daily_summary_TREND_groups1 <- cafe_pg %>%
filter(category != "PARTY CHARGES", groups == 1) %>%
group_by(dzientyg, category) %>%
summarise(avg_total = mean(total), num_bills = n_distinct(`bill number`))
# Find the rows with maximum values for each category
max_values3 <- daily_summary_TREND_groups1 %>%
group_by(category) %>%
filter(avg_total == max(avg_total))
ggplot(daily_summary_TREND_groups1, aes(x = dzientyg, y = avg_total, color = category, group = category)) +
geom_line(size = 1) +
geom_point(data = max_values3, aes(x = dzientyg, y = avg_total), pch = 19, size = 3, color = "black") +
geom_text(data = max_values3, aes(x = dzientyg, y = avg_total, label = sprintf("%.2f", avg_total)), vjust = -0.8, hjust = 0.5, size = 3) +
labs(title = "Dzienne trendy sprzedaży dla grup",
x = "Dni tygodnia",
y = "Średnia z total",
color = "Category") +
scale_color_manual(values = c("BEVERAGE" = "#696969", "FOOD" = "orange", "LIQUOR" = "darkgreen", "LIQUOR & TOBACCO" = "black", "MERCHANDISE" = "navy", "TOBACCO" = "red", "WINES" = "darkorchid")) +
scale_y_continuous(limits = c(0, max(daily_summary_TREND_groups1$avg_total) + 100)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 25, hjust = 1))
W piątki najpopularniejszymi produktami są napoje, alkohole i wina. Najwyższą średnią sprzedaż osiągają napoje na poziomie 1998,57, następnie alkohole 1691,66 i wina 1586,45 co może wynikać z chęci relaksu klientów po udręce tygodniu pracy. Tego samego dnia sprzedaż jedzenia jest najniższa wśród swojej kategorii. Z tego można ewidentnie wywnioskować, że piątki są dniem odpoczynku i zabawy. Jedzenie jest najbardziej popularne w niedziele ze średnią 1980. W niedzielę tytoń cieszy się zwiększonym zainteresowaniem, osiągając średnią sprzedaż na poziomie 1599,40. Gadżety wśród grup najlepiej sprzedają się w środę ze średnią wysokością 1653,75.
Wnioskowanie
Czy total sie różni w zależnosci od kategorii dla zakupów indywidualnych?
Przyjęliśmy założenie, że duża grupa to ‘total’ większy niż 1000 - na podstawie tego, że do 3 kwantyla średni zakupy są na poziomie około 300.
Obserwujemy zdecydowanie wyższą średnią sumę zakupów w kategorii LIQUOR & TOBACCO. Wszystkie zależności poza zależnością pomiędzy kategoriami LIQUOR & TOBBACCO a WINE są statystycznie istotne.
dane <- cafe_pg %>% filter(groups==0)
ggbetweenstats(
data = dane,
x = category,
y = total,
title = "Total per kategorie",
pairwise.display = "non-significant",
subtitle= "Suma rachunku dla zakupów indywidualnych"
)
Czy total sie różni w zalznosci od kategorii dla zakupów grupowych?
Średnia suma zakupów grupowych dla kategorii produktów jest dużo bardziej zbliżona, niż w przypadku zakupów indywidualnych.
dane <- cafe_pg %>% filter(total<10000 & groups==1)
ggbetweenstats(
data = dane,
x = category,
y = total,
title = "Total per kategorie",
pairwise.display = "significant",
subtitle= "Suma rachunku dla zakupów grupowych"
)
Czy rozkład kategorii różni się w zależności od godziny?
Zakupy z kategorii FOOD i BEVERAGE zaczynają się najwceśniej. Zakupy z kategorii LIQUOR i TOBACCO oraz WINE zaczynają się najpóźniej. Najpóźniej sprzedaje się artykuł z kategorii TOBACCO. Widać wyraźny wzrost zakupów Wina i Alkoholi w godzinach popołudniowych.
dane <- cafe_pg %>% filter(total<14000)
ggbetweenstats(
data = dane,
y = godzina, # musimy utworzyc zmienna godzina
x = category,
title = "Kategorie względem czasu",
pairwise.display = "significant",
theme(axis.text.x = element_text(angle = 25, hjust = 0.7))
)
Czy total się różni w zależnosci od miesiąca?
Średnie wartości zakupów w różnych miesiącach są bardzo porównywalne.
dane <- cafe_pg %>% filter(total<2000)
ggbetweenstats(
data = dane,
y = total,
x = miesiac,
pairwise.display = "none",
title = "Total względem miesięcy"
)
Podsumowanie i rekomendacje
Dogłębna analiza danych sprzedażowych CafePG wykazała, że kawiarnia bardzo dobrze prosperuje. W 2020 roku dochód całkowity wyniósł niespełna 33 mln.
Kawiarnia osiąga największy przychód ze sprzedaży wyrobów tytoniowych (około 45% ogółu przychodów), na drugim miejscu uplasowało się jedzenie, a na trzecim napoje. W celu zwiększenia sprzedaży alkoholi, na których marża może być bardzo wysoka, warto byłoby zaproponować promocję na wyrób tytoniowy + alkohol lub wino.
Najmniejszy przychód przynosi sprzedaż win oraz gadżetów. Warto przeanalizować koszty produkcji oraz magazynowania gadżetów, być może ich sprzedaż nie jest rentowna i należałoby zrezygnować z tej kategorii produktów. Warto również przeprowadzić ankietę wśród klientów w celu zrozumienia, dlaczego wina nie cieszą się dużą popularnością. Być może oferowane wina są zbyt drogie, lub typowi klienci CafePG nie lubują się w tego typu trunkach i można ograniczyć ich dostępność w celu minimalizowania kosztów.
3 najpopularniejsze produkty to Nirvana Hookah Single, Cappuccino oraz Mint Flavour Single. Największy przychód generuje sprzedaż Nirvana Hookah Single, Sambuki oraz Mint Flavour Single.
Największe zarobki osiągano w czwartki. W związku z czym, warto skorzystać z faktu, że w czwartki wizyty w CafePG są bardzo popularne. W czwartki liczba pracowników na zmianie powinna zostać zwiększona W celu maksymalizacji możliwej liczby obsłużonych klientów, co korzystnie wpłynie na przychód.
Najniższe przychody odnotowano w poniedziałki i wtorki. W celu zachęcenia klientów do odwiedzania CafePG w te dni można zorganizować w tych dniach dodatkowe atrakcje, na przykład koncerty na żywo lub pub quizy.
Około 21 godziny zaobserwowano spowolnienie ruchu klientów, to dobry moment aby wprowadzić promocje typu “happy hour” i utrzymać wyższy ruch klientów.
W sobotę i w niedzielę wzrasta sprzedaż wina, a spada sprzedaż innych alkoholi - aby podbić sprzedaż innych rodzajów alkoholi sugerujemy wprowadzenie promocji na pozostałe rodzaje alkoholi.
W sobotę spada średnia sprzedaż gadżetów, można ją wzmocnić poprzez wprowadzenie promocji wino + gadżet za 50%.
Analiza kombinacji, które klienci wybierają najczęściej wykazała, że bardzo popularne jest zamawianie BMT Panini z innym produktem kategorii FOOD oraz Sambucą. Można zatem zaproponować menu składające się z dwóch potraw i Sambuki.
Jeśli chodzi o kombinacje dwuelementowe, to najczęściej kupowanymi kombinacjami są NIRVANA HOOKAH SINGLE i POUTINE WITH FRIES. Można zatem założyć, że dobrą propozycją byłoby stworzenie zestawów składających się z dania z kategorii FOOD oraz produktu z kategorii TOBBACO.