Introduction

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.

Objectives

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.

Research Questions

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