Sales data analysis is an essential process that helps organisations understand business performance, customer purchasing behaviour, and market trends. By applying statistical techniques and data visualisation methods, businesses can identify key patterns, evaluate profitability, monitor sales growth, and support strategic decision-making. This study analyses the Sales Dataset containing information on order details, sales amount, profit, quantity, product categories, payment methods, customers, and geographical locations. Various descriptive and inferential statistical analyses, along with graphical visualisations, are performed to explore relationships among variables, detect trends, compare performance across categories and regions, and provide meaningful insights that can improve business operations and future sales strategies. ## Aim The aim of this study is to analyse the sales dataset using statistical techniques and data visualisation methods to identify sales patterns, customer behaviour, profitability, and business performance, thereby providing data-driven insights that support effective decision-making and strategic business planning.
To examine the overall sales performance using descriptive statistical analysis. To analyse the relationship between sales amount, profit, and quantity using correlation and regression analysis. To evaluate sales and profitability across different product categories and sub-categories. To investigate customer purchasing behaviour based on payment methods, states, cities, and time periods. To identify sales trends, outliers, and significant factors influencing business performance through statistical tests and visualisations.
What are the overall sales and profit trends observed in the dataset? Is there a significant relationship between sales amount, profit, and quantity sold? Which product categories and sub-categories contribute the most to sales and profitability? How do customer location and payment mode influence sales performance? What insights can statistical analysis and data visualisation provide to support business decision-making?
#Load Libraries
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.3
## Warning: package 'ggplot2' was built under R version 4.5.3
## Warning: package 'tidyr' was built under R version 4.5.3
## Warning: package 'readr' was built under R version 4.5.3
## Warning: package 'purrr' was built under R version 4.5.3
## Warning: package 'dplyr' was built under R version 4.5.3
## Warning: package 'forcats' was built under R version 4.5.3
## Warning: package 'lubridate' was built under R version 4.5.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.5.1
## ✔ ggplot2 4.0.3 ✔ tibble 3.2.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.3
## corrplot 0.95 loaded
library(psych)
## Warning: package 'psych' was built under R version 4.5.3
##
## Attaching package: 'psych'
##
## The following objects are masked from 'package:ggplot2':
##
## %+%, alpha
library(ggpubr)
## Warning: package 'ggpubr' was built under R version 4.5.3
library(GGally)
## Warning: package 'GGally' was built under R version 4.5.3
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.5.3
##
## Attaching package: 'reshape2'
##
## The following object is masked from 'package:tidyr':
##
## smiths
library(scales)
## Warning: package 'scales' was built under R version 4.5.3
##
## Attaching package: 'scales'
##
## The following objects are masked from 'package:psych':
##
## alpha, rescale
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
library(plotly)
## Warning: package 'plotly' was built under R version 4.5.3
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(treemap)
## Warning: package 'treemap' was built under R version 4.5.3
library(gridExtra)
## Warning: package 'gridExtra' was built under R version 4.5.3
##
## Attaching package: 'gridExtra'
##
## The following object is masked from 'package:dplyr':
##
## combine
library(PerformanceAnalytics)
## Warning: package 'PerformanceAnalytics' was built under R version 4.5.3
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.5.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.5.3
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'xts'
##
## The following objects are masked from 'package:dplyr':
##
## first, last
##
##
## Attaching package: 'PerformanceAnalytics'
##
## The following object is masked from 'package:graphics':
##
## legend
library(moments)
## Warning: package 'moments' was built under R version 4.5.2
##
## Attaching package: 'moments'
##
## The following objects are masked from 'package:PerformanceAnalytics':
##
## kurtosis, skewness
#Import Dataset
sales <- read.csv("C:/Users/User/Downloads/Rstudio_Souvik Nandi/Sales Dataset.csv")
str(sales)
## 'data.frame': 1194 obs. of 12 variables:
## $ Order.ID : chr "B-26776" "B-26776" "B-26776" "B-26776" ...
## $ Amount : int 9726 9726 9726 4975 4975 4975 1525 1525 883 8127 ...
## $ Profit : int 1275 1275 1275 1330 1330 1330 185 185 117 3551 ...
## $ Quantity : int 5 5 5 14 14 14 12 12 10 16 ...
## $ Category : chr "Electronics" "Electronics" "Electronics" "Electronics" ...
## $ Sub.Category: chr "Electronic Games" "Electronic Games" "Electronic Games" "Printers" ...
## $ PaymentMode : chr "UPI" "UPI" "UPI" "UPI" ...
## $ Order.Date : chr "2023-06-27" "2024-12-27" "2021-07-25" "2023-06-27" ...
## $ CustomerName: chr "David Padilla" "Connor Morgan" "Robert Stone" "David Padilla" ...
## $ State : chr "Florida" "Illinois" "New York" "Florida" ...
## $ City : chr "Miami" "Chicago" "Buffalo" "Miami" ...
## $ Year.Month : chr "Jun-23" "Dec-24" "Jul-21" "Jun-23" ...
head(sales)
## Order.ID Amount Profit Quantity Category Sub.Category PaymentMode
## 1 B-26776 9726 1275 5 Electronics Electronic Games UPI
## 2 B-26776 9726 1275 5 Electronics Electronic Games UPI
## 3 B-26776 9726 1275 5 Electronics Electronic Games UPI
## 4 B-26776 4975 1330 14 Electronics Printers UPI
## 5 B-26776 4975 1330 14 Electronics Printers UPI
## 6 B-26776 4975 1330 14 Electronics Printers UPI
## Order.Date CustomerName State City Year.Month
## 1 2023-06-27 David Padilla Florida Miami Jun-23
## 2 2024-12-27 Connor Morgan Illinois Chicago Dec-24
## 3 2021-07-25 Robert Stone New York Buffalo Jul-21
## 4 2023-06-27 David Padilla Florida Miami Jun-23
## 5 2024-12-27 Connor Morgan Illinois Chicago Dec-24
## 6 2021-07-25 Robert Stone New York Buffalo Jul-21
tail(sales)
## Order.ID Amount Profit Quantity Category Sub.Category
## 1189 B-25350 7699 246 5 Electronics Electronic Games
## 1190 B-26370 8825 3594 15 Furniture Tables
## 1191 B-26298 2082 642 8 Electronics Phones
## 1192 B-26298 2082 642 8 Electronics Phones
## 1193 B-26298 2082 642 8 Electronics Phones
## 1194 B-25068 914 163 13 Office Supplies Markers
## PaymentMode Order.Date CustomerName State City
## 1189 Debit Card 2023-09-23 Mark Fry Texas Austin
## 1190 Debit Card 2024-07-31 Megan Mclean New York New York City
## 1191 EMI 2020-06-02 Caitlin Hunt New York Rochester
## 1192 EMI 2022-12-15 Jenna Holland Texas Austin
## 1193 EMI 2020-08-07 Stephanie Oconnell New York Buffalo
## 1194 UPI 2024-10-26 Andrea Hill Illinois Chicago
## Year.Month
## 1189 Sep-23
## 1190 Jul-24
## 1191 Jun-20
## 1192 Dec-22
## 1193 Aug-20
## 1194 Oct-24
View(sales)
#Convert Variables
sales$Order.Date <- as.Date(sales$Order.Date)
sales$Category <- as.factor(sales$Category)
sales$Sub.Category <- as.factor(sales$Sub.Category)
sales$PaymentMode <- as.factor(sales$PaymentMode)
sales$State <- as.factor(sales$State)
sales$City <- as.factor(sales$City)
sales$CustomerName <- as.factor(sales$CustomerName)
sales$Year.Month <- as.factor(sales$Year.Month)
#Check Missing Values
colSums(is.na(sales))
## Order.ID Amount Profit Quantity Category Sub.Category
## 0 0 0 0 0 0
## PaymentMode Order.Date CustomerName State City Year.Month
## 0 0 0 0 0 0
sum(is.na(sales))
## [1] 0
#Summary Statistics
summary(sales)
## Order.ID Amount Profit Quantity
## Length:1194 Min. : 508 Min. : 50 Min. : 1.00
## Class :character 1st Qu.:2799 1st Qu.: 410 1st Qu.: 6.00
## Mode :character Median :5152 Median :1014 Median :11.00
## Mean :5178 Mean :1349 Mean :10.67
## 3rd Qu.:7626 3rd Qu.:2035 3rd Qu.:16.00
## Max. :9992 Max. :4930 Max. :20.00
##
## Category Sub.Category PaymentMode
## Electronics :388 Tables :122 COD :206
## Furniture :407 Pens :114 Credit Card:258
## Office Supplies:399 Sofas :114 Debit Card :260
## Markers :110 EMI :218
## Electronic Games:104 UPI :252
## Paper :104
## (Other) :526
## Order.Date CustomerName State
## Min. :2020-03-22 Andrew Allen : 4 California:218
## 1st Qu.:2021-09-06 Anna Blackburn : 4 Florida :200
## Median :2022-10-07 Anna Ferguson : 4 Illinois :181
## Mean :2022-10-03 Brett Sutton : 4 New York :226
## 3rd Qu.:2023-12-12 Christina Davis: 4 Ohio :180
## Max. :2025-03-15 Claudia Curry : 4 Texas :189
## (Other) :1170
## City Year.Month
## Buffalo : 90 Dec-22 : 45
## San Francisco: 84 Aug-22 : 33
## Orlando : 77 Jan-22 : 31
## Rochester : 74 Jul-23 : 30
## San Diego : 73 Nov-21 : 28
## Dallas : 72 Oct-22 : 28
## (Other) :724 (Other):999
#Descriptive Statistics
describe(sales[,c("Amount","Profit","Quantity")])
## vars n mean sd median trimmed mad min max range skew
## Amount 1 1194 5178.09 2804.92 5152 5160.65 3576.03 508 9992 9484 0.05
## Profit 2 1194 1348.99 1117.99 1014 1209.46 1049.68 50 4930 4880 0.94
## Quantity 3 1194 10.67 5.78 11 10.71 7.41 1 20 19 -0.04
## kurtosis se
## Amount -1.19 81.17
## Profit 0.04 32.35
## Quantity -1.23 0.17
#Mean Median SD
mean(sales$Amount)
## [1] 5178.09
median(sales$Amount)
## [1] 5152
sd(sales$Amount)
## [1] 2804.922
mean(sales$Profit)
## [1] 1348.992
median(sales$Profit)
## [1] 1014
sd(sales$Profit)
## [1] 1117.993
mean(sales$Quantity)
## [1] 10.6742
median(sales$Quantity)
## [1] 11
sd(sales$Quantity)
## [1] 5.777102
#Skewness & Kurtosis
skewness(sales$Amount)
## [1] 0.05350872
kurtosis(sales$Amount)
## [1] 1.815592
skewness(sales$Profit)
## [1] 0.942428
kurtosis(sales$Profit)
## [1] 3.042963
skewness(sales$Quantity)
## [1] -0.0378374
kurtosis(sales$Quantity)
## [1] 1.773545
#Correlation Matrix
correlation <- cor(sales[,c("Amount","Profit","Quantity")])
correlation
## Amount Profit Quantity
## Amount 1.00000000 0.67528536 0.04463148
## Profit 0.67528536 1.00000000 0.06608766
## Quantity 0.04463148 0.06608766 1.00000000
#Correlation Plot
corrplot(correlation,
method="color",
type="upper",
addCoef.col="black")
#Histogram
ggplot(sales,aes(Amount))+
geom_histogram(fill="steelblue",bins=30)
ggplot(sales,aes(Profit))+
geom_histogram(fill="orange",bins=30)
ggplot(sales,aes(Quantity))+
geom_histogram(fill="green",bins=30)
#Density Plot
ggplot(sales,aes(Amount))+
geom_density(fill="blue",alpha=.4)
ggplot(sales,aes(Profit))+
geom_density(fill="red",alpha=.4)
#Boxplots
ggplot(sales,aes(y=Amount))+
geom_boxplot(fill="cyan")
ggplot(sales,aes(y=Profit))+
geom_boxplot(fill="pink")
ggplot(sales,aes(y=Quantity))+
geom_boxplot(fill="yellow")
#Scatter Plot
ggplot(sales,
aes(Amount,Profit))+
geom_point(color="blue")+
geom_smooth(method="lm")
## `geom_smooth()` using formula = 'y ~ x'
#Profit vs Quantity
ggplot(sales,
aes(Quantity,Profit))+
geom_point(color="red")+
geom_smooth(method="lm")
## `geom_smooth()` using formula = 'y ~ x'
#Amount vs Quantity
ggplot(sales,
aes(Quantity,Amount))+
geom_point(color="green")+
geom_smooth(method="lm")
## `geom_smooth()` using formula = 'y ~ x'
#Pair Plot
ggpairs(
sales[,c("Amount",
"Profit",
"Quantity")]
)
#Sales by Category
ggplot(sales,
aes(Category,
Amount,
fill=Category))+
geom_bar(stat="summary",
fun="sum")
#Profit by Category
ggplot(sales,
aes(Category,
Profit,
fill=Category))+
geom_bar(stat="summary",
fun="sum")
#Sales by Subcategory
sales %>%
group_by(Sub.Category) %>%
summarise(Sales=sum(Amount)) %>%
ggplot(aes(reorder(Sub.Category,Sales),Sales))+
geom_col(fill="steelblue")+
coord_flip()
#Payment Mode Analysis
ggplot(sales,
aes(PaymentMode,
fill=PaymentMode))+
geom_bar()
#Sales by Payment Mode
sales %>%
group_by(PaymentMode) %>%
summarise(Sales=sum(Amount)) %>%
ggplot(aes(PaymentMode,
Sales,
fill=PaymentMode))+
geom_col()
#Profit by Payment Mode
sales %>%
group_by(PaymentMode) %>%
summarise(Profit=sum(Profit)) %>%
ggplot(aes(PaymentMode,
Profit,
fill=PaymentMode))+
geom_col()
#State Analysis
sales %>%
group_by(State) %>%
summarise(Sales=sum(Amount)) %>%
ggplot(aes(reorder(State,Sales),
Sales))+
geom_col(fill="purple")+
coord_flip()
#City Analysis
sales %>%
group_by(City) %>%
summarise(Sales=sum(Amount)) %>%
ggplot(aes(reorder(City,Sales),
Sales))+
geom_col(fill="darkgreen")+
coord_flip()
#Customer Analysis
sales %>%
group_by(CustomerName) %>%
summarise(Sales=sum(Amount)) %>%
arrange(desc(Sales))
## # A tibble: 802 × 2
## CustomerName Sales
## <fct> <int>
## 1 Cory Evans 28557
## 2 Emily Ellison 27352
## 3 George Foster 27352
## 4 Nicholas Anderson 27352
## 5 Katherine Williams 25121
## 6 Jacqueline Harris 24433
## 7 Randy Johnson 24295
## 8 Tammy Bell 23895
## 9 Brian Green 23737
## 10 Zachary Perez 23737
## # ℹ 792 more rows
#Top 10 Customers
sales %>%
group_by(CustomerName) %>%
summarise(Sales=sum(Amount)) %>%
top_n(10,Sales) %>%
ggplot(aes(reorder(CustomerName,Sales),
Sales))+
geom_col(fill="orange")+
coord_flip()
#Monthly Sales Trend
sales %>%
group_by(Year.Month) %>%
summarise(Sales=sum(Amount)) %>%
ggplot(aes(Year.Month,
Sales,
group=1))+
geom_line(color="blue")+
geom_point()
#Treemap
treemap(sales,
index="Category",
vSize="Amount",
vColor="Profit",
type="value")
#Pie Chart
sales %>%
group_by(Category) %>%
summarise(Sales=sum(Amount)) %>%
ggplot(aes("",Sales,
fill=Category))+
geom_col(width=1)+
coord_polar("y")
#ANOVA
anova_model<-
aov(Profit~Category,data=sales)
summary(anova_model)
## Df Sum Sq Mean Sq F value Pr(>F)
## Category 2 6.827e+05 341335 0.273 0.761
## Residuals 1191 1.490e+09 1251433
#Linear Regression
model<-
lm(Profit~
Amount+
Quantity,
data=sales)
summary(model)
##
## Call:
## lm(formula = Profit ~ Amount + Quantity, data = sales)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2262.20 -515.17 -2.88 513.97 2288.58
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.158e+02 6.549e+01 -1.769 0.0772 .
## Amount 2.685e-01 8.517e-03 31.528 <2e-16 ***
## Quantity 6.971e+00 4.135e+00 1.686 0.0921 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 824.3 on 1191 degrees of freedom
## Multiple R-squared: 0.4573, Adjusted R-squared: 0.4564
## F-statistic: 501.8 on 2 and 1191 DF, p-value: < 2.2e-16
#Regression Diagnostic
par(mfrow=c(2,2))
plot(model)
#Pareto Analysis
sales %>%
group_by(Sub.Category) %>%
summarise(Sales=sum(Amount)) %>%
arrange(desc(Sales))
## # A tibble: 12 × 2
## Sub.Category Sales
## <fct> <int>
## 1 Markers 627875
## 2 Tables 625177
## 3 Sofas 568367
## 4 Printers 566359
## 5 Electronic Games 565092
## 6 Pens 552269
## 7 Paper 524755
## 8 Phones 503055
## 9 Chairs 431964
## 10 Laptops 419950
## 11 Bookcases 413165
## 12 Binders 384611