2. Analiza brakujacych obserwacji.
Ze wstępnej analizy wynika, że zbiór danych zawiera 400 brakujących wartości.
Tabela podsumowująca braki
Powyższa tabela wskazuje rozłożenie brakujących wartości w zbiorze. Największa liczba braków dotyczy kolumn
'gross.income' oraz 'Rating', w których znajdowało się po 150 liczb NA. W kolumnie 'City' natomiast, braki stanowiły
10% wszystkich obserwacji dla tej zmiennej.
Wizualizacja lokalizacji braków

Wizualizacja prezentująca lokalizację braków w zbiorze skłania ku stwierdzeniu, że pojawiające się wartości NA
są rozmieszczone w sposób losowy, bez wyraźnych wzorców grupowania się w określonych obszarach zbioru.
Ponadto braki te stanowią 2,9% wszystkich obserwacji, co wskazuje na ich stosunkowo niewielką liczbę.
Współwystępowanie braków

W celu dokładniejszej analizy stworzono wykres UpSet, który prezentuje współwystępowanie braków między
zmiennymi. Wynika z niego, że:
- dla zmiennej 'gross.income' 116 braków (ok. 77.33%) występuje niezależnie od innych zmiennych z brakującymi
wartościami. Ponadto 20 braków współwystępuje ze zmienną 'Rating', 13 ze zmienną 'City', a 1 przypadek
braku dotyczy wszystkich trzech zmiennych jednocześnie;
- zmienna 'Rating' posiada 113 braków (ok. 75.33%) niezależnych oraz 16 przypadków współwystępujących
ze zmienną 'City';
- zmienna 'City', poza wskazanymi zależnościami, posiada 70 braków (70%), które nie występują równocześnie
w innych rekordach.
Podsumowując, w analizowanym zbiorze braki najczęściej występują osobno w poszczególnych kolumnach
(299 przypadków NA), ale istnieje określona liczba przypadków, w których braki te współwystępują w dwóch
(49 przypadków NA) lub trzech kolumnach (1 przypadek NA). Sugerować to może, że istnieje pewna zależność
między brakami w analizowanych zmiennych, jednak przez wzgląd na ich niewielką liczbę w stosunku do całkowitej
liczby braków (12.5%) – za ich występowanie może odpowiadać przypadek.
W celu zweryfikowania tej hipotezy, przeprowadza się dalszą analizę brakujących obserwacji.

Mapa występowania braków odzwierciedla wskazane przez wykres UpSet zależności. Dodatkowo odczytać z niej
można, że w 651 wierszach w zbiorze nie występują żadne braki. W pozostałych 349 rekordach pojawiają się
pojedyncze, podwójne oraz potrójne wartości NA, co zostało wykazane powyżej.
Macierz korelacji braków
Aby sprawdzić zależności pomiędzy brakującymi obserwacjami a wartościami pozostałych zmiennych, sporządza
się macierz korelacji braków.
W macierzy korelacji braków kolumny i wiersze reprezentują zmienne ze zbioru, a wartości w macierzy
odpowiadają współczynnikom korelacji między wskaźnikami braków (zmiennymi binarnymi oznaczającymi
obecność braków) lub między wskaźnikami braków a wartościami innych zmiennych. Na jej podstawie można
określić, czy wartości brakujące pojawiają się losowo (MCAR, Missing Completely at Random),
czy w przypadku silnych korelacji ich występowanie zależy od innych zmiennych (MAR, Missing at Random).
W celu jej utworzenia, wyróżnia się następujące etapy:
I. Sprawdzenie struktury danych w zbiorze.
II. Przekodwoanie wskazanych zmiennych jakościowych na ilościowe.
III. Obliczenie korelacji między brakami a zmiennymi ze zbioru.
IV. Wygenerowanie macierzy korelacji braków.
Etap I. Sprawdzenie struktury danych w zbiorze.
Tabela prezentuje strukturę zmiennych w zbiorze. Ich analiza jest konieczna, aby móc dokonać przekształceń
zmiennych jakościowych (character) na zmienne ilościowe (numeric, integer) i przejść do etapu obliczania korelacji
między brakami a zmiennymi. Wybrane zmienne do przekodowania to:
- 'Ivioice.ID'
- 'Branch'
- 'City'
- 'Customer.type'
- 'Gender'
- 'Product.line'
- 'Date'
- 'Time'
- 'Payment'.
Etap II. Przekodwoanie wskazanych zmiennych jakościowych na
ilościowe.
data2 <- data.frame(data, row.names = TRUE)
data2$Branch <- ifelse((data2$Branch) == "A", 1,
ifelse(data2$Branch == "B", 2, 0))
data2$City <- ifelse(is.na(data2$City), NA, ifelse(data2$City == "Naypyitaw", 1,
ifelse(data2$City == "Mandalay", 2, 0)))
data2$Customer.type <- ifelse((data2$Customer.type) == "Member", 1, 0)
data2$Gender <- ifelse((data2$Gender) == "Male", 1, 0)
data2$Product.line <- ifelse(data2$Product.line == "Electronic accessories", 1,
ifelse(data2$Product.line == "Fashion accessories", 2,
ifelse(data2$Product.line == "Food and beverage", 3,
ifelse(data2$Product.line == "Health and beauty", 4,
ifelse(data2$Product.line == "Sports and travel", 5, 0)))))
data2$Payment <- ifelse(data2$Payment == "Cash", 1,
ifelse(data2$Payment == "Credit card", 2, 0))
data2$Date <- as.Date(data2$Date, format = "%m/%d/%Y")
data2 <- data2 %>%
mutate(Date = month(Date))
data2$Time <- as.numeric(sub(":(\\d{2}):.*", ".\\1", data2$Time))
Na etapie przekodowania zmiennych, dokonano przekształcenia:
- na zmienne binarne (0,1): 'Customer.type' oraz 'Gender';
- na zmienne wielokategorialne (w zakresie 0-5): 'Branch' (0,1,2), 'City' (0,1,2), 'Product.line' (0,1,2,3,4,5)
i 'Payment' (0,1,2).
Ponadto przypisano zmiennej określającej datę zakupu towaru ('Date') odpowiadające jej numery miesiąca (1,2,3),
w celu wydobycia z niej możliwie istotnych informacji (np. konkretny wzorzec występowania braków) oraz przypisano
zmienną 'Invoice.ID' do nazw wierszy, przez wzgląd na jej niewielką wartość informacyjną.
Etap III. Obliczenie korelacji między brakami a zmiennymi ze
zbioru.
Po utowrzeniu zmiennej binarnej (0,1) reprezentującej wskaźnik braków, gdzie 1 oznacza brak wartości,
a 0 - jej obecność, obliczono wartość korelacji między danymi wskaźnikami oraz wskaźnikami i wartościami
innych zmiennych.
data_cor <- data2 %>% mutate(gross.margin.percentage = NULL)
NA_cor2 <- cor_mat(data_cor)
Dla 'gross.margin.percentage' korelacja nie mogła zostać policzona, ze względu na powtarzające sie wartości tej
zmiennej w każdym kolejnym wierszu, wynikiem czego korelacja skutkowała nieprawidłową wartością NA. Z tego
względu zmienna ta została wykluczona z analizy korelacji, w celach dalszej wizualizacji korelacji braków.
Etap IV. Wygenerowanie macierzy korelacji braków.

Macierz korelacji braków przedstawiona na wizualizacji wskazuje na istnienie bardzo silnej, dodatniej korelacji między
wartościami brakującymi a wartościami zmiennych: 'Total', 'Tax.5.', 'cogs' oraz 'gross.income' i silnej, dodatniej korelacji
wartości zmiennych: 'cogs', 'Unit.price', 'Quantity' i 'gross.income'. Ponadto zaobserwowano istotną korelację
dodatnią dla zmiennych 'Branch' i 'City'.
Wyniki te oznaczają, że jeśli jedna ze wskazanych zmiennych posiada brakującą wartość, istnieje duże
prawdopodobieństwo, że pozostałe zmienne również będą zawierać brakujące obserwacje.
To z kolei sugeruje, że w przypadku zmiennych o charakterze finansowym, takie braki mogą być losowe (MAR),
zależne od innych wartości, lub jeśli wartości były celowo pomijane - nielosowe (NMAR), niezależne od pozostałych
zmiennych.
Natomiast w przypadku zmiennych dotyczących lokalizacji sklepów, bardziej prawdopodobne jest, że braki
w zmiennej 'City' mają charakter losowy (MAR). Wynika to z faktu, że konkretna lokalizacja jest powiązana
z danym oddziałem sklepu ('Branch'), więc brak informacji o mieście wynikać może z wcześniej podanej informacji
o oddziale.
Dodatkowo, braki w zmiennej 'Rating' nie wykazują żadnych zależności z innymi wartościami zmiennych. Na tej
podstawie można przypuszczać, że są to braki typu MCAR i zasadnym jest zastosowanie prostej imputacji danych.
Sprawdzenie zależności występowania braków w zmiennej
‘gross.income’
W celu sprawdzenia mechanizmu występowania wartości brakujących w zmiennej 'gross.income' oraz dobrania
do niej odpowiedniej formy imputacji, należy dokonać analizy wykazanych zależności z wartościami zmiennych
'Total', 'Tax.5.', 'cogs' oraz 'Quantity' i 'Unit.price'.
Występowanie korelacji pomiędzy wymienionymi zmiennymi można wyjaśnić w prosty sposób, biorąc pod uwagę
definicję wskazanych zmiennych i ich odzwiercielenie faktycznych wartości finansowych.
Analiza wartości tych zmiennych wykazuje, że:
- zmienna 'cogs' mówiąca o koszcie wytworzenia sprzedanych towarów jest równa przychodowi ze sprzedaży, a co
za tym idzie - iloczynowi ilości sprzedanych produktów ('Quantity') i kosztowi jednostkowemu produktu ('Unit.price'):
'cogs' = 'Quantity' * 'Unit.price';
- zmienna 'Tax.5.' mówiąca o opłacie podatkowej od sprzedaży w wysokości 5% jest równa iloczynowi kosztu
sprzedanych towarów ('cogs') i 5% podatku:
'Tax.5. = 'cogs' * 5%;
- zmienna 'Total' mówiąca o całkowitej kwocie do zapłaty przez klienta za pojedynczą fakturę, z uwzglenieniem
podatku jest równa sumie kosztów sprzedanych towarów ('cogs') i opłacie podatkowej w wysokości 5% ('Tax.5.'):
'Total' = 'cogs' + 'Tax.5.';
- zmienna 'gross.income' mówiąca o dochodzie brutto (zysku) za sprzedane towary, która w rzeczywistości
odzwierciedla różnicę przychodów ze sprzedaży i kosztu sprzedanych produktów, w zbiorze danych jest
równowartością różnicy całkowitej kwoty do zapłaty z podatkiem ('Total') i kosztów wytworzenia sprzedanych
produktów ('cogs'):
'gross.income' = 'Total' - 'cogs'
Jeśli zatem 'Total' = 'cogs' + 'Tax.5.', to 'gross.income' = ('cogs' + 'Tax.5.') - 'cogs' = 'Tax.5.'.
Tę zależność potwierdza poniższa wizualziacja.

Histogram przedstawia porównanie rozkładów zmiennych 'gross.income' oraz 'Tax.5.'. Obie zmienne są nałożone
na siebie, w celu umożliwienia bezpośredniego porównania ich kształtu i rozkładu. Ze zbioru obserwacji zmiennej
'gross.income' wykluczono 150 obserwacji brakujących, co nieznacznie zaniża jej rozkład. Zauważyć jednak można,
że dla obu zmiennych, wartości obserwacji skupiają sie w zakresie 0-25, czyniąc je prawostronnie skośnymi.
Ponadto obserwowalna jest zależność, w której częstość występowania danych wartości dla obu zmiennych
odzwierciedla niemalże identyczny kształt rozkładu, z wysokimi i niskimi częstościami w tych samych przedziałach.
W związku z powyższą analizą dotyczącą zależności między brakami zmiennej 'gross.inocme' a zmiennymi 'Total',
'Tax.5.' oraz 'cogs' można wyciągnąć wniosek, że związek wartości 'gross.income' z wartościami pozostałych
zmiennych wynika z finansowych powiązań między nimi. Dodatkowo, można przyjąć, że wartości zmiennej
'gross.income' odpowiadają wartościom zmiennej 'Tax.5.' i zasadnym jest zastosowanie imputacji poprzez
zastąpienie wartości brakujących obserwacjami pełnowartościowej zmiennej.
Sprawdzenie zależności występowania braków w ‘City’ od zmiennej
‘Branch’

Aby lepiej zrozumieć zależność między wartościami brakujacymi w zmiennej 'City' a wartościami zmiennej 'Branch'
sporządzono powyższy wykres słupkowy. Wskazuje on, że braki w każdym z oddziałów ('Branch') są rozłożone
równomiernie (wynoszą ok. 3.5%), z niewielkimi odchyleniami (ok. 0.47 p. %). Może to świadczyć o tym, że braki
te nie są zależne od konkretnych oddziałów.
Wynik testu chi-kwadrat
|
|
Statistic
|
p_value
|
df
|
|
X-squared
|
1.54
|
0.46
|
2
|
W ramach sprawdzenia zależności braków zmiennej 'City' od zmiennej 'Branch' wykonano nieparametryczny test
zależności chi2. Hipotezy dla tesu brzmią następująco:
H0: Braki w zmiennej 'City' są niezależne od zmiennej 'Branch'.
HA: Braki w zmiennej 'City' są zależne od zmiennej 'Branch'.
Statystyka chi2 równa 1,54 przy wartości p-value (0,46) większej od przyjętego poziomu istotności (0,05) wykazała,
że nie ma podstaw do odrzucenia H0 mówiącego o niezależności braków obserwacji zmiennej 'City' od wartości
zmiennej 'Branch'.
Wobec tego, można wskazać, że braki występujące w zmiennej 'City' nie mają statystycznie istotnej zależności
i można zastosować dla nich prostą imputację danych.
PODSUMOWANIE ANALIZY BRAKUJĄCYCH OBSERWACJI
Z powyższej analizy dotyczącej obserwacji brakujących w zbiorze danych dotyczącym sprzedaży w trzech sklepach
Biedronka wynika, że wartości NA występują w trzech zmiennych: 'gross.income' (150 przypadków braków), 'Rating'
(150 przypadków braków) oraz 'City' (100 przypadków braków).
Przedstawione wizualizacje oraz testy wykazały, że braki te najprawdopodobniej są losowe (MAR) lub kompletnie
losowe (MCAR) w przypadku zmiennej finansowej 'gross.income' oraz zmiennej dotyczącej lokalzacji 'City', i kompletnie
losowe (MCAR) w przypadku zmiennej 'Rating'.
W zwiazku z tym, zaleca się stosowanie prostej imputacji danych polegającej na uzupełnieniu brakujących wartości
w zmiennej 'gross.income' wartościami ze zmiennej 'Tax.5.', przypisaniu brakującym wartościom zmiennej 'City'
odpowieniej nazwy miasta w oparciu o oddział 'Branch', jaki jest mu przypisany oraz zastosowaniu np. średniej
lub mediany w uzupełnieniu zmiennej 'Rating', bądź uzupełnianiu jej poprzez wielokrotną imputację, przy pomocy
pakietu "mice" (Multiple Imputation by Chained Equations).
3. Walidacja danych.
W celu sprawdzenia, czy wartości w zbiorze danych spełniają określone krytera dla zmiennych, których poprawne
zachowanie jest niezbędne do dalszej analizy obejmującej m.in. imputację, wizualizację, wnioskowanie statatystyczne
i testowanie, stosuje się walidację danych.
Proces ten polega na definiowaniu reguł, jakie muszą spełnić zmienne w zbiorze, a następnie sprawdzenie, czy
występują w nim jakiekolwiek nieprawidłowości w postaci "brudnych" danych. Jeżeli analiza wykaże obecność takich
wartości, kolejnym etapem jest "czyszczenie" zbioru. Może to obejmować poprawę danych (np. dopasowanie
do prawidłowego formatu) lub usunięcie informacji, które są nieistotne dla badania, a mogą zakłócać działanie
programu i proces dalszej analizy.
Sprawdzanie poprawności danych zależnych
Dla analizowanego zbioru danych zdefiniowano reguły walidacyjne, dla wybranych zmiennych zależnych
jakościowych i ilościowych, których nieprawidłowości mogłyby mieć istotny wpływ na dalszą analizę.
Określone reguły przedstawia się następująco:

Powyższa wizualizacja wskazuje, że w analizowanym zbiorze danych nie występują nieprawidłowości w postaci
"brudnych" wartości w zmiennych zależnych o określonych regułach.
Sprawdzenie poprawności zmiennych kategorycznych
Ponadto można stweirdzić, że zbiór ten nie posiada również nieprawidłowości w postaci m.in. literówek
w wartościach zmiennych kategorycznych.
Sprawdzenie występowania duplikatów rekordów
W zbiorze tym nie występują również duplikaty wierszów.
PODSUMOWANIE WALIDACJI DANYCH
Z powyższej analizy dotyczącej identyfikacji nieprawidłowości w zbiorze danych dotyczącym sprzedaży w trzech
sklepach Biedronka wynika, że wartości zmiennych są poprawne i nie wymagają poddania procesowi czyszczenia
danych (Data Cleansing).
4. Czyszczenie danych z brakujacych obserwacji.
Poniższy kod uzupełnia brakujące wartości w kolumnach, wykorzystując zależności między zmiennymi i proces
imputacji.
Wobec tego:
- kolumna 'City' została uzupełniona na podstawie jednoznacznej relacji z kolumną 'Branch';
- braki w kolumnie 'gross.income' zastąpiono wartościami z kolumny 'Tax.5.', ponieważ dane te były tożsame;
- braki w kolumnie 'Rating' uzupełniono za pomocą imputacji z pakietu "mice", wykorzystując metodę dopasowania
predyktywnego ("pmm").
# Mapowanie relacji między 'Branch' a 'City'
branch_to_city <- data %>%
filter(!is.na(City)) %>%
distinct(Branch, City) %>%
group_by(Branch) %>%
summarize(City = first(City))
# Łączenie danych, aby wypełnić brakujące wartości w kolumnie 'City'
data <- data %>%
left_join(branch_to_city, by = "Branch", suffix = c("", ".y")) %>%
mutate(City = ifelse(is.na(City), City.y, City)) %>%
select(-City.y)
# Sprawdzanie liczby brakujących wartości w kolumnie 'City'
sum(is.na(data$City))
## [1] 0
# Sprawdzanie dostępnych kolumn
colnames(data)
## [1] "Invoice.ID" "Branch"
## [3] "City" "Customer.type"
## [5] "Gender" "Product.line"
## [7] "Unit.price" "Quantity"
## [9] "Tax.5." "Total"
## [11] "Date" "Time"
## [13] "Payment" "cogs"
## [15] "gross.margin.percentage" "gross.income"
## [17] "Rating"
# Zastępowanie brakujących wartości w kolumnie 'gross.income' wartością z kolumny 9
data <- data %>%
mutate(`gross.income` = ifelse(is.na(`gross.income`), data[[9]], `gross.income`))
# Sprawdzanie liczby brakujących wartości w kolumnie 'gross income'
sum(is.na(data$`gross.income`))
## [1] 0
# Imputacja brakujących wartości w zmiennej 'Rating' za pomocą pakietu 'mice'
imputed_data <- mice(data, m = 1, method = "pmm", maxit = 50, seed = 123)
##
## iter imp variable
## 1 1 Rating
## 2 1 Rating
## 3 1 Rating
## 4 1 Rating
## 5 1 Rating
## 6 1 Rating
## 7 1 Rating
## 8 1 Rating
## 9 1 Rating
## 10 1 Rating
## 11 1 Rating
## 12 1 Rating
## 13 1 Rating
## 14 1 Rating
## 15 1 Rating
## 16 1 Rating
## 17 1 Rating
## 18 1 Rating
## 19 1 Rating
## 20 1 Rating
## 21 1 Rating
## 22 1 Rating
## 23 1 Rating
## 24 1 Rating
## 25 1 Rating
## 26 1 Rating
## 27 1 Rating
## 28 1 Rating
## 29 1 Rating
## 30 1 Rating
## 31 1 Rating
## 32 1 Rating
## 33 1 Rating
## 34 1 Rating
## 35 1 Rating
## 36 1 Rating
## 37 1 Rating
## 38 1 Rating
## 39 1 Rating
## 40 1 Rating
## 41 1 Rating
## 42 1 Rating
## 43 1 Rating
## 44 1 Rating
## 45 1 Rating
## 46 1 Rating
## 47 1 Rating
## 48 1 Rating
## 49 1 Rating
## 50 1 Rating
# Wybór ukończonego zestawu danych
data <- complete(imputed_data, 1)
# Sprawdzanie liczby brakujących wartości w całym zbiorze danych po imputacji
sum(is.na(data))
## [1] 0
5. Wartości Odstające.
Wartości odstające to obserwacje znacząco odbiegające od reszty danych, które mogą zniekształcać wyniki
analiz statystycznych. Aby zminimalizować ich wpływ, przeprowadzono analizę zmiennych 'Unit.price', 'Total',
'Quantity' i 'Rating'.
# Rysowanie boxplotów dla wybranych zmiennych
b1 <- ggplot(data, aes(y = Unit.price)) +
geom_boxplot() +
labs(title = "Boxplot: Unit Price") +
theme_minimal()
b2 <- ggplot(data, aes(y = Total)) +
geom_boxplot() +
labs(title = "Boxplot: Total") +
theme_minimal()
# Rysowanie histogramów dla wybranych zmiennych
h1 <- ggplot(data, aes(x = Unit.price)) +
geom_histogram(bins = 30, fill = "#0c4c8a") +
labs(title = "Histogram: Unit Price", x = "Unit Price", y = "Frequency") +
theme_minimal()
h2 <- ggplot(data, aes(x = Total)) +
geom_histogram(bins = 30, fill = "#0c4c8a") +
labs(title = "Histogram: Total", x = "Total", y = "Frequency") +
theme_minimal()
# Wyświetlenie wykresów w siatce 2x2
grid.arrange(b1, b2, h1, h2, nrow = 2)

replace_outliers_with_median <- function(column) {
Q1 <- quantile(column, 0.25, na.rm = TRUE)
Q3 <- quantile(column, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
column[column < lower_bound | column > upper_bound] <- median(column, na.rm = TRUE)
return(column)
}
W przypadku analizowanych zmiennych 'Unit.price' i 'Total' zaobserwowano obecność wartości odstających.
Dla zmiennej 'Unit.price' mediana wynosi około 55 dolarów, natomiast wartości maksymalne przekraczają 100
dolarów, co wskazuje na obecność wyjątkowo wysokich wartości, które znacznie przewyższają typowy zakres cen
jednostkowych produktów.
Dla zmiennej 'Total' mediana oscyluje w granicach 250 dolarów, podczas gdy wartość maksymalna wynosi ponad
1000 dolarów. Tak duże różnice sugerują, że pewne transakcje znacząco odbiegają od typowego poziomu całkowitych
kwot zakupów.
Obecność takich wartości odstających może mieć istotny wpływ na wyniki analiz statystycznych, szczególnie
w przypadku miar wrażliwych na ekstremalne wartości, takich jak średnia arytmetyczna. Aby zminimalizować ich
wpływ i poprawić jakość dalszej analizy danych, wartości odstające zostały zastąpione medianą zmiennych.
Działanie to pozwala na bardziej reprezentatywną ocenę danych, co może mieć kluczowe znaczenie w kontekście
analizy zachowań klientów, segmentacji rynku lub przewidywania przyszłych trendów sprzedażowych.
Wyświetlanie wartości odstających dla zmiennej ‘Total’
## [1] 167 168 351 358 423 558 700 793 997
Wartości odstające zostały zastąpione poprzez medianę wartości zmiennej.
PODSUMOWANIE ANALIZY WARTOŚCI ODSTAJĄCYCH
Zastąpienie wartości odstających w danych pozwala na uzyskanie bardziej reprezentatywnych wyników, eliminując
wpływ skrajnych wartości, które mogą zniekształcać analizy. Dzięki temu modelowanie i wnioskowanie staje się
bardziej precyzyjne, a interpretacja danych jest łatwiejsza i bardziej wiarygodna. Takie podejście pomaga lepiej
uchwycić rzeczywiste zależności w analizowanej próbie.
6. Statystyki opisowe.
statystyki <- function(x) {
data.frame(
"Min" = min(x, na.rm = TRUE),
"Max" = max(x, na.rm = TRUE),
"Kwartyl dolny" = quantile(x, 0.25, na.rm = TRUE),
"Mediana" = round(median(x, na.rm = TRUE), 2),
"Kwartyl górny" = quantile(x, 0.75, na.rm = TRUE),
"Średnia" = round(mean(x, na.rm = TRUE), 2),
"Odch. std." = round(sd(x, na.rm = TRUE), 2),
"IQR" = round(IQR(x, na.rm = TRUE), 2),
"Odchylenie ćwiartkowe" = round(IQR(x, na.rm = TRUE) / 2, 2),
"Odch. std. w %" = round((sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE)) * 100, 2),
"Odch. ćwiartkowe w %" = round((IQR(x, na.rm = TRUE) / median(x, na.rm = TRUE)) * 100, 2),
"Skośność" = round(skewness(x, na.rm = TRUE), 2),
"Kurtoza" = round(kurtosis(x, na.rm = TRUE), 2)
)
}
Statystyki dla zmiennej ‘Total’ według płci (‘Gender’)
# Obliczenie statystyk
statystyki_total <- data %>%
group_by(Gender) %>%
summarise(across(Total, statystyki)) %>%
unnest(cols = c(Total))
# Przekształcenie danych na format długi
tabela_total <- statystyki_total %>%
pivot_longer(cols = -Gender, names_to = "Statystyka", values_to = "Wartość") %>%
pivot_wider(names_from = Gender, values_from = Wartość)
# Wyświetlenie tabel
knitr::kable(tabela_total,
digits = 2,
align = "lcc",
caption = "Tabela 1. Statystyki dla 'Total' wg płci.",
col.names = c("Statystyka", "Kobiety", "Mężczyźni"))
Tabela 1. Statystyki dla ‘Total’ wg płci.
| Min |
12.69 |
10.68 |
| Max |
951.82 |
950.25 |
| Kwartyl.dolny |
132.76 |
117.95 |
| Mediana |
264.76 |
244.23 |
| Kwartyl.górny |
478.23 |
453.18 |
| Średnia |
325.87 |
306.17 |
| Odch..std. |
237.61 |
235.63 |
| IQR |
345.47 |
335.23 |
| Odchylenie.ćwiartkowe |
172.74 |
167.62 |
| Odch..std..w.. |
72.91 |
76.96 |
| Odch..ćwiartkowe.w.. |
130.49 |
137.26 |
| Skośność |
0.78 |
0.93 |
| Kurtoza |
2.66 |
2.95 |
Tabela przedstawia statystyki zmiennej 'Total' dla kobiet i mężczyzn.
Na jej podstawie stwierdzić można, że:
- Wartości minimalne i maksymalne są podobne w obu grupach, co sugeruje zbliżony zakres danych.
- Mediana i kwartyle pokazują, że kobiety osiągają nieco wyższe wartości 'Total' niż mężczyźni
(mediana: 272,58 vs. 244,23). Podobny trend widać w średniej, co oznacza, że ogólnie wartości
zmiennej 'Total' są wyższe dla kobiet.
- Zmienność wyników w obu grupach jest porównywalna – wskazują na to zbliżone wartości odchylenia
standardowego i rozstępu międzykwartylowego (IQR).
- Skośność dodatnia (0,83 dla kobiet, 0,96 dla mężczyzn) oznacza, że rozkłady są asymetryczne
w prawo – większość wartości jest niższa, ale pojawiają się pojedyncze wysokie obserwacje.
- Kurtoza (2,81 dla kobiet, 3,04 dla mężczyzn) sugeruje, że rozkłady mają umiarkowanie grubsze
ogony niż rozkład normalny.
Statystyki dla ‘gross.income’ według płci (‘Gender’)
# Obliczenie statystyk
statystyki_income <- data %>%
group_by(Gender) %>%
summarise(across(gross.income, statystyki)) %>%
unnest(cols = c(gross.income))
# Przekształcenie danych na format długi
tabela_income <- statystyki_income %>%
pivot_longer(cols = -Gender, names_to = "Statystyka", values_to = "Wartość") %>%
pivot_wider(names_from = Gender, values_from = Wartość)
# Wyświetlenie tabel
knitr::kable(tabela_income,
digits = 2,
align = "lcc",
caption = "Tabela 2. Statystyki dla 'gross.income' wg płci.",
col.names = c("Statystyka", "Kobiety", "Mężczyźni"))
Tabela 2. Statystyki dla ‘gross.income’ wg płci.
| Min |
0.60 |
0.51 |
| Max |
49.65 |
49.49 |
| Kwartyl.dolny |
6.32 |
5.62 |
| Mediana |
12.98 |
11.63 |
| Kwartyl.górny |
23.16 |
21.75 |
| Średnia |
15.96 |
14.80 |
| Odch..std. |
11.87 |
11.52 |
| IQR |
16.84 |
16.14 |
| Odchylenie.ćwiartkowe |
8.42 |
8.07 |
| Odch..std..w.. |
74.40 |
77.87 |
| Odch..ćwiartkowe.w.. |
129.75 |
138.76 |
| Skośność |
0.83 |
0.96 |
| Kurtoza |
2.81 |
3.04 |
Tabela przedstawia statystyki dotyczące gross.income w podziale na płeć.
Na jej podstawie stwierdzić można, że:
- Mediana oraz kwartyle pokazują, że kobiety osiągają nieco wyższe wartości Gross Income niż
mężczyźni (mediana: 13,57 vs. 11,22), co znajduje odzwierciedlenie również w średniej (16,03
vs. 14,83).
- Zmienność w obu grupach jest porównywalna – świadczą o tym podobne wartości odchylenia
standardowego oraz rozstępu międzykwartylowego (IQR).
- Dodatnia skośność (0,83 dla kobiet, 0,96 dla mężczyzn) sugeruje, że w obu przypadkach rozkład
jest asymetryczny w prawo, czyli większość wartości jest stosunkowo niska, ale pojawiają się
pojedyncze wysokie obserwacje.
- Kurtoza (2,90 dla kobiet, 3,03 dla mężczyzn) wskazuje, że rozkład ma nieco grubsze ogony niż
rozkład normalny, co oznacza większą liczbę wartości skrajnych.
Statystyki dla ‘Rating’ według typu klienta (‘Customer.type’)
# Obliczenie statystyk
statystyki_rating <- data %>%
group_by(Customer.type) %>%
summarise(across(Rating, statystyki)) %>%
unnest(cols = c(Rating))
# Przekształcenie danych na format długi
tabela_rating <- statystyki_rating %>%
pivot_longer(cols = -Customer.type, names_to = "Statystyka", values_to = "Wartość") %>%
pivot_wider(names_from = Customer.type, values_from = Wartość)
# Wyświetlenie tabel
knitr::kable(tabela_rating,
digits = 2,
align = "lcc",
caption = "Tabela 3. Statystyki dla 'Rating' wg typu klienta.",
col.names = c("Statystyka", "Normal", "Member"))
Tabela 3. Statystyki dla ‘Rating’ wg typu klienta.
| Min |
4.00 |
4.00 |
| Max |
10.00 |
10.00 |
| Kwartyl.dolny |
5.40 |
5.60 |
| Mediana |
6.90 |
7.00 |
| Kwartyl.górny |
8.40 |
8.40 |
| Średnia |
6.90 |
6.99 |
| Odch..std. |
1.73 |
1.69 |
| IQR |
3.00 |
2.80 |
| Odchylenie.ćwiartkowe |
1.50 |
1.40 |
| Odch..std..w.. |
25.01 |
24.12 |
| Odch..ćwiartkowe.w.. |
43.48 |
40.00 |
| Skośność |
0.03 |
0.00 |
| Kurtoza |
1.85 |
1.88 |
Tabela przedstawia statystyki dotyczące ocen ('Rating') wystawianych przez klientów w podziale
na typ (Normal i Member).
Na jej podstawie stwierdzić można, że:
- Zakres ocen w obu grupach jest identyczny (od 4,00 do 10,00). Mediana i kwartyle wskazują, że
członkowie programu lojalnościowego (Member) wystawiają nieco wyższe oceny niż klienci zwykli
(Normal), choć różnice są niewielkie (mediana: 7,10 vs. 7,00). Średnia również jest
minimalnie wyższa dla członków (7,05 vs. 6,97).
- Rozkłady ocen w obu grupach są bardzo podobne – zarówno odchylenie standardowe, jak i rozstęp
międzykwartylowy (IQR) mają zbliżone wartości. Skośność bliska zeru (-0,01 dla Normal, -0,02
dla Member) oznacza, że rozkłady są niemal symetryczne.
- Kurtoza (1,84 dla Normal, 1,83 dla Member) wskazuje na spłaszczony kształt rozkładu w
porównaniu do rozkładu normalnego, co oznacza mniejszą liczbę skrajnych ocen.
Statystyk dla ‘Unit.price’ według kategorii produktów
(‘Product.line’)
# Obliczenie statystyk
statystyki_unit_price <- data %>%
group_by(Product.line) %>%
summarise(across(Unit.price, statystyki)) %>%
unnest(cols = c(Unit.price))
# Przekształcenie danych na format długi
tabela_unit_price <- statystyki_unit_price %>%
pivot_longer(cols = -Product.line, names_to = "Statystyka", values_to = "Wartość") %>%
pivot_wider(names_from = Product.line, values_from = Wartość)
# Wyświetlenie tabel
knitr::kable(tabela_unit_price,
digits = 2,
align = "lcc",
caption = "Tabela 4. Statystyki dla 'Unit Price' wg kategorii produktów.",
col.names = c("Statystyka", unique(data$Product.line)))
Tabela 4. Statystyki dla ‘Unit Price’ wg kategorii
produktów.
| Min |
10.56 |
10.18 |
10.13 |
10.08 |
10.53 |
10.17 |
| Max |
99.73 |
99.89 |
99.79 |
99.96 |
99.92 |
99.96 |
| Kwartyl.dolny |
27.98 |
35.52 |
33.47 |
32.42 |
34.31 |
34.42 |
| Mediana |
51.50 |
55.09 |
54.00 |
57.41 |
55.59 |
58.65 |
| Kwartyl.górny |
75.90 |
81.10 |
78.74 |
76.13 |
77.52 |
80.68 |
| Średnia |
53.55 |
57.15 |
56.01 |
54.85 |
55.32 |
56.99 |
| Odch..std. |
26.75 |
26.67 |
26.27 |
26.35 |
26.21 |
26.91 |
| IQR |
47.92 |
45.58 |
45.27 |
43.71 |
43.21 |
46.26 |
| Odchylenie.ćwiartkowe |
23.96 |
22.79 |
22.63 |
21.85 |
21.61 |
23.13 |
| Odch..std..w.. |
49.95 |
46.66 |
46.90 |
48.04 |
47.38 |
47.21 |
| Odch..ćwiartkowe.w.. |
93.04 |
82.74 |
83.84 |
76.14 |
77.73 |
78.88 |
| Skośność |
0.10 |
0.01 |
0.06 |
-0.07 |
-0.01 |
-0.06 |
| Kurtoza |
1.70 |
1.81 |
1.81 |
1.85 |
1.80 |
1.72 |
Tabela przedstawia statystyki dotyczące Unit Price (ceny jednostkowej) w podziale na
kategorie produktów.
Na jej podstawie stwierdzić można, że:
- Wszystkie kategorie mają podobny zakres cen – wartości minimalne wahają
się od 10,08 (Sports and travel) do 10,56 (Health and beauty), natomiast maksymalne ceny są
bardzo zbliżone i mieszczą się w przedziale 99,73–99,96.
- Mediana ceny jednostkowej jest najwyższa dla Fashion accessories (58,65) oraz Sports and
travel (57,41), a najniższa dla Home and lifestyle (54,00). Średnie wartości są również do
siebie zbliżone, ale najwyższą średnią cenę mają Electronic accessories (57,15), a najniższą
Sports and travel (54,85) oraz Food and beverages (55,32).
- Odchylenie standardowe we wszystkich grupach jest bardzo podobne – waha się od 26,21 (Food
and beverages) do 26,91 (Fashion accessories), co wskazuje na zbliżoną zmienność cen w każdej
kategorii. Rozstęp międzykwartylowy (IQR) również pokazuje, że ceny w poszczególnych
kategoriach nie różnią się znacznie pod względem rozproszenia – najwyższy IQR ma Health and
beauty (47,92), a najniższy Food and beverages (43,21).
- Skośność we wszystkich przypadkach jest bliska zeru, co oznacza, że rozkłady cen są
symetryczne – nie występuje wyraźne przesunięcie w stronę niższych lub wyższych wartości.
- Kurtoza we wszystkich kategoriach mieści się w przedziale 1,70–1,85, co oznacza, że rozkłady
cen są lekko spłaszczone w porównaniu do rozkładu normalnego. Wskazuje to na mniejszą liczbę
wartości skrajnych, czyli rzadziej występujące wyjątkowo niskie lub wysokie ceny.
7. Wykresy.
Wykres kołowy
Wykres kołowy prezentuje preferencje metody płatności wezględu na płeć. Wynika z niego, że mężczyźni wolą
płacić karta debetową, kobiety natomiast preferują płatności gotówką.
Histogram i wykres pudełkowy
Histogram przedstawia rozkład ocen w poszczególnych miastach, pokazując, jak często występują określone
wartości ocen. Dzięki niemu możemy łatwo zauważyć ogólny kształt rozkładu, jego skośność oraz ewentualne
wartości odstające.
Z kolei wykres pudełkowy (boxplot) pozwala lepiej zobaczyć rozkład danych pod kątem ich mediany, kwartylów
oraz wartości odstających. Środkowa linia w pudełku reprezentuje medianę ocen, a granice pudełka pokazują
zakres między pierwszym a trzecim kwartylem. Wąsy wskazują wartości minimalne i maksymalne, pomijając
odstające obserwacje, które są zaznaczone jako osobne punkty. Wykres pudełkowy ułatwia szybkie porównanie
mediany ocen między różnymi miastami oraz identyfikację ewentualnych różnic w rozproszeniu danych.
# Tworzenie histogramu
# Wyświetlenie wykresów obok siebie
grid.arrange(plot_female, plot_male, ncol = 2)

# Oddzielne histogramy dla każdego miasta
ggplot(data, aes(x = Rating)) +
geom_histogram(bins = 30, fill = "#69b3a2", color = "black", alpha = 0.8) +
facet_wrap(~ City, scales = "free_y") + # Oddzielne panele dla każdego miasta
labs(
title = "Rozkład ocen (Rating) w zależności od miasta",
x = "Ocena (Rating)",
y = "Liczba obserwacji"
) +
theme_minimal() +
theme(
strip.text = element_text(size = 12, face = "bold"), # Wyraźne etykiety miast
axis.text = element_text(size = 10),
axis.title = element_text(size = 12)
)

# Rozkład dla oceny
ggplot(data, aes(x = City, y = Rating, fill = City)) +
geom_boxplot(alpha = 0.8) +
labs(
title = "Porównanie ocen (Rating) w zależności od miasta",
x = "Miasto",
y = "Ocena (Rating)",
fill = "Miasto"
) +
theme_minimal() +
scale_fill_brewer(palette = "Pastel1")

Wykres słupkowy
Wykres słupkowy przedstawia średnią sprzedaż dla każdej linii produktów, co pozwala na szybkie porównanie
wyników poszczególnych kategorii. Słupki mają kolor niebieski, a ich wysokość odpowiada wartości średniej
sprzedaży w danej linii produktów.
# Tworzenie wykresu słupkowego
# Obliczanie średniej sprzedaży dla każdej linii produktów
average_sales <- aggregate(Total ~ Product.line, data = data, mean)
# Zwiększenie marginesów dla większej przestrzeni na etykiety
par(mar = c(8, 4, 4, 2) + 0.1)
# Tworzenie wykresu słupkowego z bardziej czytelnymi etykietami
barplot(
average_sales$Total,
names.arg = average_sales$Product.line,
col = "lightblue", # Kolor słupków
main = "Średnia sprzedaż według linii produktów",
xlab = "", # Usuń opis osi X, aby nie dublować etykiet
ylab = "Średnia sprzedaż",
las = 2, # Pionowe etykiety osi X
cex.names = 0.6 # Zmniejszenie rozmiaru tekstu etykiet
)
# Dodanie opisu osi X poniżej wykresu
mtext("Linia produktów", side = 1, line = 7, cex = 1.2)

Wykres typu “heatmapa”
Wykres typu heatmapa przedstawia średnie oceny (Rating) w zależności od miasta i płci. Kolor kafelków
odzwierciedla wartość średniej oceny – jaśniejsze odcienie oznaczają niższe wartości, a ciemniejsze wyższe.
# Tworzenie wykresu typu "heatmapa"
# Agregowanie danych
heatmap_data <- data %>%
group_by(City, Gender) %>%
summarise(Average_Rating = mean(Rating, na.rm = TRUE)) %>%
ungroup()
## `summarise()` has grouped output by 'City'. You can override using the
## `.groups` argument.
# Tworzenie wykresu
ggplot(heatmap_data, aes(x = Gender, y = City, fill = Average_Rating)) +
geom_tile(color = "white") +
labs(
title = "Średnie oceny (Rating) w zależności od miasta i płci",
x = "Płeć",
y = "Miasto",
fill = "Średnia ocena"
) +
theme_minimal() +
scale_fill_gradient(low = "lightblue", high = "darkblue")

Wykres linowy
Wykres liniowy przedstawia trend sprzedaży w czasie, umożliwiając obserwację zmian w całkowitej sprzedaży
na przestrzeni dni. Linia łączy punkty reprezentujące dzienne sumy sprzedaży, co pozwala na łatwe dostrzeżenie
wzorców, takich jak okresowe wzrosty i spadki.
# Tworzenie wykresu trendów
# Konwersja kolumny 'Date' na format daty
data$Date <- as.Date(data$Date, format = "%m/%d/%Y")
# Grupowanie danych według daty i obliczanie całkowitej sprzedaży
daily_sales <- aggregate(Total ~ Date, data = data, sum)
# Tworzenie wykresu liniowego
plot(
daily_sales$Date,
daily_sales$Total,
type = "l", # Typ wykresu: linia
col = "blue", # Kolor linii
lwd = 2, # Grubość linii
main = "Sprzedaż w czasie",
xlab = "Data",
ylab = "Całkowita sprzedaż"
)
# Dodanie punktów na wykresie dla lepszej widoczności
points(
daily_sales$Date,
daily_sales$Total,
col = "black", # Kolor punktów
pch = 16 # Typ punktów: kropki
)

Porównanie ‘Total’ i ‘Branch’
Wykres pudełkowy przedstawia porównanie wartości 'Total' dla trzech gałęzi (A, B, C).
Każda gałąź ma podobnyrozkład wartości, z medianą na zbliżonym poziomie.
Występują wartości odstające (outliers) powyżej 1000.
Rozstęp międzykwartylowy (IQR) jest podobny dla wszystkich gałęzi, co sugeruje względnie równomierne
rozproszenie danych.
# Porównanie Total wg gałęzi
ggplot(data, aes(x = Branch, y = Total, fill = Branch)) +
geom_boxplot() +
labs(title = "Porównanie 'Total' wg gałęzi", x = "Gałęzie", y = "Total")

Rozkład ‘gross income’ i ‘customer type’
Większość transakcji generuje niskie wartości 'gross.income' (głównie poniżej 10), co widać po wysokich
słupkach na początku osi X.
Rozkład jest prawostronnie skośny – im wyższy Gross Income, tym rzadsze transakcje.
Klienci Normal (turkusowy kolor) mają więcej transakcji o niższych wartościach Gross Income, ale ich
rozkład jest zbliżony do członków Member (czerwony kolor).
ggplot(data, aes(x = gross.income, fill = Customer.type)) +
geom_histogram(bins = 20, alpha = 0.7, position = "identity") +
labs(title = "Rozkład 'Gross Income' wg typu klienta", x = "Gross Income", y = "Liczba transakcji")

Rozkład ‘Rating’ według płci (‘Gender’)
Wykres przedstawia rozkład ocen w zależności od płci (Female – czerwony, Male – turkusowy).
Ogólny rozkład ocen dla obu płci jest podobny, ale są pewne różnice w gęstości.
Mężczyźni (turkusowy) mają większą koncentrację ocen wokół 6-7, co oznacza, że częściej wystawiają oceny
w tym zakresie.
Kobiety (czerwony) mają więcej ocen w skrajnych wartościach – widoczny jest nieco większy udział ocen
w okolicach 4-5 oraz 9-10.
Ogólnie, różnice nie są duże, ale kobiety częściej wystawiają zarówno bardzo niskie, jak i bardzo wysokie oceny,
a mężczyźni częściej oceniają w średnim zakresie.
ggplot(data, aes(x = Rating, fill = Gender)) +
geom_density(alpha = 0.5) +
labs(title = "Rozkład ocen wg płci", x = "Ocena", y = "Gęstość")

Porównanie ‘gross.income’ i płci (‘Gender’)
Wykres przedstawia porównanie dochodów brutto ze względu na płeć.
Mediana dochodów kobiet i mężczyzn jest na zbliżonym poziomie, co sugeruje brak istotnych różnic
w przeciętnych zarobkach między grupami.
Rozkład dochodów w obu przypadkach jest podobny, choć widać kilka wartości odstających, wskazujących
na jednostki z wyraźnie wyższymi zarobkami.
Ogólnie dochody obu płci mają porównywalną strukturę.
ggplot(data, aes(x = Gender, y = gross.income, fill = Gender)) +
geom_boxplot() +
labs(title = "Gross Income wg płci", x = "Płeć", y = "Gross Income")

Porównanie ‘Customer.type’ i ‘Total’
Wykres przedstawia porównanie całkowitej wartości zakupów w zależności od typu klienta.
Mediana wydatków dla członków programu lojalnościowego (Member) i klientów standardowych (Normal) jest
na podobnym poziomie, co sugeruje brak istotnych różnic w przeciętnych wartościach zakupów.
Rozkład wydatków jest zbliżony dla obu grup, choć występują pojedyncze wartości odstające wskazujące na
wyjątkowo wysokie zakupy.
Ogólnie rzecz biorąc, typ klienta nie wydaje się mieć dużego wpływu na poziom wydatków.
ggplot(data, aes(x = Customer.type, y = Total, fill = Customer.type)) +
geom_boxplot() +
labs(title = "Total wg typu klienta", x = "Typ klienta", y = "Total")

Porównanie ‘Rating’ i ‘Branch’
Wykres przedstawia porównanie ocen (Rating) dla trzech różnych gałęzi (A, B, C).
Mediany ocen we wszystkich gałęziach są zbliżone, co sugeruje, że poziom ocen klientów jest podobny
niezależnie od oddziału. Rozkład ocen jest szeroki, co oznacza, że w każdej gałęzi występują zarówno niskie,
jak i wysokie oceny.
Ogólnie rzecz biorąc, nie widać znaczących różnic w ocenach między oddziałami.
ggplot(data, aes(x = Branch, y = Rating, fill = Branch)) +
geom_boxplot() +
labs(title = "Porównanie 'Rating' wg gałęzi", x = "Gałęzie", y = "Rating")

Porównanie ‘gross.income’ i ‘Product.line’
Wykres przedstawia porównanie dochodu brutto ("Gross Income") w różnych kategoriach produktów.
Większość kategorii produktów ma podobną medianę wartości dochodu brutto, co sugeruje, że przeciętny dochód
dla różnych typów produktów jest zbliżony.
Szerokość pudełek jest podobna w większości kategorii, co oznacza porównywalną zmienność danych.
W każdej kategorii występują wartości odstające, co sugeruje, że w niektórych przypadkach dochód brutto był
wyjątkowo wysoki.
Ogólnie rzecz biorąc, różnice między kategoriami produktów nie są znaczące, co sugeruje, że żadna z nich nie
wyróżnia się wyraźnie pod względem dochodu brutto.
ggplot(data, aes(x = Product.line, y = gross.income, fill = Product.line)) +
geom_boxplot() +
labs(title = "Porównanie 'Gross Income' wg kategorii produktów", x = "Kategoria produktu", y = "Gross Income") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

8. Wnioskowanie statystyczne.
Końcowa analiza zbioru danych dotyczącego sprzedaży w trzech sklepach Biedronka polega na przeprowadzeniu
testów parametrycznych i nieparametrycznych w celu zrozumienia określonych wartości zmiennych.
Zmienne ilościowe brane pod uwagę przy testowaniu to: 'Rating', Unit.price', 'Quantity' i 'Total', natomiast
zmienne kategoryczne to: 'City', 'Customer.type' i 'Payment'.
Testowanie normalności rozkładów
Testowanie normalności rozkładów zmiennych opiera się na statystyce Shapiro-Wilka oraz wykresie Q-Q
(Quantile-Quantile), porównującym rozkład empiryczny danej zmiennej z rozkładem normalnym.
Hipotezy dla testu Shapiro-Wilka brzmią następująco:
H0: Badana zmienna posiada rozkład normalny wartości.
HA: Badana zmienna nie posiada rozkładu normalnego wartości.
> Zmienna ‘Rating’
Test Shapiro-Wilka
|
|
Statystyka
|
p_value
|
|
W
|
0.96
|
0
|

> Zmienna ‘Unit.price’
Test Shapiro-Wilka
|
|
Statystyka
|
p_value
|
|
W
|
0.95
|
0
|

> Zmienna ‘Quantity’
Test Shapiro-Wilka
|
|
Statystyka
|
p_value
|
|
W
|
0.93
|
0
|

> Zmienna ‘Total’
Test Shapiro-Wilka
|
|
Statystyka
|
p_value
|
|
W
|
0.91
|
0
|

Testy normalności rozkładów zmiennych: 'Rating', 'Unit.price', 'Quantity' oraz 'Total' wykazały, że są to zmienne
nie posiadające rozkładów normalnych swoich wartości.
Wniosek ten uzasadnia statystyka Shapiro-Wilka, która w przypadku każdej zmiennej wyniosła ok. 0.96,
a odpowiadająca jej wartość p-value przyjęła wartość niższą od przyjętego poziomu istotności (0 < 0,05), czym
wykazała, że istnieją przesłanki, aby odrzucić H0 mówiącą o normalności rozkładu wartości badanych zmiennych.
Ponadto wykresy Q-Q dla wymienionych zmiennych nie przyjęły postaci linii prostej, znacznie odchylając się od
rozkładu normalnego, czym również przyczyniły się do wsparcia hipotezy o braku rozkładu normalnego zmiennych
'Rating', 'Unit.price', 'Quantity' oraz 'Total'.
Wobec powyższego przyjmuje się, że dalsze analizowanie zmiennych opierać się będzie o testy nieparametryczne.
Testy nieparametryczne dla wybranych zmiennych ilościowych i
kategorycznych
Histogramy i test Wilcoxona




Przedstatwione wyżej histogramy dla wybranych zmiennych ilościowych wykazały, że:
- rozkład wartości dla zmiennej 'Rating' jest lewostronnie skośny, gdyż większość wartości skupia się po prawej
stronie od mediany równej 5.5. Ponadto najczęściej przyznawaną oceną dla sklepu było 6 (17,5%
klientów), a najrzadsze oceny miały zakres 1-3,9 (0% klientów).
- rozkład wartości dla zmiennej 'Unit.price' nie wykazuje obserwowalnego skupienia po którejś ze stron mediany
równej 55,23. Oznacza to, że ceny produktów były mniej więcej podobne, istnieją jednak pojedyncze odstępstwa
od tych wartości;
- rozkład wartości dla zmiennej 'Quantity' jest nieznacznie prawostronnie skośny od mediany równej 5, co świadczyć
może, że zwyczajowa liczba produktów kupowana przez badanych klientów była większa niż 5. Ponadto największa
liczba klientów (ok. 11,5%) kupowała 10 sztuk towaru w danej lokalizacji i czasie;
- rozkład wartości dla zmiennej 'Total' jest prawostronnie skośny, o czym świadczy fakt, że wartości rozciągają się
po prawej stronie od mediany równej 253,85, a większość wartości koncentruje się po jej lewej stornie. Stwierdzić
zatem można, że największa liczba transakcji opiewała na kwoty z przedziału ok. 0-250 dolarów, gdyż wartości
w przedziale 0-250 dolarów dominują, ale pojawiają się również wartości dochodzące do 1050 dolarów, co ma
wpływ na końcową skośność.
Ponadto statystyka Wilcoxona, dla której testowane są hipotezy:
H0: Rozkład wartości zmiennej nie różni się od mediany jej wartości,
HA: Rozkład wartości zmiennej różni się od mediany jej wartości,
wykazała, że na podstawie wartości p-value, która jest bliska 0 dla wszystkich zmiennych (p-value < 0,05) można
odrzucić H0 mówiące o braku różnic między wartościami zmiennych, a ich medianą.
Testy zależności
Testy zależności dla zmiennej ‘Rating’

Dla nieparametrycznego testu Kruskala-Wallisa zależności bada się następujące hipotezy:
H0: Rozkład wartości zmiennej ocen ('Rating') w każdym mieście ('City') jest taki sam.
HA: Rozkład wartości zmiennej ocen ('Rating') w każdym mieście ('City') nie jest taki sam.
Statystyka testu wyniosła 1,86 przy wartości p-value większej od przyjętego poziomu istotności alfa (0,39 > 0,05),
co wskazuje, że nie ma istotnych przesłanek do odrzucenia H0, twierdzącego, że rozkłady wartości ocen we wszystkich
trzech miastach, gdzie znajdują się sklepy są sobie równe.

Dla nieparametrycznego testu zależności Manna-Whitneya między zmienną 'Rating' a 'Customer.type' bada się hipotezy:
H0: Mediany ocen ('Rating') nadawanych przez oba typy klientów ('Customer.type') są sobie równe, a rozkłady
dla klienta "Member" i "Normal" są identyczne.
HA: Mediany ocen ('Rating') nadawanych przez oba typy klientów ('Customer.type') nie są sobie równe,
a rozkłady dla klienta "Member" i "Normal" są nie identyczne.
HA1: Mediana ocen ('Rating') nadawanych przez posiadaczy karty członkowskiej jest większa od mediany ocen
osób nieposiadających karty.
HA2: Mediana ocen ('Rating') nadawanych przez posiadaczy karty członkowskiej jest mniejsza od mediany
ocen osób nieposiadających karty.
Statystyka testu wyniosła ok. 119 000 przy wartości p-value większej od przyjętego poziomu istotności alfa
(0,2 > 0,05), co wskazuje, że nie ma istotnych przesłanek do odrzucenia H0 twierdzącego, że mediany wartości ocen
nadawanych przez osobę posiadającą kartę członkowską nie różnią się znacząco od mediany ocen przyznawanych
przez klientów nie będących w jej posiadaniu. Ponadto test wykazał, że rozkłady dla obu typów klientów są z dużym
prawdopodobieństwem identyczne.
Testy zależności zmiennej ‘Quantity’ oraz ‘Gender’

Dla nieparametrycznego testu zależności Manna-Whitneya zmiennej 'Gender' i 'Quantity' bada się hipotezy:
H0: Mediany ilości zakupionych produktów ('Quantity') przez klientów obu płci ('Customer.type') są sobie
równe i rozkłady dla "Female" i "Male" są identyczne.
HA: Mediany ilości zakupionych produktów ('Quantity') przez klientów obu płci ('Customer.type') nie są sobie
równe i rozkłady dla "Female" i "Male" nie są identyczne.
HA1: Mediana ilości zakupionych produktów ('Quantity') przez kobiety ("Female") jest większa od
mediany ilości towarów dla mężczyzn ("Male").
HA2: Mediana ilości zakupionych produktów ('Quantity') przez kobiety ("Female") jest mniejsza od
mediany ilości towarów dla mężczyzn ("Male").
Statystyka testu wyniosła ok. 136 000 przy wartości p-value mniejszej od przyjętego poziomu istotności alfa
(0,2 < 0,05), co wskazuje, że istnieją istotne przesłanki, aby odrzucić H0 twierdzącą, że mediany ilości produktów
zakupionych przez klientów obu płci są sobie równe, a rozkład wartości ilości zakupionych produktów dla kobiet
i mężczyzn są identyczne. Ponadto stwierdzić można, że mediana ilości zakupionych towarów kobiet jest większa
od mediany dla mężczyzn.
Test korelacji między zmiennymi ‘Customer.type’ i
‘Payment’

Dla nieparametrycznego testu Pearsona (p) badającego korelację między zmiennymi 'Customer.type' i 'Payment'
bada się następujące hipotezy:
H0: Nie istnieje korelacja między osobami posiadającymi i nieposiadającymi kartę członkowską sklepu a formą
płatności za zakupy (p = 0).
HA: Istnieje korelacja między osobami posiadającymi i nieposiadającymi kartę członkowską sklepu a formą
płatności za zakupy (p =/= 0).
Statystyka testu Pearsona (p) wyniosła 5,22 przy wartości p-value mniejszej od przyjętego poziomu istotności alfa
(0,03 < 0,05) dla osoby nie będącej posiadaczem karty lojalnosciowej sklepu i większej dla osoby, która tę kartę ma
(0,83 > 0,05). W związku z tym dla osoby nie posiadającej karty, istnieją istotne przesłanki, aby odrzucić H0, a co
za tym idzie - jej korelacja z formą płatności istnieje i jest dodatnia (p > 0), natomiast dla osoby posiadającej taką
kartę nie ma podstaw do odrzucenia H0, zatem jej korelacja z formą płatności nie występuje.
PODSUMOWANIE CZĘŚCI TESTOWEJ
Przeprowadzone testy wykazały następujące zależności:
- Ocena klientów ('Rating') nigdy nie była niższa od oceny 4, natomiast najczęściej przyznawana ocena przez
klientów to 6. Ponadto prawdopodobnym jest, że przyznawane oceny nie są zależne ani od miasta, w jakim się
znajduje dany sklep Biedronka, ani od faktu, czy klient posiada kartę lojalnościową czy też nie.
- Ilość zakupionych produktów 'Quantity' przez przeciętnego, badanego klienta w trzech pierwszych miesiącach 2019
wynosiła więcej niż 5. Ponadto środkowa liczba oznaczająca ilość zakupionych produktów przez kobiety była w tym
okresie wyższa od mediany zakupionych produktów przez mężczyzn.
- Istnieje pewna zależność pomiędzy osobami nieposiadającymi kartę członkowską sklepu a formą, jaką wybierają
przy płatności za zakupy. Można się spodziewać, że takie osoby częściej wybiorą płatność poprzez portfel
elektroniczny niż kartą kredytową czy gotówką. Dodatkowo płatność kartą kredytową wybiorą najmniej chętnie.
Nie istnieją jednak przesłanki, aby móc zakładać, że osoby posiadające kartę członkowską preferują daną formę
płatności za zakupy.