library(readr)
Sales <- read_csv("C:/Users/nguye/Downloads/100000 Sales Records.csv")
## Rows: 100000 Columns: 14
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (7): Region, Country, Item.Type, Sales.Channel, Order.Priority, Order.Da...
## dbl (7): Order.ID, Units.Sold, Unit.Price, Unit.Cost, Total.Revenue, Total.C...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Nhận xét: Kết quả in ra cho thấy bộ dữ liệu gồm 100.000 dòng và 14 cột, trong đó có biến ký tự là Region, Country, Item.Type, Sales.Channel, Order.Priority, Order.Date, Ship.Date và 7 biến số là Units.Sold, Unit.Price, Unit.Cost, Total.Revenue, Total.Cost, Total.Profit. Đây là một bộ dữ liệu lớn, có cấu trúc rõ ràng và bao quát nhiều khía cạnh trong hoạt động bán hàng.
summary(Sales)
## Region Country Item.Type Sales.Channel
## Length:100000 Length:100000 Length:100000 Length:100000
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Order.Priority Order.Date Order.ID Ship.Date
## Length:100000 Length:100000 Min. :100008904 Length:100000
## Class :character Class :character 1st Qu.:326046383 Class :character
## Mode :character Mode :character Median :547718512 Mode :character
## Mean :550395554
## 3rd Qu.:775078534
## Max. :999996459
## Units.Sold Unit.Price Unit.Cost Total.Revenue
## Min. : 1 Min. : 9.33 Min. : 6.92 Min. : 18.7
## 1st Qu.: 2505 1st Qu.:109.28 1st Qu.: 56.67 1st Qu.: 279753.3
## Median : 5007 Median :205.70 Median :117.11 Median : 789891.6
## Mean : 5001 Mean :266.70 Mean :188.02 Mean :1336066.7
## 3rd Qu.: 7495 3rd Qu.:437.20 3rd Qu.:364.69 3rd Qu.:1836489.6
## Max. :10000 Max. :668.27 Max. :524.96 Max. :6682700.0
## Total.Cost Total.Profit
## Min. : 13.8 Min. :4.820e+00
## 1st Qu.: 162928.3 1st Qu.:9.590e+04
## Median : 467937.4 Median :2.837e+05
## Mean : 941975.5 Mean :3.941e+05
## 3rd Qu.:1209474.7 3rd Qu.:5.684e+05
## Max. :5249075.0 Max. :1.739e+06
Nhận xét:Các biến đều có độ phân tán khá lớn, thể hiện sự khác biệt giữa các đơn hàng. Trung bình, mỗi đơn hàng bán ra khoảng 5000 sản phẩm, với giá trung bình 266,7 và chi phí 188,02. Giá trị trung bình của doanh thu (1.336.066) cao hơn chi phí (941.975), cho thấy lợi nhuận trung bình của mỗi đơn hàng đạt khoảng 394.100, phản ánh hiệu quả kinh doanh tích cực.
sapply(Sales,function(Sales) sum(is.na(Sales)))
## Region Country Item.Type Sales.Channel Order.Priority
## 0 0 0 0 0
## Order.Date Order.ID Ship.Date Units.Sold Unit.Price
## 0 0 0 0 0
## Unit.Cost Total.Revenue Total.Cost Total.Profit
## 0 0 0 0
Nhận xét:Kết quả kiểm tra trả về toàn bộ giá trị bằng 0, nghĩa là không có bất kỳ giá trị thiếu nào trong 14 cột dữ liệu.Đây là một kết quả tốt vì dữ liệu đầy đủ, không bị NA .Điều này có nghĩa là không cần áp dụng thêm bất kỳ phương pháp xử lý bổ sung khác.Nhờ đó, các phân tích tiếp theo như tính tổng doanh thu, lợi nhuận hay vẽ biểu đồ đều đảm bảo chính xác và đáng tin cậy, không bị ảnh hưởng bởi lỗi thiếu dữ liệu.
Sales[duplicated(Sales),]
## # A tibble: 0 × 14
## # ℹ 14 variables: Region <chr>, Country <chr>, Item.Type <chr>,
## # Sales.Channel <chr>, Order.Priority <chr>, Order.Date <chr>,
## # Order.ID <dbl>, Ship.Date <chr>, Units.Sold <dbl>, Unit.Price <dbl>,
## # Unit.Cost <dbl>, Total.Revenue <dbl>, Total.Cost <dbl>, Total.Profit <dbl>
Nhận xét:Kết quả hiển thị là một bảng rỗng (# A tibble: 0 x 14), nghĩa là không có dòng dữ liệu nào bị trùng lặp. Kết quả này rất tốt vì đảm bảo các phép tính tổng hợp như doanh thu hoặc lợi nhuận không bị sai lệch do dữ liệu trùng. Dữ liệu có độ tin cậy cao và phản ánh đúng thực tế
boxplot(Sales$Units.Sold)
Nhận xét:Min= 1, Q1 = 2505, Q2 (Median) = 5007, Q3 = 7495, Max = 10000 Số lượng sản phẩm bán ra dao động từ 1 đến 10000 sản phẩm, thể hiện sự khác biệt lớn giữa các đơn hàng. Một nửa số đơn hàng (50%) có lượng bán nằm trong khoảng 2505 – 7495 sản phẩm, được giới hạn bởi hai tứ phân vị Q1 và Q3. Giá trị trung vị (Q2 = 5007) nằm gần giữa hộp, cho thấy dữ liệu phân bố khá cân đối quanh mức trung bình. Hầu hết các đơn hàng có quy mô trung bình, khoảng 5000 sản phẩm, trong khi một số đơn lớn đạt tới 10000 sản phẩm, có thể là đơn sỉ hoặc hợp đồng cung cấp số lượng lớn cho đại lý.
boxplot(Sales$Unit.Price)
Nhận xét:Min = 9,33, Q1 = 109,28, Q2 = 205,70, Q3 = 437,20, Max = 668,27 Giá bán mỗi sản phẩm có sự chênh lệch rõ rệt giữa các loại hàng. Một nửa số sản phẩm có giá nằm trong khoảng 109,28 – 437,20 đồng (Q1 – Q3). Giá trị trung vị (Q2 = 205,70) thể hiện mức giá phổ biến nhất rơi vào nhóm trung bình thấp, quanh 200 đồng. Giá thấp nhất là 9,33 đồng, trong khi cao nhất là 668,27 đồng, cho thấy doanh nghiệp kinh doanh đa dạng nhiều loại hàng hóa từ giá rẻ đến cao cấp. Biểu đồ có dạng lệch phải, nghĩa là phần lớn sản phẩm có giá thấp, chỉ một số ít có giá rất cao – thường là hàng cao cấp hoặc đặc biệt.
boxplot(Sales$Unit.Cost)
Nhận xét:Min = 6,92, Q1 = 56,67, Q2 = 117,11, Q3 = 364,69, Max = 524,96 Chi phí sản xuất dao động từ 6,92 đến 524,96 đồng, cho thấy mức độ khác biệt đáng kể giữa các mặt hàng. Khoảng giữa (Q1 – Q3) nằm trong khoảng 56,67 – 364,69 đồng, tức là 50% sản phẩm có chi phí ở mức trung bình. Giá trị trung vị (Q2 = 117,11) thấp hơn trung bình (188,02), phản ánh rằng đa số sản phẩm có chi phí thấp, chỉ một số ít sản phẩm đặc biệt có chi phí cao. So sánh với giá bán (trung bình 266,70 đồng), có thể thấy biên lợi nhuận dương, chứng tỏ doanh nghiệp đang hoạt động hiệu quả. Dữ liệu có dạng lệch phải nhẹ, do một vài sản phẩm có chi phí cao vượt trội so với phần còn lại.
boxplot(Sales$Total.Revenue)
Nhận xét:Min = 18,7, Q1 = 279753,3, Q2 = 789891,6, Q3 = 1836489,6, Max = 6682700,0 Tổng doanh thu của các đơn hàng thay đổi rất mạnh, từ 18,7 đồng đến 6682700 đồng, phản ánh sự khác biệt lớn về quy mô giao dịch. Một nửa số đơn hàng có doanh thu trong khoảng 279753 – 1836489 đồng (Q1 – Q3). Giá trị trung vị (Q2 = 789891) cho thấy đa số đơn hàng mang lại doanh thu trung bình, dưới 1 triệu đồng. Biểu đồ có dạng lệch phải, nghĩa là phần lớn đơn hàng ở mức doanh thu vừa phải, nhưng có một số ít đơn hàng đặc biệt lớn làm tổng doanh thu tăng cao.
boxplot(Sales$Total.Cost)
Nhận xét: Min = 13,8, Q1 = 162.928,3, Q2 = 467.937,4, Q3 = 1.209.474,7, Max = 5.249.075,0 Tổng chi phí của các đơn hàng phân bố từ 13,8 đến 5249075 . Phần lớn chi phí tập trung trong khoảng 162928 – 1209474, tương ứng với vùng giữa Q1 – Q3. Giá trị trung vị (Q2 = 467937) cho thấy đa số đơn hàng có chi phí trung bình khoảng 450000 đồng. Dữ liệu lệch phải, nghĩa là một vài đơn hàng có chi phí rất cao, thường đi kèm với doanh thu cao. Nhìn chung, chi phí tăng tỉ lệ thuận với doanh thu, và vì chi phí trung bình (941975) thấp hơn doanh thu trung bình (1336066 ), nên doanh nghiệp vẫn duy trì lợi nhuận dương và ổn định.
boxplot(Sales$Total.Profit)
Nhận xét:Min = 4,82, Q1 = 95900, Q2 = 283700, Q3 = 568400, Max = 1739000 Lợi nhuận của các đơn hàng dao động từ 4,82 đến 1739000, cho thấy hiệu quả bán hàng thay đổi tùy quy mô đơn hàng. Một nửa các đơn hàng có lợi nhuận trong khoảng 95900 – 568400 (Q1 – Q3). Giá trị trung vị (Q2 = 283700) thể hiện mức lợi nhuận phổ biến nhất mà doanh nghiệp thu được cho mỗi đơn hàng. Biểu đồ lệch phải, nghĩa là đa số đơn hàng có lợi nhuận trung bình hoặc thấp, nhưng vẫn có một số đơn hàng đặc biệt sinh lợi cao, kéo giá trị trung bình lên (394100). Điều này phản ánh tính hiệu quả và ổn định trong hoạt động kinh doanh, đồng thời thể hiện khả năng tạo ra lợi nhuận cao ở các giao dịch quy mô lớn.
scale <- function(vector){
if(is.numeric(vector) != TRUE){
print("No have num")
}
empty=c()
minus <- vector - min(vector)
scaling <- minus / (max(vector)-min(vector))
}
Units.Sold <- as.data.frame(scale(Sales$Units.Sold))
colnames(Units.Sold) <- c("scale.UNS")
Nhận xét:Việc chuẩn hóa giúp đưa các biến về cùng thang đo, thuận tiện khi so sánh hoặc vẽ biểu đồ. Đây là bước cần thiết trong các phân tích thống kê hoặc mô hình hóa vì nó giúp loại bỏ sự khác biệt về đơn vị đo lường giữa các biến (ví dụ doanh thu tính bằng triệu đồng trong khi giá đơn vị tính bằng nghìn đồng).
Vì định dạng đang ở character, nên sẽ có thêm bước chuyển về dữ liệu về đúng định dạng.
Sales$Order.Date <- as.Date(Sales$Order.Date, format = "%m/%d/%Y") #chuyển định dạng về Date
Sales$Year <- format(as.Date(Sales$Order.Date), "%Y")
Sales_Year_2014 <- Sales[Sales$Year == "2014",]
head(Sales_Year_2014)
## # A tibble: 6 × 15
## Region Country Item.Type Sales.Channel Order.Priority Order.Date Order.ID
## <chr> <chr> <chr> <chr> <chr> <date> <dbl>
## 1 Middle Eas… Azerba… Snacks Online C 2014-10-08 5.35e8
## 2 Sub-Sahara… Sao To… Personal… Online M 2014-09-17 8.93e8
## 3 Middle Eas… Jordan Household Offline L 2014-07-09 2.23e8
## 4 Sub-Sahara… Comoros Beverages Offline L 2014-08-10 5.81e8
## 5 Sub-Sahara… Zambia Cosmetics Offline M 2014-07-26 9.93e8
## 6 Middle Eas… Egypt Cereal Online C 2014-07-14 8.88e8
## # ℹ 8 more variables: Ship.Date <chr>, Units.Sold <dbl>, Unit.Price <dbl>,
## # Unit.Cost <dbl>, Total.Revenue <dbl>, Total.Cost <dbl>, Total.Profit <dbl>,
## # Year <chr>
Nhận Xét: Thực hiện phân tổ theo năm giúp ta dễ kiểm soát được năm đó có bao nhiêu đơn hàng được đặt
Sales$Ship.Date <- as.Date(Sales$Ship.Date, format = "%m/%d/%Y")
Sales$delivery_Date <- as.data.frame(Sales$Ship.Date-Sales$Order.Date)
summary(Sales$delivery_Date )
## Sales$Ship.Date - Sales$Order.Date
## Min. : 0.00 days
## 1st Qu.:12.00 days
## Median :25.00 days
## Mean :25.04 days
## 3rd Qu.:38.00 days
## Max. :50.00 days
Dựa vào thống kê ngày giao hàng, sẽ phân ra làm ba mức ngày giao hàng theo tứ phân vị: - Khoảng 1 nếu nhỏ hơn tứ phân vị 1 thì có tốc độ giao hàng nhanh. - Khoảng 2 nếu nhỏ hơn tứ phân vị 3 thì có tốc độ giao hàng trung bình. - Khoảng 3 nếu lớn hơn tứ phân vị 3 thì có tốc độ giao hàng nhanh.
Sales$Sort_Date <- ifelse(
Sales$delivery_Date < 12, "Tốc độ nhanh",
ifelse(
Sales$delivery_Date < 38, "Tốc độ trung bình",
"Tốc độ chậm"))
table(Sales$Sort_Date)
##
## Tốc độ chậm Tốc độ nhanh Tốc độ trung bình
## 25709 23553 50738
Nhận xét:Kết quả thống kê cho thấy thời gian giao hàng trung bình là khoảng 25,04 ngày, với giá trị nhỏ nhất là 0 ngày và lớn nhất là 50 ngày. Các tứ phân vị lần lượt là Q1 = 12 ngày, Q2 = 25 ngày và Q3 = 38 ngày, cho thấy phần lớn các đơn hàng được giao trong khoảng từ 12 đến 38 ngày. Dựa trên kết quả này, dữ liệu được phân loại thành ba nhóm: “Tốc độ nhanh” (dưới 12 ngày) với 23.553 đơn hàng, “Tốc độ trung bình” (từ 12 đến 38 ngày) với 50.738 đơn hàng, và “Tốc độ chậm” (trên 38 ngày) với 25.709 đơn hàng
Tốc_độ_chậm <- Sales[Sales$Sort_Date == "Tốc độ chậm",]
head(Tốc_độ_chậm)
## # A tibble: 6 × 17
## Region Country Item.Type Sales.Channel Order.Priority Order.Date Order.ID
## <chr> <chr> <chr> <chr> <chr> <date> <dbl>
## 1 Sub-Sahara… Sao To… Fruits Offline M 2015-12-09 8.54e8
## 2 Europe Malta Household Offline L 2015-03-10 2.44e8
## 3 Sub-Sahara… Camero… Fruits Online H 2015-12-18 3.70e8
## 4 Middle Eas… Morocco Vegetabl… Offline L 2014-05-15 2.29e8
## 5 Europe Switze… Baby Food Offline M 2011-03-26 5.40e8
## 6 North Amer… Greenl… Fruits Online L 2011-07-30 1.21e8
## # ℹ 10 more variables: Ship.Date <date>, Units.Sold <dbl>, Unit.Price <dbl>,
## # Unit.Cost <dbl>, Total.Revenue <dbl>, Total.Cost <dbl>, Total.Profit <dbl>,
## # Year <chr>, delivery_Date <df[,1]>, Sort_Date <chr[,1]>
Đầu tiên, các ký hiệu “C”, “H”, “M”, “L” trong cột Order.Priority được thay thế lần lượt bằng “Critical”, “High”, “Medium” và “Low” để dữ liệu dễ hiểu và thuận tiện cho phân tích. Sau đó, dữ liệu được phân tổ theo loại hàng (Item.Type) và độ ưu tiên (Order.Priority) để xem xét mức doanh thu tương ứng.
Sales$Order.Priority[Sales$Order.Priority == "C"] <- "Critical"
Sales$Order.Priority[Sales$Order.Priority == "H"] <- "High"
Sales$Order.Priority[Sales$Order.Priority == "M"] <- "Medium"
Sales$Order.Priority[Sales$Order.Priority == "L"] <- "Low"
Reve_Item_Priority <- aggregate(Sales$Total.Revenue,
by = list(Item = Sales$Item.Type, Priority = Sales$Order.Priority),
FUN = sum)
head(Reve_Item_Priority[order(Reve_Item_Priority$x, decreasing = TRUE),], 5) # Doanh thu cao nhất
## Item Priority x
## 45 Office Supplies Medium 7092747489
## 31 Household Low 7075645433
## 43 Household Medium 6963174924
## 21 Office Supplies High 6934264465
## 7 Household Critical 6892145842
tail(Reve_Item_Priority[order(Reve_Item_Priority$x, decreasing = TRUE),], 5) # Doanh thu thấp nhất
## Item Priority x
## 2 Beverages Critical 489781794
## 18 Fruits High 97379757
## 6 Fruits Critical 96050857
## 30 Fruits Low 93937323
## 42 Fruits Medium 93270648
Nhận xét:Office Supplies và Household là hai nhóm hàng có doanh thu cao nhất, đặc biệt khi mức độ ưu tiên là Medium hoặc Low, cho thấy đây là nhóm hàng được tiêu thụ ổn định, có đơn hàng lớn và thường xuyên. Ngược lại, Fruits và Beverages nằm trong nhóm doanh thu thấp nhất, dù có các đơn hàng mang độ ưu tiên “Critical”, cho thấy đây là nhóm sản phẩm ít được đặt hoặc có giá trị đơn hàng thấp hơn.
Asia = Sales[Sales$Region=="Asia",]
Nhận xét:Khi lọc dữ liệu cho khu vực Asia, ta có thể phân tích sâu hơn theo từng mặt hàng. Việc tính trung bình số sản phẩm bán và lợi nhuận theo từng quốc gia cho phép so sánh hiệu quả kinh doanh giữa các nước trong khu vực
Sold_asia <- aggregate(
cbind(Units.Sold = Asia$Units.Sold,
Total.Profit = Asia$Total.Profit),
by = list(country = Asia$Country, Item = Asia$Item.Type),
FUN = mean
)
head(Sold_asia)
## country Item Units.Sold Total.Profit
## 1 Bangladesh Baby Food 4943.745 473907.4
## 2 Bhutan Baby Food 5309.855 509002.7
## 3 Brunei Baby Food 5401.833 517819.7
## 4 Cambodia Baby Food 4920.152 471645.8
## 5 China Baby Food 5253.744 503623.9
## 6 India Baby Food 5490.847 526352.6
Nhận xét:Biến mới giúp đánh giá hiệu quả kinh doanh tương đối giữa các quốc gia và sản phẩm. Những nước hoặc mặt hàng có lợi nhuận trung bình đến cao là những khu vực trọng điểm tiềm năng.
q_unit <- quantile(Sold_asia$Units.Sold, probs = c(0.25, 0.75))
q_profit <- quantile(Sold_asia$Total.Profit, probs = c(0.25, 0.75))
Nhận xét:Giá trị tứ phân vị của Units.Sold là Q1=4701 và Q3=5319, có nghĩa là nhóm quốc gia có doanh số dưới 4701 được xem là thấp, nhóm từ 4701 đến 5319 là trung bình, và trên 5319 là cao.Còn của Total.Profit là Q1=215725 và Q3=525101, có nghĩa là quốc gia có lợi nhuận dưới 215725 được xếp vào nhóm thấp, từ 215725 đến 525101 là trung bình, và trên 525101 là cao.
Sold_asia$PhatTrien <- ifelse(
Sold_asia$Units.Sold < q_unit[1] & Sold_asia$Total.Profit < q_profit[1], "Phát triển chậm",
ifelse(
Sold_asia$Units.Sold <= q_unit[2] & Sold_asia$Total.Profit <= q_profit[2], "Phát triển trung bình",
"Phát triển tốt"
)
)
Nhận xét:Dựa trên hai tiêu chí số lượng bán và lợi nhuận, các quốc gia được chia thành: Phát triển chậm: cả doanh số và lợi nhuận đều thấp (dưới Q1). Phát triển trung bình: nằm trong khoảng giữa Q1 và Q3. Phát triển tốt: cả hai chỉ tiêu đều vượt Q3. Phân loại này giúp doanh nghiệp nhận diện các thị trường tiềm năng và những khu vực cần cải thiện chiến lược bán hàng.
low_deve <- Sold_asia[Sold_asia$PhatTrien == "Phát triển chậm",]
head(low_deve)
## country Item Units.Sold Total.Profit PhatTrien
## 29 Bhutan Beverages 4248.295 66528.31 Phát triển chậm
## 30 Brunei Beverages 4415.531 69147.21 Phát triển chậm
## 35 Japan Beverages 4144.375 64900.91 Phát triển chậm
## 39 Malaysia Beverages 4660.028 72976.04 Phát triển chậm
## 40 Maldives Beverages 4088.022 64018.43 Phát triển chậm
## 46 Singapore Beverages 4354.763 68195.59 Phát triển chậm
Nhận xét:Danh sách các nước thuộc nhóm “phát triển chậm” được trích lọc để phân tích riêng, từ đó đề xuất giải pháp như tăng quảng cáo, thay đổi chính sách giá, hay mở rộng kênh phân phối để cải thiện hiệu quả kinh doanh.