LỜI CẢM ƠN

Em xin bày tỏ lòng biết ơn đặc biệt đến ThS. Trần Mạnh Tường – người đã tận tình dìu dắt và truyền đạt kiến thức trong suốt thời gian qua. Nhờ sự hướng dẫn tâm huyết và những lời khuyên quý báu của Thầy, em đã có thể hoàn thành bài báo cáo tiểu luận này một cách trọn vẹn nhất. Vô cùng trân trọng những bài học quý giá mà Thầy đã dành cho, không chỉ về kiến thức chuyên môn mà còn về thái độ học tập và làm việc nghiêm túc, trách nhiệm.

Em nhận thức được rằng bài báo cáo này vẫn còn tồn tại một số hạn chế và thiếu sót. Xin chân thành mong nhận được những góp ý quý báu từ thầy để em có thể hoàn thiện bản thân và đạt được kết quả tốt hơn trong học tập và công việc sau này.

Cuối cùng, xin kính chúc quý thầy sức khỏe, dồi dào nhiệt huyết và thành công trong sự nghiệp trồng người. Em xin chân thành cảm ơn!

LỜI CAM KẾT

Em xin cam đoan số liệu và kết quả nghiên cứu trong bài tiểu luận này là trung thực và các thông tin trích dẫn trong báo cáo đã được chỉ rõ nguồn gốc rõ ràng và được phép công bố.

KẾT CẤU

Bài báo cáo tiểu luận của nhóm chúng em bao gồm 2 phần:

  • Phần 1: Phân tích tiêu thụ điện năng ở Vương quốc Anh: giai đoạn 2009 - 2024

  • Phần 2: Phân tích CTCP Chứng khoán SSI thông qua báo cáo tài chính: giai đoạn 2015 - 2024

Hai chương là hai phần nội dung tách biệt nhau.

PHẦN 1: PHÂN TÍCH TIÊU THỤ ĐIỆN NĂNG Ở VƯƠNG QUỐC ANH: GIAI ĐOẠN 2009 - 2024

Ở phần 1, em đã sử dụng bộ dữ liệu về lịch sử tiêu thụ điện năng ở Vương quốc Anh trong khoảng thời gian từ năm 2009 đến năm 2024 được lấy từ nguồn Kaggle - một nền tảng trực tuyến cho cộng đồng khoa học dữ liệu. Bộ dữ liệu được National Grid ESO - đơn vị vận hành hệ thống điện cho Vương quốc Anh thu thập và được cập nhật hai lần mỗi giờ, tức có nghĩa là có 48 mục mỗi ngày.

Tải các gói thư viện cần thiết

library(dplyr)
library(lubridate)
library(ggplot2)
library(scales)
library(knitr)
library(kableExtra)
library(igraph)
library(ggraph)
library(treemapify)
library(rnaturalearth)
library(rnaturalearthdata)
library(sf)
library(patchwork)
library(tibble)
library(tidyr)
library(psych)
library(tidyverse)
library(corrr)

- Giải thích kỹ thuật: Sử dụng hàm library() để khai báo các thư viện cần thiết .

- Giải thích ỹ nghĩa: Các thư viện như dplyr, lubridate, ggplot2, scales, knitr, tidyr, psych, … được cài đặt và tải lên để đảm bảo môi trường làm việc có đủ các công cụ cần thiết cho việc đọc, xử lý, phân tích và trực quan hóa dữ liệu.

1. Giới thiệu bộ dữ liệu (10 thao tác)

1.1: Đọc dữ liệu từ tệp CSV

dataUK <- read.csv("dataUK.csv") 

Giải thích code: dùng hàm read.csv để đọc dữ liệu từ tệp có định dạng CSV, sau đó dùng toán tử gán “<-” để tạo ra data frame có tên là dataUK và lưu trữ toàn bộ nội dung đã đọc được từ tệp CSV.

Ý nghĩa của kết quả: Bộ dữ liệu đã được đọc và được lưu trong một data frame tên là dataUK để thuận tiện cho việc xử lý và phân tích ở các bước tiếp theo.

1.2: Kiểm tra kích thước của bộ dữ liệu

dim(dataUK) 
## [1] 278512     19

Giải thích code: dùng hàm dim() để lấy ra một vector chứa 2 giá trị số nguyên: [số hàng, số cột] của data frame dataUK.

Ý nghĩa của kết quả: Bộ dữ liệu có tất cả 278512 hàng (tức 278512 quan sát) và 19 cột (tức 19 biến).

1.3: Kiểm tra các giá trị bị thiếu (NA) trên mỗi cột

colSums(is.na(dataUK)) 
##           settlement_date         settlement_period               period_hour 
##                         0                         0                         0 
##                        nd                       tsd      england_wales_demand 
##                         0                         0                         0 
##  embedded_wind_generation    embedded_wind_capacity embedded_solar_generation 
##                         0                         0                         0 
##   embedded_solar_capacity               non_bm_stor      pump_storage_pumping 
##                         0                         0                         0 
##                  ifa_flow                 ifa2_flow              britned_flow 
##                         0                         0                         0 
##                moyle_flow            east_west_flow                 nemo_flow 
##                         0                         0                         0 
##                is_holiday 
##                         0

Giải thích code: dùng hàm is.na() để xác định các giá trị thiếu, sau đó dùng hàm colSums() để đếm số lượng các giá trị thiếu đó cho từng biến (cột).

Ý nghĩa của kết quả: Bộ dữ liệu không có giá trị bị thiếu.

1.4: Kiểm tra số lượng quan sát trùng lặp

sum(duplicated(dataUK))
## [1] 0

Giải thích code: dùng hàm duplicated() để tìm tất cả các hàng trùng lặp, sau đó dùng hàm sum() để tổng số lượng các hàng trùng lặp đó.

Ý nghĩa của kết quả: Bộ dữ liệu không có hiện tượng trùng lặp.

1.5: Kiểm tra cấu trúc bộ dữ liệu

sapply(dataUK, class)
##           settlement_date         settlement_period               period_hour 
##               "character"                 "integer"               "character" 
##                        nd                       tsd      england_wales_demand 
##                 "integer"                 "integer"                 "integer" 
##  embedded_wind_generation    embedded_wind_capacity embedded_solar_generation 
##                 "integer"                 "integer"                 "integer" 
##   embedded_solar_capacity               non_bm_stor      pump_storage_pumping 
##                 "integer"                 "integer"                 "integer" 
##                  ifa_flow                 ifa2_flow              britned_flow 
##                 "integer"                 "integer"                 "integer" 
##                moyle_flow            east_west_flow                 nemo_flow 
##                 "integer"                 "integer"                 "integer" 
##                is_holiday 
##                 "integer"

Giải thích code: đoạn code được dùng để liệt kê kiểu dữ liệu của mọi biến (cột) trong data frame dataUK.

Ý nghĩa của kết quả: Trong 19 biến, có 17 biến định lượng (integer) và 2 biến định tính (character).

1.6: Xem 10 dòng dữ liệu đầu tiên

dataUK %>%
  head(10) %>%
  select(settlement_date, settlement_period, nd, tsd, england_wales_demand, is_holiday) %>%
  kable(format = "latex", booktabs = TRUE, caption = "10 dòng đầu tiên của bộ dữ liệu") %>%
  kable_styling(latex_options = c("hold_position", "striped", "scale_down"), position = "center", font_size = 9)

Giải thích code:

  • (2): dùng hàm head() để chọn và lấy 10 dòng đầu tiên của data frame dataUK.

  • (3): dùng hàm select() để chọn lọc và giữ lại 6 biến cần quan sát từ 10 dòng dữ liệu vừa trích xuất.

  • (4): dùng hàm kable() để chuyển đổi tập dữ liệu đã lọc thành một bảng; tham số format = “latex” được dùng để định dạng đầu ra cho bảng; tham số booktabs = TRUE được dùng để sử dụng các quy tắc định dạng bảng chất lượng cao; tham số caption = “…” được dùng để thêm tiêu đề cho bảng.

  • (5): dùng hàm kable_styling để áp dụng các tùy chỉnh định dạng nâng cao cho bảng; tham số latex_options = c(…) dùng để thêm các tùy chỉnh đặc biệt như “hold_position”, “striped” - tạo hiệu ứng sọc ngang, “scale_down” - thu nhỏ kích thước bảng; tham số position = “center” dùng để căn giữa bảng trên trang; tham số font_size = 9 dùng để đặt cỡ chữ của bảng là 9 point.

Ý nghĩa của kết quả: Kết quả cho ra bảng xem trước của 10 dòng dữ liệu đầu tiên.

1.7: Đếm tần suất của biến nhị phân

table(dataUK$is_holiday) 
## 
##      0      1 
## 272272   6240

Giải thích code: dùng hàm table() để đếm tần suất của các giá trị riêng biệt trong cột dữ liệu is_holiday.

Ý nghĩa của kết quả: Trong 278512 quan sát của bộ dữ liệu, với biến nhị phân “is_holiday”, tần suất xuất hiện của giá trị 0 là 272272 quan sát và tần suất xuất hiện của giá trị 1 là 6240 quan sát (giá trị 0 biểu thị ngày thường, giá trị 1 biểu thị ngày lễ).

1.8: Kiểm tra thứ tự sắp xếp

is.unsorted(dataUK$settlement_period) 
## [1] TRUE

Giải thích code: dùng hàm is.unsorted() để kiểm tra xem cột dữ liệu settlement_period có bị sắp xếp sai thứ tự hay không.

Ý nghĩa của kết quả: Kết quả cho thấy rằng cột dữ liệu “settlement_period” chưa được sắp xếp theo thứ tự tăng dần, tức là các giá trị trong cột này nằm lộn xộn, không có trật tự. Lý giải cho điều này là bởi vì dữ liệu được thu thập 2 lần mỗi giờ, tức là 48 lần mỗi ngày, và sang ngày hôm sau chu trình này tiếp tục diễn ra. Do đó, khi kiểm tra cột “settlement_period”, chúng ta sẽ thấy kết quả cho ra từ hàm “is.unsorted()” là TRUE.

1.9: Liệt kê tên các cột

names(dataUK) 
##  [1] "settlement_date"           "settlement_period"        
##  [3] "period_hour"               "nd"                       
##  [5] "tsd"                       "england_wales_demand"     
##  [7] "embedded_wind_generation"  "embedded_wind_capacity"   
##  [9] "embedded_solar_generation" "embedded_solar_capacity"  
## [11] "non_bm_stor"               "pump_storage_pumping"     
## [13] "ifa_flow"                  "ifa2_flow"                
## [15] "britned_flow"              "moyle_flow"               
## [17] "east_west_flow"            "nemo_flow"                
## [19] "is_holiday"

Giải thích code: dùng hàm names() để lấy ra một danh sách chuỗi văn bản (character vector), trong đó mỗi chuỗi là tên của một biến (cột) trong bộ dữ liệu dataUK.

Ý nghĩa của kết quả: Danh sách tên của 19 biến, tương ứng với 19 cột lần lượt là:

  1. settlement_date

  2. settlement_period

  3. period_hour

  4. nd

  5. tsd

  6. england_wales_demand

  7. embedded_wind_generation

  8. embedded_wind_capacity

  9. embedded_solar_generation

  10. embedded_solar_capacity

  11. non_bm_stor

  12. pump_storage_pumping

  13. ifa_flow

  14. ifa2_flow

  15. britned_flow

  16. moyle_flow

  17. east_west_flow

  18. nemo_flow

  19. is_holiday

1.10: Bảng tổng hợp các biến số

data_summary_UK <- data.frame(
  Ten_cot = names(dataUK), 
  Giai_thich = c(
    "ngày ghi nhận dữ liệu theo định dạng dd/mm/yy",
    "chu kỳ nửa giờ cho sản lượng lịch sử đã xảy ra",
    "Giờ trong ngày (được làm tròn đến giờ tiếp theo)",
    "tổng sản lượng điện được đo đếm trên công tơ đo đếm phát điện vận hành của National Grid ESO",
    "bằng nd cộng với sản lượng điện bổ sung cần thiết để đáp ứng tải tại các trạm, bơm tích trữ và xuất khẩu liên kết",
    "nhu cầu của Anh và xứ Wales, như nd ở trên nhưng dựa trên cơ sở Anh và xứ Wales",
    "ước tính sản lượng điện gió của Vương quốc Anh từ các trang trại gió không lắp đặt công tơ đo đếm Hệ thống truyền tải",
    "là góc nhìn tốt nhất của National Grid ESO về công suất điện gió nhúng đã lắp đặt tính bằng GB",
    "ước tính sản lượng điện mặt trời của GB từ các tấm pin quang điện",
    "dành cho các đơn vị không được bao gồm trong định nghĩa máy phát điện ND. Điều này có thể ở dạng giảm phát điện hoặc giảm nhu cầu",
    "nhu cầu do bơm tại các đơn vị lưu trữ bơm thủy điện; -ve biểu thị tải bơm",
    "nhu cầu do bơm tại các đơn vị lưu trữ bơm thủy điện; -ve biểu thị tải bơm",
    "dòng chảy trên liên kết tương ứng, -ve biểu thị công suất xuất ra từ GB; +ve biểu thị công suất nhập vào GB",
    "lưu lượng trên liên kết tương ứng. -ve biểu thị công suất xuất ra từ Vương quốc Anh; +ve biểu thị công suất nhập vào Vương quốc Anh",
    "lưu lượng trên liên kết tương ứng. -ve biểu thị công suất nhập vào Vương quốc Anh; +ve biểu thị công suất xuất ra từ Vương quốc Anh",
    "dòng chảy trên liên kết tương ứng. -ve biểu thị công suất xuất ra từ GB; +ve biểu thị công suất nhập vào GB",
    "lưu lượng trên liên kết tương ứng. -ve biểu thị công suất xuất ra từ Vương quốc Anh; +ve biểu thị công suất nhập vào Vương quốc Anh",
    "lưu lượng trên liên kết tương ứng. -ve biểu thị công suất xuất ra từ Vương quốc Anh; +ve biểu thị công suất nhập vào Vương quốc Anh",
    "biến nhị phân (1 = Ngày lễ, 0 = Ngày thường)"
  ),
  Đơn_vị_tính = c(
    "",
    "",
    "",
    "MW",                      
    "MW",                       
    "MW",                       
    "MW",                      
    "MW",                       
    "MW",                     
    "MW",                       
    "MW",                      
    "MW",                       
    "MW",                       
    "MW",                       
    "MW",
    "MW",
    "MW",
    "MW",                     
    "Binary (0/1)"))
kable(data_summary_UK, 
      caption = "Bảng mô tả tổng hợp dữ liệu", 
      col.names = c("Tên biến", "Ý nghĩa", "Đơn vị tính"),
      col.names.align = 'c',
      align = c('l', 'l', 'c'),
      format = "latex",
      booktabs = TRUE) %>% 
  kable_styling(
    latex_options = c("striped", "hold_position", "scale_down"),
    full_width = F, 
    position = "center")

Giải thích code:

  • (2): tạo cột tên “Ten_cot” bằng cách trích xuất vector tên cột từ data frame dataUK.

  • (3)->(23): tạo cột tên “Giai_thich” bằng cách dùng hàm c() tạo ra một vector chuỗi ký tự chứa các giải thích ý nghĩa chi tiết cho từng biến tương ứng.

(24)->(44): tạo cột tên “Don_vi_tinh” bằng cách dùng hàm c() tạo ra một vector chuỗi ký tự chứa đơn vị tính của từng biến tương ứng.

  • (46)->(57): dùng hàm kable() cùng các tham số định dạng và tùy chỉnh nâng cao để tạo bảng tổng hợp.

  • Ý nghĩa của kết quả: Ta có được Bảng mô tả chi tiết các biến trong bộ dữ liệu.

    2. Xử lý dữ liệu thô, mã hóa dữ liệu (10 thao tác)

    2.1: Xử lý dữ liệu

    processed_data <- dataUK %>%
      mutate(
        settlement_date = dmy_hm(settlement_date), 
        year = year(settlement_date),
        month = month(settlement_date, label = TRUE, abbr = FALSE),
        weekday = wday(settlement_date, label = TRUE, abbr = FALSE),
        hour = as.numeric(substr(period_hour, 1, 2)))

    Giải thích code:

    • (1): tạo data frame mới tên là processed_data bằng cách thực hiện một chuỗi biến đổi trên data frame dataUK.

    • (2): thực hiện các biến đổi trên các cột đã có hoặc tạo các cột mới.

    • (3): chuyển đổi cột dữ liệu settlement_date sang định dạng ngày giờ chuẩn của R.

    • (4): trích xuất giá trị năm dưới dạng số nguyên từ cột settlement_date gán vào cột mới tên year.

    • (5): trích xuất giá trị tháng từ cột settlement_date, trả về tên tháng đầy đủ và gán vào cột mới tên month.

    • (6): trích xuất giá trị ngày trong tuần từ cột settlement_date, trả về tên ngày đầy đủ và gán vào cột mới tên weekday.

    • (7): trích xuất chuỗi ký tự bắt đầu từ vị trí thứ 1 và kết thúc ở vị trí thứ 2, sau đó chuyển đổi thành giá trị số nguyên và gán vào cột mới tên hour.

    Ý nghĩa của kết quả: Chuẩn hóa biến thời gian settlement_date và trích xuất các biến định danh/thứ tự liên quan đến thời gian (year, month, weekday, hour). Đây là bước quan trọng trong phân tích chuỗi thời gian để nắm bắt các yếu tố chu kỳ và mùa vụ.

    2.2: Xóa các biến số không cần thiết

    processed_data$non_bm_stor <- NULL 
    processed_data$pump_storage_pumping <- NULL 

    Giải thích code: cả 2 dòng code (1) và (2) đều dùng toán tử “$” để truy cập vào cột non_bm_stor và cột pump_storage_pumping trong data frame processed_data vừa được tạo ở thao tác trước, sau đó gán giá trị NULL vào 2 cột này để xóa vĩnh viễn 2 biến dữ liệu này ra khỏi data frame.

    Ý nghĩa của kết quả: Hai biến non_bm_storpump_storage_pumping đã được xóa.

    2.3: Tạo 2 biến mới

    processed_data <- processed_data %>% 
      mutate(
        total_flow = ifa_flow + ifa2_flow + britned_flow + moyle_flow + east_west_flow + nemo_flow,
        embedded_ratio = (embedded_wind_generation + embedded_solar_generation)/nd)

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3), (4): tạo 2 cột mới có tên lần lượt là total_flow: Tổng đại số của các luồng điện qua các đường dây kết nối (interconnectors: IFA, IFA2, Britned, Moyle, East-West, Nemo) và embedded_ratio: Tỷ lệ giữa tổng sản lượng điện gió và mặt trời phân tán (embedded_wind_generation + embedded_solar_generation) so với Nhu cầu Quốc gia (nd).

    Ý nghĩa của kết quả: 2 biến mới xuất hiện trong data frame processed_data, trong đó:
    • total_flow đại diện cho Lưu lượng điện ròng (Net Flow) giữa hệ thống điện Anh và các nước lân cận. Giá trị dương/âm thể hiện nhập/xuất khẩu điện ròng, rất quan trọng để phân tích an ninh năng lượng.
    • embedded_ratio là một chỉ số tập trung (concentration index), đo lường tỷ trọng đóng góp của năng lượng tái tạo phân tán vào tổng nhu cầu điện, phản ánh mức độ thâm nhập của năng lượng sạch.

    2.4: Phân tổ dữ liệu theo mùa

    processed_data <- processed_data %>%
      mutate(
        season = case_when(
          month %in% c("December", "January", "February") ~ "Winter",
          month %in% c("March", "April", "May") ~ "Spring",
          month %in% c("June", "July", "August") ~ "Summer",
          month %in% c("September", "October", "November") ~ "Autumn"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên season và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4)->(7): các điều kiện bên trong hàm case_when(), dùng toán tử “%in%” để kiểm tra xem giá trị của cột month có nằm trong các tập hợp chuỗi ký tự được quy ước hay không, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột season.

    Ý nghĩa của kết quả: Mã hóa yếu tố Mùa vụ (Seasonality) bằng việc phân tổ dữ liệu theo mùa dựa trên các tháng, cho phép các phân tích thống kê và xây dựng mô hình dự báo chính xác hơn.

    2.5: Phân tổ dữ liệu theo buổi trong ngày

    processed_data <- processed_data %>%
      mutate(
        time_of_day = case_when(
          hour >= 5 & hour < 12 ~ "Morning",
          hour >= 12 & hour < 17 ~ "Afternoon",
          hour >= 17 & hour < 22 ~ "Evening",
          TRUE ~ "Night"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên time_of_day và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4)->(7): các điều kiện bên trong hàm case_when(), dùng toán tử so sánh “>,<,=” cùng với toán tử logic “&” để kiểm tra xem giá trị của cột hour có nằm trong các khoảng được quy ước hay không, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột time_of_day.

    Ý nghĩa của kết quả: Mã hóa yếu tố Chu kỳ ngày (Diurnal Cycle) bằng việc phân tổ dữ liệu theo các buổi trong ngày dựa trên giờ, giúp xác định và phân tích các mẫu hành vi của người tiêu dùng và nhà sản xuất điện tại các thời điểm quan trọng trong ngày.

    2.6: Phân tổ dữ liệu loại ngày

    processed_data <- processed_data %>%
      mutate(
        day_group = case_when(
          is_holiday == 1 ~ "Ngày lễ",
          is_holiday == 0 ~ "Ngày thường"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên day_group và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4), (5): các điều kiện bên trong hàm case_when(), dùng toán tử so sánh “==” để kiểm tra xem giá trị của cột is_holiday có bằng giá trị được quy ước hay không, nếu bằng 1 thì là Ngày lễ còn nếu bằng 0 thì là Ngày thường, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột day_group.

    Ý nghĩa của kết quả: Mã hóa yếu tố Ngày lễ/Ngày thường. Hành vi sử dụng điện trong Ngày lễ (hoặc cuối tuần) thường khác biệt đáng kể so với Ngày thường (do các hoạt động công nghiệp, thương mại… giảm). Việc phân tổ này giúp phân lập ảnh hưởng của các ngày nghỉ lễ lên nhu cầu và cung cấp điện so với ngày thường ở mức độ như thế nào.

    2.7: Phân tổ dữ liệu theo Nhu cầu Quốc gia

    processed_data <- processed_data %>%
      mutate(
        nd_group = case_when(
          nd <= 20000 ~ "Nhu cầu thấp",
          nd > 20000 & nd <= 40000 ~ "Nhu cầu trung bình",
          nd > 40000 ~ "Nhu cầu cao"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên nd_group và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4), (5), (6): các điều kiện bên trong hàm case_when(), dùng toán tử so sánh “>,<,=” cùng với toán tử logic “&” để kiểm tra xem giá trị của cột nd có nằm trong các khoảng được quy ước hay không, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột nd_group.

    Ý nghĩa của kết quả: Phân tổ theo Quy mô nhu cầu. Việc phân tổ này cho phép phân tích hoặc mô hình hóa tác động của các yếu tố khác nhau lên các mức độ nhu cầu cụ thể, thay vì chỉ trên nhu cầu liên tục.

    2.8: Phân tổ dữ liệu theo năm ghi nhận

    processed_data <- processed_data %>%
      mutate(
        year_group = case_when(
          year <= 2012 ~ "Early Period",
          year > 2012 & year <= 2016 ~ "Mid Period",
          year > 2016 & year <= 2020 ~ "Later Period",
          TRUE ~ "Recent Period"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên year_group và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4)->(7): các điều kiện bên trong hàm case_when(), dùng toán tử so sánh “>,<,=” cùng với toán tử logic “&” để kiểm tra xem giá trị của cột year có nằm trong các khoảng được quy ước hay không, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột year_group.

    Ý nghĩa của kết quả: Mã hóa yếu tố Thời kỳ phát triển, cho phép phân tích sự thay đổi cấu trúc của hệ thống điện qua các giai đoạn khác nhau.

    2.9: Phân tổ dữ liệu theo mức độ dòng chảy kết nối (interconnector flow)

    processed_data <- processed_data %>%
      mutate(
        flow_group = case_when(
          total_flow < -2000 ~ "Large Net Export",
          total_flow >= -2000 & total_flow < -500 ~ "Moderate Net Export",
          total_flow >= -500 & total_flow <= 500 ~ "Near Balance",
          total_flow > 500 & total_flow <= 2000 ~ "Moderate Net Import",
          total_flow > 2000 ~ "Large Net Import"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên flow_group và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4)->(8): các điều kiện bên trong hàm case_when(), dùng toán tử so sánh “>,<,=” cùng với toán tử logic “&” để kiểm tra xem giá trị của cột total_flow có nằm trong các khoảng được quy ước hay không, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột flow_group.

    Ý nghĩa của kết quả: Phân tổ theo Cán cân thương mại điện năng, giúp phân loại các tình huống vận hành quan trọng, rất hữu ích cho việc phân tích ảnh hưởng của giao thương điện lên giá điện nội địa và các vấn đề khác.

    2.10: Phân tổ dữ liệu theo chỉ số “embedded_ratio”

    processed_data <- processed_data %>%
      mutate(
        em_ra_group = case_when(
        embedded_ratio <= 0.05 ~ "Very Low Renewable Impact",
        embedded_ratio > 0.05 & embedded_ratio <= 0.15 ~ "Low Renewable Impact",
        embedded_ratio > 0.15 & embedded_ratio <= 0.3 ~ "Medium Renewable Impact",
        TRUE ~ "High Renewable Impact"))

    Giải thích code:

    • (1): cập nhật chính data frame processed_data.

    • (2), (3): tạo cột mới có tên em_ra_group và dùng hàm case_when() để thực hiện phân loại có điều kiện.

    • (4)->(7): các điều kiện bên trong hàm case_when(), dùng toán tử so sánh “>,<,=” cùng với toán tử logic “&” để kiểm tra xem giá trị của cột embedded_ratio có nằm trong các khoảng được quy ước hay không, sau đó dùng toán tử ~ để gán giá trị quy ước tương ứng cho cột em_ra_group.

    Ý nghĩa của kết quả: Phân tổ theo Tác động của năng lượng tái tạo phân tán. Việc phân loại này giúp nghiên cứu mối quan hệ phi tuyến tính giữa mức độ thâm nhập của năng lượng tái tạo phân tán và các biến số vận hành hệ thống, cho phép so sánh các trường hợp khi năng lượng tái tạo chiếm tỷ trọng rất thấp, thấp, trung bình và cao.

    3. Thống kê cơ bản (20 thao tác)

    3.1: Tính toán và hiển thị các thống kê mô tả cơ bản cho biến định lượng nd

    des_nd <- describe(processed_data$nd) 
    des_nd %>%
      kable(format = "latex", caption = "Bảng thống kê mô tả biến nd", booktabs = TRUE) %>%
      kable_styling(latex_options = c("striped", "hold_position", "scale_down"))

    Giải thích code:

    • (1): dùng toán tử “$” để truy cập vào cột nd của data frame processed_data, sau đó dùng hàm describe() để tính toán một loạt các số liệu thống kê mô tả và dùng toán tử gán “<-” để lưu trữ kết quả vào đối tượng mới tên là des_nd.

    • (2)->(4): dùng hàm kable(), kable_styling() cùng với các tham số định dạng và tùy chỉnh nâng cao để tạo ra bảng thống kê mô tả cho biến nd.

    Ý nghĩa của kết quả: Biến nd có giá trị trung bình (mean) là 31,187.04 MW; độ lệch chuẩn (sd) = 7,831.31 cho thấy mức biến động lớn; giá trị trung vị (median) là 30,491 MW; giá trị trung bình hiệu chỉnh sau khi loại 10% dữ liệu ở hai đầu (trimmed) là 30,826.31 MW; độ lệch tuyệt đối trung vị (mad)là 8,814.8 MW; giá trị nhỏ nhất (min) = 13,367 MW; giá trị lớn nhất (max) = 59,095 MW; khoảng biến thiên (range) là 45,258; độ xiên (skew) = 0.38, dương, phân phối xiên phải, phần đuôi của đồ thị phân phối biến nd kéo dài về phía bên phải. Điều này có nghĩa là có một số lượng nhỏ các giá trị cực đoan cao (ngoại lai dương) kéo giá trị trung bình lên cao hơn so với trung vị; độ nhọn (kurtosis) = -0.49, âm, cho thấy phân phối dẹt hơn so với phân phối chuẩn (platykurtic), tức là ít ngoại lai cực đoan hơn; và sai số chuẩn trung bình (se) là 14.84, ước tính độ chính xác của giá trị trung bình mẫu, chứng tỏ rằng nếu bạn lặp lại quá trình lấy mẫu và tính toán giá trị trung bình nhiều lần, trung bình mẫu của bạn sẽ dao động xung quanh trung bình thực của tổng thể với độ biến thiên xấp xỉ \(14.84\) đơn vị.

    3.2: tính toán tần suất (số lượng) và tỷ lệ phần trăm của các quan sát trong tập dữ liệu theo từng mùa (season)

    season_counts <- table(processed_data$season) 
    season_props <- prop.table(season_counts)*100 
    season_summary <- data.frame( 
      Mùa = names(season_counts), 
      Số_lượng = as.numeric(season_counts),
      Tỷ_lệ_phần_trăm = round(as.numeric(season_props), 2) 
    )
    kable( 
      season_summary, 
      caption = "**Tần suất theo mùa**", 
      align = c('l', 'c', 'c') )
    Tần suất theo mùa
    Mùa Số_lượng Tỷ_lệ_phần_trăm
    Autumn 69840 25.08
    Spring 70480 25.31
    Summer 70128 25.18
    Winter 68064 24.44

    Giải thích code:

    • (1): tính toán tần suất của mỗi giá trị duy nhất (mỗi mùa) trong cột season của data frame processed_data.

    • (2): chuyển đổi tần suất thô (season_counts) thành tỷ lệ tương đối bằng cách chia mỗi số đếm cho tổng số quan sát.

    • (3)->(7): kết hợp các kết quả tần suất và tỷ lệ vào một data frame tên là season_summary có cấu trúc để dễ dàng trình bày.

    • (8)->(12): dùng hàm kable() cùng các tham số để tạo và định dạng bảng.

    Ý nghĩa của kết quả: Bảng thống kê tần suất theo mùa được tạo, trong đó:
    • Mùa xuân (Spring) có 70480 quan sát, chiếm 25.31%.
    • Mùa hè (Summer) có 70128 quan sát, chiếm 25.18%.
    • Mùa thu (Autumn) có 69840 quan sát, chiếm 25.08%.
    • Mùa đông (Winter) có 68064 quan sát, chiếm 24.44%.

    3.3: Tính toán tần suất (số lượng quan sát) và tỷ lệ phần trăm của các nhóm luồng điện tổng thể (flow_group) và sắp xếp kết quả theo thứ tự giảm dần

    flow_distribution <- processed_data %>% 
      group_by(flow_group) %>% 
      tally(name = "Số_lượng_quan_sát") %>% 
      mutate(Tỷ_lệ_phần_trăm = round(Số_lượng_quan_sát / sum(Số_lượng_quan_sát) * 100, 2)) %>% 
      arrange(desc(Số_lượng_quan_sát)) 
    kable( 
      flow_distribution, 
      caption = "**Phân phối Tổng dòng chảy kết nối (Total Flow)**", 
      align = 'c')
    Phân phối Tổng dòng chảy kết nối (Total Flow)
    flow_group Số_lượng_quan_sát Tỷ_lệ_phần_trăm
    Large Net Import 124235 44.61
    Moderate Net Import 86025 30.89
    Near Balance 29309 10.52
    Moderate Net Export 26605 9.55
    Large Net Export 12338 4.43

    Giải thích code:

    • (1)->(5): thực hiện phân tích phân phối tần suất (và tỷ lệ tương đối) của biến flow_group bằng cách nhóm dữ liệu, đếm tần suất của mỗi nhóm, tính tỷ lệ phần trăm, và cuối cùng là sắp xếp kết quả theo tần suất giảm dần.

    • (6)->(10): dùng hàm kable() cùng các tham số để tạo và định dạng bảng.

    Ý nghĩa của kết quả: Bảng thống kê phân phối tổng dòng chảy được tạo, trong đó:
    • Nhóm Large Net Import có số quan sát nhiều nhất là 124235, chiếm tỉ lệ cao nhất là 44.61%.
    • Nhóm Large Net Export có số quan sát ít nhất là 12338, chiếm tỉ lệ thấp nhất là 4.43%.

    3.4: Tính toán Ma trận Hệ số Tương quan tuyến tính Pearson

    selected_vars <- processed_data %>%
      select(nd, tsd, embedded_wind_generation, embedded_solar_generation, total_flow) 
    correlation_matrix <- cor(selected_vars, use = "complete.obs") 
    rounded_matrix <- round(correlation_matrix, 4) 
    kable( rounded_matrix, caption = "**Ma trận Hệ số Tương quan**", align = 'c')
    Ma trận Hệ số Tương quan
    nd tsd embedded_wind_generation embedded_solar_generation total_flow
    nd 1.0000 0.9920 -0.1577 -0.1543 -0.1081
    tsd 0.9920 1.0000 -0.1500 -0.1720 -0.1985
    embedded_wind_generation -0.1577 -0.1500 1.0000 0.1619 0.0393
    embedded_solar_generation -0.1543 -0.1720 0.1619 1.0000 0.1436
    total_flow -0.1081 -0.1985 0.0393 0.1436 1.0000

    Giải thích code: sử dùng hàm select() để tạo một tập dữ liệu mới có tên selected_vars, chỉ chứa các cột nd, tsd, embedded_wind_generation, embedded_solar_generation, và total_flow từ data frame processed_data. Sau đó, dùng hàm cor() để tính toán ma trận hệ số tương quan giữa các biến đã chọn. Tham số use = “complete.obs” đảm bảo rằng mọi hàng có giá trị bị thiếu sẽ bị loại bỏ khỏi tính toán. Sau đó, hàm round() làm tròn các giá trị trong ma trận tương quan đến bốn chữ số thập phân. Cuối cùng, dùng hàm kable() để tạo ra bảng.

    Kết quả:

    • \(\mathbf{r}(\text{nd}, \text{tsd}) = 0.9920\): tương quan dương cực kỳ mạnh, gần như giống hệt nhau về mặt tuyến tính.

    • \(\mathbf{r}(\text{nd}, \text{embedded\_wind\_generation}) = -0.1577\): tương quan âm rất yếu, cho thấy mối liên hệ nghịch biến.

    • \(\mathbf{r}(\text{nd}, \text{embedded\_solar\_generation}) = -0.1543\): tương quan âm rất yếu, cho thấy mối liên hệ nghịch biến.

    • \(\mathbf{r}(\text{total\_flow}, \text{nd}) = -0.1081\): tương quan âm rất yếu, cho thấy mối liên hệ nghịch biến.

    3.5: Phân tích Phương sai một chiều (One-Way ANOVA) để kiểm tra xem có sự khác biệt đáng kể về mặt thống kê về mức nhu cầu (nd) giữa các nhóm năm (year_group) hay không.

    processed_data$year_group <- as.factor(processed_data$year_group)
    anova_model <- aov(nd ~ year_group, data = processed_data)
    anova_summary <- summary(anova_model)
    print(anova_summary)
    ##                 Df    Sum Sq   Mean Sq F value Pr(>F)    
    ## year_group       3 3.242e+12 1.081e+12   21747 <2e-16 ***
    ## Residuals   278508 1.384e+13 4.969e+07                   
    ## ---
    ## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

    Giải thích code: chuẩn bị biến nhóm bằng cách chuyển nó thành biến yếu tố, sau đó lắp mô hình ANOVA một yếu tố để đánh giá sự khác biệt về mặt thống kê của giá trị trung bình nd giữa các nhóm year_group bằng cách sử dụng kiểm định F.

    Ý nghĩa của kết quả: Giá trị P (Pr(>F)) < 2e-16, giá trị cực kỳ nhỏ, gần như bằng 0, suy ra bác bỏ giả thuyết \(H_0\): Giá trị trung bình của nd là như nhau giữa tất cả các nhóm năm. F value = 21,747, giá trị thống kê F lớn chứng tỏ rằng sự khác biệt quan sát được giữa các nhóm năm là rất lớn so với sự biến thiên bên trong các nhóm đó.

    –> Kết luận: Yếu tố Thời gian (năm) có ảnh hưởng đáng kể đến mức nhu cầu (nd). Điều này phản ánh xu hướng nhu cầu thay đổi theo thời gian, có thể do tăng trưởng dân số, hiệu suất năng lượng, thay đổi khí hậu hoặc xu hướng kinh tế.

    3.6: Tính toán Trung bình Động 24 kỳ (24-period Moving Average - MA) cho biến nd

    ma_nd <- stats::filter( 
      processed_data$nd, 
      filter = rep(1/24, 24), 
      method = "convolution", 
      sides = 1, 
      circular = FALSE)
    processed_data$nd_MA24 <- c(rep(NA, 23), ma_nd[!is.na(ma_nd)]) 
    tail_ma_nd <- tail(processed_data[, c("nd", "nd_MA24")], 10) 
    kable(tail_ma_nd, caption = "**Ví dụ về Trung bình động 24 kỳ của ND**", align = 'c')
    Ví dụ về Trung bình động 24 kỳ của ND
    nd nd_MA24
    278503 36248 36157.04
    278504 34942 36254.33
    278505 33594 36228.62
    278506 32220 36132.50
    278507 30535 35923.62
    278508 29114 35660.50
    278509 27204 35298.00
    278510 26006 34884.58
    278511 23908 34381.67
    278512 23217 33851.67

    Giải thích code:

    • (1)->(6): dùng hàm stats::filter() để lọc tuyến tính biến nd trong data frame processed_data, tham số filter = … cho biết mỗi giá trị MA sẽ là trung bình đơn giản của 24 điểm dữ liệu, tham số method = … lựa chọn phương pháp lọc, tham số sides = … chỉ định rằng bộ lọc chỉ sử dụng các giá trị trước đó, tham số circular = … chỉ định rằng không giả định chuỗi thời gian là tuần hoàn.

    • (7): tạo một biến mới nd_MA24 trong data frame processed_data, chèn 23 giá trị NA vào đầu chuỗi, sau đó nối các giá trị MA hợp l.ệ

    • (8): chọn 10 hàng cuối cùng của hai cột ndnd_MA24.

    • (9): để tạo và hiển thị một bảng kết quả.

    Kết quả:

    3.7: Tính toán giá trị trung bình (mean) và trung vị (median) của tỷ lệ sử dụng năng lượng nhúng (embedded_ratio) riêng biệt cho từng nhóm ngày (day_group)

    ratio_by_day_group <- processed_data %>% 
      group_by(day_group) %>% 
      summarise( 
        Mean_Embedded_Ratio = mean(embedded_ratio, na.rm = TRUE), 
        Median_Embedded_Ratio = median(embedded_ratio, na.rm = TRUE))
    kable(ratio_by_day_group, caption = "**Tỷ lệ sử dụng Năng lượng nhúng trung bình theo loại ngày**", align = 'c')
    Tỷ lệ sử dụng Năng lượng nhúng trung bình theo loại ngày
    day_group Mean_Embedded_Ratio Median_Embedded_Ratio
    Ngày lễ 0.0836409 0.0482291
    Ngày thường 0.0764484 0.0456548

    Giải thích code: gom nhóm dữ liệu theo biến day_group và tính toán các thước đo xu hướng trung tâm (trung bình và trung vị) cho biến embedded_ratio để hiểu sự khác biệt của biến đó giữa các nhóm. Sau đó, kết quả được trình bày dưới dạng bảng sẵn sàng cho báo cáo.

    Ý nghĩa của kết quả:
    • Đối với ngày lễ: Mean = 0.0836409, Median = 0.0482291.
    • Đối với ngày thường: Mean = 0.0764484, Median = 0.0456548.

      –> Sự khác biệt giữa các nhóm ngày: Giá trị trung bình và trung vị của embedded_ratio ở nhóm Ngày lễ đều cao hơn so với nhóm Ngày thường, tức là tỷ lệ nhu cầu được đáp ứng bằng năng lượng nhúng cao hơn vào ngày lễ so với ngày thường. Minh chứng cho điều này là do nhu cầu tổng thể thấp hơn vào ngày nghỉ (do công nghiệp giảm), khiến cùng một lượng sản lượng nhúng chiếm tỷ lệ lớn hơn.

    3.8: Tạo bảng tần số chéo (cross-tabulation) giữa hai biến phân loại (day_group và nd_group)

    cross_tab_nd_day <- table(processed_data$day_group, processed_data$nd_group) 
    prop_table_nd_day <- prop.table(cross_tab_nd_day) * 100 
    kable(cross_tab_nd_day, caption = "**Phân tích chéo giữa loại ngày và nhóm nhu cầu**", align = c('c', 'c', 'c'))
    Phân tích chéo giữa loại ngày và nhóm nhu cầu
    Nhu cầu cao Nhu cầu thấp Nhu cầu trung bình
    Ngày lễ 177 606 5457
    Ngày thường 40230 15038 217004

    Giải thích code: thực hiện thống kê mô tả cơ bản bằng cách phân tích chéo hai biến nhóm day_groupnd_group để xác định mối liên hệ và số lượng quan sát (tần suất) giữa chúng. Sau đó, kết quả được trình bày dưới dạng bảng sẵn sàng cho báo cáo.

    Ý nghĩa của kết quả: Ngày lễ: tập trung Nhu cầu trung bình cao nhất với 5,457 quan sát, theo sau là Nhu cầu thấp với 606 quan sát và Nhu cầu cao là thấp nhất với 177 quan sát. Ngày thường: tập trung Nhu cầu trung bình cao nhất với 217,004 quan sát, theo sau là Nhu cầu cao với 40,230 quan sát và Nhu cầu thấp là thấp nhất với 15,038 quan sát.

    3.9: Tính toán hệ số tương quan tuyến tính Pearson giữa hai biến định lượng: nd và embedded_ratio.

    cor_nd_emratio <- cor(processed_data$nd, processed_data$embedded_ratio) 
    print(paste("Hệ số tương quan giữa nd và embedded_ratio:", cor_nd_emratio)) 
    ## [1] "Hệ số tương quan giữa nd và embedded_ratio: -0.354116168299656"

    Giải thích code: thực hiện bước phân tích mối quan hệ định lượng cơ bản, cụ thể là tìm hiểu xem biến nd và biến embedded_ratio có xu hướng thay đổi cùng nhau một cách tuyến tính hay không, và sau đó trình bày kết quả đó một cách dễ đọc.

    Ý nghĩa của kết quả: Hệ số tương quan giữa ndembedded_ratio là -0.354116168299656 (<0), tương quan âm, nghịch biến.

    3.10: Tính toán giá trị trung bình của biến nd (nhu cầu/demand) dựa trên sự kết hợp của hai yếu tố phân loại: thời điểm trong ngày (time_of_day) và nhóm ngày (day_group).

    mean_nd_by_time_day <- aggregate(nd ~ time_of_day + day_group, data = processed_data, FUN = mean) 
    print("Giá trị trung bình của nd theo time_of_day và day_group:") 
    ## [1] "Giá trị trung bình của nd theo time_of_day và day_group:"
    print(mean_nd_by_time_day) 
    ##   time_of_day   day_group       nd
    ## 1   Afternoon     Ngày lễ 30250.14
    ## 2     Evening     Ngày lễ 32393.14
    ## 3     Morning     Ngày lễ 26426.76
    ## 4       Night     Ngày lễ 24010.99
    ## 5   Afternoon Ngày thường 34498.82
    ## 6     Evening Ngày thường 36246.69
    ## 7     Morning Ngày thường 31359.27
    ## 8       Night Ngày thường 25301.97

    Giải thích code: thống kê mô tả nhằm xác định giá trị trung bình có điều kiện của biến nd và tính giá trị trung bình cho mọi tổ hợp của hai biến phân loại time_of_dayday_group.

    Ý nghĩa của kết quả: Ngày lễ: nhu cầu vào buổi sáng là 26,426.76 MW, vào buổi chiều là 30,250.14 MW, vào buổi tối là 32,393.14 và vào buổi khuya là 24,010.99 MW. Ngày thường: nhu cầu vào buổi sáng là 31,359.27 MW, vào buổi chiều là 34,498.82 MW, vào buổi tối là 36,246.69 và vào buổi khuya là 25,301.97 MW.

    3.11: Tính toán giá trị trung bình của sản lượng điện mặt trời nhúng (embedded_solar_generation) theo từng tháng (month)

    mean_solar_by_month <- aggregate(embedded_solar_generation ~ month, data = processed_data, FUN = mean)
    print("Giá trị trung bình sản lượng mặt trời nhúng theo tháng:")
    ## [1] "Giá trị trung bình sản lượng mặt trời nhúng theo tháng:"
    print(mean_solar_by_month)
    ##        month embedded_solar_generation
    ## 1    January                  273.6083
    ## 2   February                  495.4155
    ## 3      March                  798.1228
    ## 4      April                 1238.7887
    ## 5        May                 1431.1196
    ## 6       June                 1482.9145
    ## 7       July                 1407.6153
    ## 8     August                 1237.1067
    ## 9  September                  986.1375
    ## 10   October                  620.0771
    ## 11  November                  346.4325
    ## 12  December                  207.8900

    Giải thích code: dùng hàm aggregate() để thực phân tích thống kê biến embedded_solar_generation theo nhóm month với tham số FUN = mean chỉ định hàm thống kê được áp dụng cho mỗi nhóm là tính giá trị trung bình (Mean) và lưu trữ vào một data frame mới. Sau đó, in ra nội dung kết quả.

    Kết quả: cho ra sản lượng điện mặt trời nhúng trung bình của từng tháng như sau:

    • Tháng 1: 273.6083 MW

    • Tháng 2: 495.4155 MW

    • Tháng 3: 798.1228 MW

    • Tháng 4: 1,238.7887 MW

    • Tháng 5: 1,431.1196 MW

    • Tháng 6: 1,482.9145 MW

    • Tháng 7: 1,407.6153 MW

    • Tháng 8: 1,237.1067 MW

    • Tháng 9: 986.1375 MW

    • Tháng 10: 620.0771 MW

    • Tháng 11: 346.4325 MW

    • Tháng 12: 207.8900 MW

    –> Sản lượng điện mặt trời nhúng trung bình của tháng 6 là cao nhất và của tháng 12 là thấp nhất.

    3.12: Tính toán giá trị trung bình của sản lượng điện gió nhúng (embedded_wind_generation) theo từng tháng (month)

    mean_wind_by_month <- aggregate(embedded_wind_generation ~ month, data = processed_data, FUN = mean)
    print("Giá trị trung bình sản lượng gió nhúng theo tháng:")
    ## [1] "Giá trị trung bình sản lượng gió nhúng theo tháng:"
    print(mean_wind_by_month)
    ##        month embedded_wind_generation
    ## 1    January                1533.3996
    ## 2   February                1645.8491
    ## 3      March                1396.9221
    ## 4      April                1162.6461
    ## 5        May                1036.6392
    ## 6       June                 975.8777
    ## 7       July                 935.5192
    ## 8     August                1055.0263
    ## 9  September                1130.2600
    ## 10   October                1386.8316
    ## 11  November                1436.0914
    ## 12  December                1600.3519

    Giải thích code: dùng hàm aggregate() để thực phân tích thống kê biến embedded_wind_generation theo nhóm month với tham số FUN = mean chỉ định hàm thống kê được áp dụng cho mỗi nhóm là tính giá trị trung bình (Mean) và lưu trữ vào một data frame mới. Sau đó, in ra nội dung kết quả.

    Kết quả: cho ra sản lượng điện gió nhúng trung bình của từng tháng như sau:

    • Tháng 1: 1,533.3996 MW

    • Tháng 2: 1,645.8491 MW

    • Tháng 3: 1,396.9221 MW

    • Tháng 4: 1,162.6461 MW

    • Tháng 5: 1,036.6392 MW

    • Tháng 6: 975.8777 MW

    • Tháng 7: 935.5192 MW

    • Tháng 8: 1,055.0263 MW

    • Tháng 9: 1,130.2600 MW

    • Tháng 10: 1,386.8316 MW

    • Tháng 11: 1,436.0914 MW

    • Tháng 12: 1,600.3519 MW

    –> Sản lượng điện gió nhúng trung bình của tháng 2 là cao nhất và của tháng 7 là thấp nhất.

    3.13: Tìm giá trị Mode (giá trị xuất hiện nhiều nhất) cho biến phân loại nd_group

    mode_nd_group <- names(sort(table(processed_data$nd_group), decreasing = TRUE)[1])
    print(paste("Mode (giá trị xuất hiện nhiều nhất) của nd_group là:", mode_nd_group))
    ## [1] "Mode (giá trị xuất hiện nhiều nhất) của nd_group là: Nhu cầu trung bình"

    Giải thích code: tính giá trị xuất hiện nhiều nhất (Mode) của biến nd_group bằng cách đếm tần suất, sắp xếp giảm dần, và chọn tên của phần tử có tần suất cao nhất.

    Kết quả: Nhóm nhu cầu trung bình xuất hiện nhiều nhất.

    3.14: Tính toán Hệ số Biến thiên (Coefficient of Variation - CV) cho biến tsd

    cv_tsd <- sd(processed_data$tsd) / mean(processed_data$tsd) 
    cv_tsd * 100 
    ## [1] 23.24795

    Giải thích code: tính toán mức độ biến động tương đối của dữ liệu tsd và biểu thị kết quả dưới dạng phần trăm.

    Kết quả:: Hệ số biến thiên CV có giá trị là 23.24795 tức là xấp xỉ 23.25%, độ lệch chuẩn của biến “tsd” bằng khoảng \(23.25\%\) của giá trị trung bình của nó. Đồng thời, chỉ ra rằng biến “tsd” có mức độ biến động tương đối khoảng \(23.25\%\), khẳng định rằng tsd không phải là một biến cố định; giá trị của nó thay đổi đáng kể so với mức trung bình của nó. Mức độ biến động này cần được xem xét khi xây dựng mô hình dự báo hoặc phân tích rủi ro liên quan đến “tsd”.

    3.15: Tính toán phạm vi (range) và khoảng biến thiên (range difference) của biến total_flow.

    range(processed_data$total_flow) 
    ## [1] -5118  5963
    diff(range(processed_data$total_flow)) 
    ## [1] 11081

    Giải thích code: dùng hàm range() để xác định giới hạn (cận dưới và cận trên) của biến total_flow, sau đó tính toán độ lớn của khoảng cách hai giới hạn đó bằng hàm diff().

    Kết quả: Với biến “total_flow”, giá trị nhỏ nhất là -5,118, giá trị lớn nhất là 5,963 và khoảng cách từ min đến max là 11,081.

    3.16: Tính toán giá trị trung bình của các cột đại diện cho luồng điện qua cáp kết nối (interconnector flows) cho hai nhóm dữ liệu: ngày nghỉ (is_holiday = TRUE) và ngày thường (is_holiday = FALSE).

    flow_cols <- c("ifa_flow", "ifa2_flow", "britned_flow", "moyle_flow", "east_west_flow", "nemo_flow") 
    processed_data %>% 
      group_by(is_holiday) %>% 
      summarise(across(all_of(flow_cols), mean)) 
    ## # A tibble: 2 × 7
    ##   is_holiday ifa_flow ifa2_flow britned_flow moyle_flow east_west_flow nemo_flow
    ##        <int>    <dbl>     <dbl>        <dbl>      <dbl>          <dbl>     <dbl>
    ## 1          0     922.      53.8         506.      -125.          -50.9      176.
    ## 2          1    1098.      61.2         439.      -143.          -60.1      170.

    Giải thích code: tính toán giá trị trung bình của tập hợp các flow, tách biệt giữa ngày lễ và ngày thường.

    Kết quả: Có sự khác biệt về mức độ luồng điện trung bình của hầu hết các cáp kết nối khi so sánh Ngày Nghỉ với Ngày Thường.

    • Giá trị Trung bình Dương (\(\text{ifa\_flow}\), \(\text{ifa2\_flow}\), \(\text{britned\_flow}\), \(\text{nemo\_flow}\)): Cho thấy xu hướng trung bình là xuất khẩu điện (tức là luồng điện ra khỏi hệ thống mà dữ liệu này đại diện, thường là Vương quốc Anh) thông qua các kết nối này.

    • Giá trị Trung bình Âm (\(\text{moyle\_flow}\), \(\text{east\_west\_flow}\)): Cho thấy xu hướng trung bình là nhập khẩu điện (tức là luồng điện đi vào hệ thống) thông qua các kết nối này.

    • Sự khác biệt này cho thấy luồng điện qua cáp kết nối chịu ảnh hưởng bởi mô hình nhu cầu/sản xuất khác nhau xảy ra vào các ngày nghỉ lễ so với các ngày làm việc điển hình. Ví dụ: nhu cầu công nghiệp giảm vào ngày nghỉ có thể làm thay đổi sự cân bằng cung cầu, từ đó ảnh hưởng đến luồng điện qua các đường truyền quốc tế.

    3.17: Tính ma trận hiệp phương sai giữa các biến “nd”, “tsd” và “england_wales_demand”

    cov(processed_data[, c("nd", "tsd", "england_wales_demand")]) 
    ##                            nd      tsd england_wales_demand
    ## nd                   61329362 59034588             55440348
    ## tsd                  59034588 57741477             53396795
    ## england_wales_demand 55440348 53396795             50283885

    Giải thích code: dùng hàm cov() để tính toán ma trận hiệp phương sai giữa các biến “nd”, “tsd” và “england_wales_demand” trong data frame processed_data.

    Kết quả: Ta có được ma trận hiệp phương sai giữa các biến “nd”, “tsd” và “england_wales_demand”.

    • Các giá trị trên đường chéo chính là phương sai của từng biến số, đo lường mức độ biến động (phân tán) của mỗi biến quanh giá trị trung bình của nó. \(\text{Var}(nd) = 61,329,362\): Cho thấy nd có độ biến động rất lớn. * \(\text{Var}(tsd) = 57,741,477\): tsd có độ biến động cao, xếp sau nd. * \(\text{Var}(\text{england\_wales\_demand}) = 50,283,885\): độ biến động thấp hơn nhiều so với ndtsd.

    • Các Phần Tử Ngoài Đường Chéo (Hiệp phương sai - Covariance) là hiệp phương sai giữa hai biến số. Giá trị dương lớn cho thấy hai biến có xu hướng cùng tăng hoặc cùng giảm.

    3.18: Kiểm định ANOVA

    anova_two_way <- aov(nd ~ season * day_group, data = processed_data) 
    summary(anova_two_way)
    ##                      Df    Sum Sq   Mean Sq  F value Pr(>F)    
    ## season                3 2.668e+12 8.892e+11 17335.79 <2e-16 ***
    ## day_group             1 1.171e+11 1.171e+11  2282.90 <2e-16 ***
    ## season:day_group      3 1.113e+10 3.710e+09    72.32 <2e-16 ***
    ## Residuals        278504 1.429e+13 5.129e+07                    
    ## ---
    ## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

    Giải thích code: dùng hàm anova() để thực hiện kiểm định ANOVA cho hai nhân tố seasonday_group để xác định xem sự khác biệt trong biến nd có được giải thích bởi hai nhân tố đó hay không.

    Kết quả: Tất cả các kiểm định trong ANOVA (ảnh hưởng chính của season, ảnh hưởng chính của day_group, và tương tác \(\text{season}:\text{day\_group}\)) đều có \(\text{P-value}\) nhỏ hơn \(0.05\). Điều này cho thấy cả mùa, nhóm ngày và sự tương tác giữa chúng đều là những yếu tố dự báo đáng tin cậy cho sự biến đổi của nd.

    3.19: Kiểm định Wilcoxon

    wilcox.test(nd ~ is_holiday, data = processed_data) 
    ## 
    ##  Wilcoxon rank sum test with continuity correction
    ## 
    ## data:  nd by is_holiday
    ## W = 1063640543, p-value < 2.2e-16
    ## alternative hypothesis: true location shift is not equal to 0

    Giải thích code: dùng hàm wilcox.test() để kiểm định Wilcoxon nhằm kiểm tra xem biến nd có sự khác biệt về giá trị trung vị (median) một cách có ý nghĩa thống kê giữa ngày lễ và ngày thường hay không, mà không cần giả định dữ liệu có phân phối chuẩn.

    Kết quả:

    • Wilcoxon rank sum test with continuity correction: Kiểm định tổng hạng Wilcoxon có hiệu chỉnh liên tục

    • \(W = 1063640543\)

    • \(p\text{-value} < 2.2e-16\), bác bỏ giả thuyết \(H_0\). Kết luận: Có bằng chứng thống kê mạnh mẽ để kết luận rằng vị trí phân phối (hay trung vị/trung bình) của biến nd khác nhau đáng kể giữa ngày nghỉ và ngày thường. Nói cách khác, giá trị của nd chịu ảnh hưởng bởi việc ngày đó có phải là ngày nghỉ hay không.

    3.20: Tính toán công suất tối đa của gió và mặt trời, sau đó tính tổng công suất nhúng tối đa cho từng nhóm năm

    processed_data %>% 
      group_by(year_group) %>% 
      summarise( 
        Max_Wind_Capacity = max(embedded_wind_capacity), 
        Max_Solar_Capacity = max(embedded_solar_capacity), 
        Total_Embedded_Capacity = Max_Wind_Capacity + Max_Solar_Capacity)
    ## # A tibble: 4 × 4
    ##   year_group    Max_Wind_Capacity Max_Solar_Capacity Total_Embedded_Capacity
    ##   <fct>                     <int>              <int>                   <int>
    ## 1 Early Period               2236               2035                    4271
    ## 2 Later Period               6559              13080                   19639
    ## 3 Mid Period                 5113              11503                   16616
    ## 4 Recent Period              6622              17197                   23819

    Giải thích code: đoạn code được dùng để tìm ra công suất lắp đặt tối đa đã đạt được cho điện gió và điện mặt trời theo nhóm năm.

    Kết quả:

    • Trong giai đoạn Early Period (2009 - 2012): công suất gió nhúng tối đa là 2236 MW, công suất năng lượng mặt trời nhúng là 2035 MW và tổng công suất nhúng là 4271 MW.

    • Trong giai đoạn Mid Period (2013 - 2016): công suất gió nhúng tối đa là 5113 MW, công suất năng lượng mặt trời nhúng là 11503 MW và tổng công suất nhúng là 16616 MW.

    • Trong giai đoạn Later Period (2017 - 2020): công suất gió nhúng tối đa là 6559 MW, công suất năng lượng mặt trời nhúng là 13080 MW và tổng công suất nhúng là 19639 MW.

    • Trong giai đoạn Recent Period (2021 - 2024): công suất gió nhúng tối đa là 6622 MW, công suất năng lượng mặt trời nhúng là 17197 MW và tổng công suất nhúng là 23819 MW.

    4. Trực quan hóa dữ liệu: (20 biểu đồ)

    4.1: Biểu đồ Mật độ Phân phối Nhu cầu Điện năng Quốc gia

    processed_data %>%
      ggplot(aes(x = nd)) +                                                
      geom_density(fill = "#0072B2", alpha = 0.7, color = "darkblue", linewidth = 0.8) + 
      geom_vline(aes(xintercept = mean(nd, na.rm = TRUE)),                 
                 color = "red", linetype = "dashed", linewidth = 1) +       
      labs(title = "Phân phối Nhu cầu Điện năng Quốc gia",                
           x = "Nhu cầu Điện năng (MW)",
           y = "Mật độ") +
      xlim(min(processed_data$nd, na.rm = TRUE), max(processed_data$nd, na.rm = TRUE)) +
      annotate("text", x = mean(processed_data$nd, na.rm = TRUE)*1.05, y = 0.00005,
               label = paste("Trung bình:", round(mean(processed_data$nd, na.rm = TRUE), 0), "MW"),
               color = "black") + scale_x_continuous(labels = comma)

    Nhận xét:

    • Phân phối Chuẩn và Lệch: Phân phối của Nhu cầu Điện (\(nd\)) có hình dạng tương đối giống phân phối chuẩn (Normal Distribution), tập trung ở mức trung bình. Tuy nhiên, nó có vẻ hơi lệch trái (negatively skewed), tức là có một cái đuôi dài hơn về phía nhu cầu thấp hơn, và đỉnh phân phối nằm ở bên phải của giá trị trung bình.

    • Khoảng Tập trung: Đại đa số các quan sát Nhu cầu Điện tập trung mạnh trong khoảng từ \(24,000\ MW\) đến \(32,000\ MW\).

    • Giá trị Trung bình và Độ biến động: Giá trị trung bình được xác định là \(31,187\ MW\) (đường đứt quãng màu đỏ). Tuy nhiên, đỉnh của mật độ phân phối (mode) dường như nằm ở mức nhu cầu thấp hơn một chút so với giá trị trung bình, khoảng \(28,000\ MW\). Sự phân tán khá rộng, cho thấy nhu cầu điện có độ biến động cao, phản ánh sự thay đổi lớn giữa nhu cầu thấp điểm mùa hè/cuối tuần và nhu cầu cao điểm mùa đông/ngày thường.

    4.2: Biểu đồ Cột Nhu cầu Điện năng Quốc gia Trung bình Hàng tháng

    dothi2 <- processed_data %>%                                           
      group_by(month) %>%                                                   
      summarise(avg_nd = mean(nd, na.rm = TRUE)) %>%                       
      ungroup()                                                           
    dothi2 %>%
      ggplot(aes(x = month, y = avg_nd, fill = avg_nd)) +                   
      geom_col(color = "black", linewidth = 0.5) +                          
      geom_text(aes(label = round(avg_nd, 0)), vjust = -0.5, color = "black", size = 3) + 
      labs(title = "Nhu cầu Điện năng Quốc gia Trung bình theo Tháng",    
           x = "Tháng",
           y = "Nhu cầu Điện năng Trung bình (MW)",
           fill = "Nhu cầu (MW)") +
      scale_fill_gradient(low = "lightblue", high = "red", label = comma) + 
      scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.1))) + 
      geom_segment(aes(x = as.numeric(month) - 0.45, xend = as.numeric(month) + 0.45, y = avg_nd, yend = avg_nd), 
                   color = "black", linewidth = 1.5)

    Nhận xét:

    • Tính Mùa vụ Đỉnh-Đáy: Nhu cầu điện thể hiện một chu kỳ rõ rệt, đạt đỉnh cao nhất vào các tháng Mùa Xuân (Tháng 12, Tháng 1, Tháng 2) và thấp nhất vào các tháng Mùa Hè (Tháng 7, Tháng 8). Đỉnh: Nhu cầu trung bình cao nhất là vào Tháng 1 (khoảng \(27,325\ MW\)), Tháng 12 (khoảng \(35,160\ MW\)) và Tháng 2 (khoảng \(35,882\ MW\)). Đáy: Nhu cầu trung bình thấp nhất là vào Tháng 7 (khoảng \(34,942\ MW\)) và Tháng 8 (khoảng \(27,019\ MW\)).

    • Sự Chuyển tiếp Dần dần: Sự thay đổi nhu cầu không đột ngột mà là một quá trình chuyển tiếp mượt mà: nhu cầu giảm dần từ đỉnh Đông sang đáy Hè, và tăng dần trở lại từ đáy Hè sang đỉnh Đông. Các tháng chuyển tiếp như Tháng 4 và Tháng 10 có nhu cầu ở mức trung bình.

    • Sự Phụ thuộc vào Nhiệt độ: Sự phân bố này cho thấy nhu cầu điện chịu ảnh hưởng mạnh mẽ bởi yếu tố nhiệt độ, với nhu cầu sưởi ấm chiếm phần lớn trong tổng nhu cầu vào mùa đông, trong khi nhu cầu làm mát vào mùa hè không đủ lớn để đẩy nhu cầu lên mức tương đương.

    4.3:Biểu đồ Đường Chu kỳ Nhu cầu Điện Trung bình trong Ngày, Chia theo Mùa

    processed_data %>%
      ggplot(aes(x = hour, y = nd, color = season)) +                       
      stat_summary(fun = "mean", geom = "line", size = 1.2) +            
      facet_wrap(~season) + scale_y_continuous(labels = comma) +                                  
      labs(                                                                
        title = "Chu kỳ Nhu cầu điện trung bình trong ngày theo từng Mùa",
        x = "Giờ trong ngày",
        y = "Nhu cầu điện trung bình (MW)",
        color = "Mùa") 

    Nhận xét:

    • Nhu cầu điện trong ngày thường có 2 đỉnh: một đỉnh nhỏ vào buổi sáng (khoảng 8-9h) và một đỉnh lớn hơn vào buổi tối (khoảng 17-19h).

    • Mùa đông có nhu cầu cao nhất ở mọi thời điểm trong ngày, đặc biệt là vào buổi tối.

    • Mùa hè có nhu cầu thấp nhất và đường cong nhu cầu cũng “phẳng” hơn so với các mùa khác.

    4.4:Heatmap Nhu cầu Điện năng Trung bình Phân bố theo Giờ trong Ngày và Ngày trong Tuần

    dothi4 <- processed_data %>%                                           
      group_by(weekday, hour) %>%                                       
      summarise(avg_nd = mean(nd, na.rm = TRUE)) %>%                       
      ungroup()                                                            
    dothi4 %>%
      ggplot(aes(x = weekday, y = factor(hour), fill = avg_nd)) +           
      geom_tile(color = "red", linewidth = 0.5) +                          
      labs(title = "Heatmap nhu cầu điện năng (theo giờ & ngày trong tuần)",
           x = "Ngày trong tuần",
           y = "Giờ trong ngày",
           fill = "Nhu cầu (MW)") +
      scale_fill_viridis_c(option = "magma", labels = comma) +              
      geom_rect(aes(xmin = as.numeric(weekday) - 0.5, xmax = as.numeric(weekday) + 0.5, 
                    ymin = as.numeric(factor(hour)) - 0.5, ymax = as.numeric(factor(hour)) + 0.5),
                fill = NA, color = "grey", linewidth = 0.1) +               
      scale_y_discrete(limits = rev) +                                      
      geom_text(data = filter(dothi4, avg_nd == max(avg_nd, na.rm = TRUE)), 
                aes(label = round(avg_nd/1000, 1)), color = "red", size = 3, fontface = "bold")

    Nhận xét:

    1. Tính chu kỳ và Cấu trúc Cao điểm/Thấp điểm: Biểu đồ thể hiện rõ ràng hai cấu trúc tiêu thụ chính:

    • Cao điểm (Màu sáng/trắng): Tập trung mạnh vào các ngày trong tuần (Thứ Hai đến Thứ Sáu), với hai giai đoạn cao điểm chính là: Sáng sớm (Khoảng 7h-9h): Phản ánh nhu cầu khởi động các hoạt động kinh doanh và cá nhân. Chiều tối (Khoảng 17h-20h): Đây là giai đoạn cao điểm nhất, nơi ô màu trắng/vàng đậm nhất xuất hiện, do sự trùng lặp của nhu cầu dân dụng (nấu ăn, sưởi ấm) và các hoạt động công nghiệp/thương mại cuối ngày.

    • Thấp điểm (Màu tối/tím): Thấp điểm xảy ra vào ban đêm (từ 0h đến 5h) ở tất cả các ngày và cuối tuần (Thứ Bảy, Chủ Nhật). Nhu cầu cuối tuần giảm đáng kể, đặc biệt là vào ban ngày, cho thấy sự ngắt quãng của các hoạt động công nghiệp lớn.

    2. Sự Giảm Sút Cuối Tuần (Weekend Effect): Nhu cầu điện trong Thứ Bảy và Chủ Nhật là thấp hơn đáng kể so với các ngày trong tuần (màu sắc tối hơn). Cấu trúc hai đỉnh cao điểm cũng mờ nhạt hoặc biến mất vào cuối tuần.

    3. Đỉnh Nhu cầu Tuyệt đối: Giá trị Nhu cầu trung bình cao nhất (được đánh dấu) tập trung ở khung giờ 18h - 19h của các ngày giữa tuần (Thứ Ba, Thứ Tư, Thứ Năm).

    4.5: Biểu đồ Violin và Boxplot So sánh Phân phối Nhu cầu Điện giữa Ngày Thường và Ngày Lễ

    dothi5 <- processed_data %>%
      mutate(is_holiday_label = factor(is_holiday, levels = c(0, 1), labels = c("Ngày thường", "Ngày lễ")))
    dothi5 %>%
      ggplot(aes(x = is_holiday_label, y = nd, fill = is_holiday_label)) +  
      geom_violin(trim = TRUE, alpha = 0.6) +                              
      geom_boxplot(width = 0.1, color = "black", alpha = 0.8) +            
      labs(title = "Phân phối nhu cầu điện năng: Ngày thường và Ngày lễ",    
           x = "Loại ngày",
           y = "Nhu cầu điện năng (MW)",
           fill = "Loại ngày") +
      scale_fill_manual(values = c("Ngày thường" = "#007302", "Ngày lễ" = "#0072B2")) + 
      scale_y_continuous(labels = comma) +                                 
      geom_jitter(data = . %>% sample_frac(0.005), alpha = 0.1, size = 0.5, color = "black") + 
      stat_summary(fun = median, geom = "point", shape = 20, size = 5, color = "white") 

    Nhận xét:

    • Nhu cầu Ngày Lễ Thấp hơn Đáng kể: Phân phối Nhu cầu trong Ngày lễ (màu xanh dương) nằm thấp hơn rõ rệt so với Ngày thường (màu xanh lá). Điểm trung vị (dấu chấm trắng) và hộp (boxplot) của Ngày lễ nằm thấp hơn, cho thấy cả mức nhu cầu điện điển hình lẫn mức nhu cầu trung bình đều giảm đáng kể vào các ngày nghỉ.

    • Độ Biến động Thấp hơn (Ngày Lễ): Biểu đồ violin của Ngày lễ có vẻ hẹp hơn và ngắn hơn so với Ngày thường (đặc biệt là ở phía trên), cho thấy nhu cầu không chỉ thấp hơn mà còn ít biến động hơn hoặc ít đạt đến các mức nhu cầu cực đại như Ngày Thường. Điều này phản ánh sự dừng lại hoặc giảm cường độ của các hoạt động thương mại và công nghiệp.

    • Phân phối Ngày Thường: Phân phối Ngày thường trải rộng hơn và có đuôi dài hơn về phía nhu cầu cao (skewness), cho thấy sự tồn tại của các thời điểm nhu cầu rất cao (cao điểm).

    4.6: Biểu đồ Cột Xếp chồng Tổng Nhu cầu Điện Phân tách theo Mùa và Năm

    dothi6 <- processed_data %>%                                            
      group_by(year, season) %>%                                          
      summarise(total_nd = sum(nd, na.rm = TRUE)) %>%                       
      ungroup()                                                            
    dothi6 %>%
      ggplot(aes(x = factor(year), y = total_nd, fill = season)) +         
      geom_col(position = position_stack(reverse = TRUE), color = "black", linewidth = 0.3) + 
      labs(title = "Tổng nhu cầu điện năng theo mùa và năm (Chọn lọc)",    
           x = "Năm",
           y = "Tổng nhu cầu điện năng (MW)",
           fill = "Mùa") +
      scale_fill_manual(values = c("Đông" = "#0072B2", "Thu" = "#D55E00", "Hè" = "#009E73", "Xuân" = "#F0E442")) + 
      scale_y_continuous(labels = unit_format(unit = "GWh", scale = 1e-6)) + 
      geom_text(aes(label = round(total_nd / sum(total_nd, na.rm = TRUE) * 100, 1), group = year), 
                position = position_stack(vjust = 0.5, reverse = TRUE), size = 3, color = "black") + 
      geom_hline(yintercept = 0, color = "black", linewidth = 1) 

    Nhận xét:

    • Xu hướng Giảm Tổng Nhu cầu: Xu hướng rõ rệt nhất là chiều cao tổng thể của các cột giảm dần qua các năm, đặc biệt từ năm 2010 đến 2023. Điều này tái khẳng định nhận xét trước đó: tổng nhu cầu điện năng quốc gia đang giảm dần trong dài hạn.

    • Sự Chiếm ưu thế Ổn định của Mùa Đông: Trong cơ cấu nhu cầu hàng năm, Mùa Đông (Winter - màu xanh đậm) luôn chiếm tỷ trọng lớn nhất (thường từ \(29\%\) đến \(30\%\)) và là mùa có tổng nhu cầu cao nhất. Điều này cho thấy vai trò chủ đạo của nhu cầu sưởi ấm trong tổng tiêu thụ điện.

    • Sự Ổn định Tỷ lệ Mùa vụ: Mặc dù tổng nhu cầu giảm, cơ cấu tỷ lệ phần trăm đóng góp của các mùa lại tương đối ổn định qua các năm: Mùa Đông (tối đa) \(\approx 29\% - 30\%\). Mùa Hè (Summer - màu xanh lá) chiếm tỷ trọng thấp nhất (thường \(\approx 20\% - 21\%\)). Mùa Xuân (Spring - màu vàng) và Mùa Thu (Autumn - màu cam) duy trì tỷ trọng ở mức trung bình (khoảng \(23\% - 24\%\) mỗi mùa).

    4.7: Biểu đồ Histogram Phân phối Nhu cầu Điện Anh & xứ Wales theo Mùa

    processed_data %>%
      ggplot(aes(x = england_wales_demand, fill = season)) +                
      geom_histogram(bins = 50, color = "white", alpha = 0.8) +          
      labs(title = "Phân phối nhu cầu điện năng ở Anh và xứ Wales theo mùa",
           x = "Nhu cầu Điện năng (MW)",
           y = "Số lượng Quan sát") +
      facet_wrap(~ season, scales = "free_y", ncol = 2) +                   
      scale_fill_manual(values = c("Đông" = "#56B4E9", "Xuân" = "#009E73", "Hè" = "#F0E442", "Thu" = "#E69F00")) + 
      scale_x_continuous(labels = comma) +                                
      geom_vline(data = . %>% group_by(season) %>% summarise(avg_demand = mean(england_wales_demand, na.rm = TRUE)), 
                 aes(xintercept = avg_demand), color = "black", linetype = "dashed", linewidth = 1)

    Nhận xét:

    • Nhu cầu Trung bình Biến động theo Mùa: Giá trị trung bình (đường đứt quãng màu đỏ) cho thấy nhu cầu điện có xu hướng cao nhất vào Mùa Đông (lớn nhất) và thấp nhất vào Mùa Hè (nhỏ nhất). Mùa Thu và Mùa Xuân có mức nhu cầu trung bình nằm giữa, với Mùa Thu có nhu cầu trung bình cao hơn Mùa Xuân. Điều này phản ánh rõ ràng nhu cầu sưởi ấm và chiếu sáng tăng cao trong những tháng lạnh.

    • Hình dạng Phân phối: Mùa Hè (Hè) thì Phân phối nhu cầu là hẹp nhất và tập trung nhất xung quanh mức trung bình thấp, cho thấy nhu cầu ổn định hơn. Mùa Đông (Đông) thì Phân phối nhu cầu là rộng nhất và có phần lệch phải, cho thấy sự biến động lớn nhất (có cả những thời điểm nhu cầu cực kỳ cao) và một dải nhu cầu rộng hơn so với các mùa khác. Mùa Xuân (Xuân)Mùa Thu (Thu) thì Các phân phối này có độ rộng và vị trí nằm giữa hai thái cực Hè và Đông.

    4.8: Biểu đồ Tán xạ Quan hệ Nhu cầu Điện và Phát điện Gió Nhúng

    processed_data %>%
      sample_frac(0.01) %>%                                                 
      ggplot(aes(x = nd, y = embedded_wind_generation)) +                  
      geom_point(alpha = 0.5, color = "#0072B2") +                       
      geom_smooth(method = "lm", color = "red", se = TRUE, linewidth = 1.2) + 
      labs(title = "Mối quan hệ giữa Nhu cầu Điện năng và Phát điện Gió",   
           x = "Nhu cầu Điện năng (MW)",
           y = "Phát điện Gió (MW)") +
      scale_x_continuous(labels = comma) +                             
      scale_y_continuous(labels = comma) +                                  
      geom_hline(yintercept = mean(processed_data$nd, na.rm = TRUE),        
                 linetype = "dotted", color = "grey50") +
      annotate("text", x = max(processed_data$nd, na.rm = TRUE) * 0.9, y = 0, 
               label = paste("R-squared:", round(cor(processed_data$nd, processed_data$embedded_wind_generation, use = "complete.obs")^2, 3)),
               color = "black", size = 3)

    Nhận xét:

    • Không có Mối Quan hệ Tuyến tính Mạnh mẽ: Các điểm dữ liệu phân tán rộng khắp biểu đồ, tạo thành một hình chữ nhật lớn thay vì một đường thẳng rõ ràng. Đường hồi quy tuyến tính (màu đỏ) gần như nằm ngang với độ dốc rất nhỏ (gần như bằng 0). Điều này được xác nhận bởi giá trị \(R^2\) (Hệ số xác định) rất thấp, gần bằng 0.

    • Ý nghĩa Thống kê: Giá trị \(R^2\) thấp chỉ ra rằng Nhu cầu Điện năng (\(nd\)) giải thích rất ít (hoặc gần như không giải thích) sự thay đổi của Phát điện Gió (\(embedded\_wind\_generation\)). Nói cách khác, lượng điện gió được tạo ra không phụ thuộc một cách có ý nghĩa vào mức nhu cầu điện năng tại thời điểm đó.

    • Độ Biến động: Phát điện gió (\(y\)) thể hiện độ biến động rất lớn ở hầu hết mọi mức nhu cầu (\(x\)), từ 0 MW đến hơn 6000 MW, cho thấy nguồn điện gió chủ yếu bị chi phối bởi các yếu tố thời tiết (tốc độ gió), không liên quan đến nhu cầu tiêu thụ.

    • Phân bố Nhu cầu: Nhu cầu điện (\(x\)) tập trung chủ yếu trong khoảng từ \(20,000\ MW\) đến \(45,000\ MW\).

    4.9: Biểu đồ Treemap Tổng Nhu cầu Điện Phân cấp theo Năm và Buổi

    dothi9 <- processed_data %>%                                           
      group_by(year, time_of_day) %>%                                       
      summarise(total_nd = sum(nd, na.rm = TRUE), .groups = 'drop')        
    ggplot(dothi9, aes(area = total_nd, fill = year, label = time_of_day, subgroup = year)) + 
      geom_treemap() +                                                      
      geom_treemap_subgroup_border(color = "white", size = 5) +            
      geom_treemap_text(color = "white", place = "centre", grow = TRUE, fontface = "italic") + 
      geom_treemap_subgroup_text(place = "bottom", alpha = 0.5, color = "black", fontface = "bold") + 
      labs(title = "Cấu trúc Phân cấp Tổng Nhu cầu Điện theo Giai đoạn và Buổi")

    Nhận xét:

    • Xu hướng Giảm Nhu cầu Tổng thể: Quan sát tổng thể, diện tích của các nhóm Năm có xu hướng giảm dần từ các năm đầu (ví dụ: 2010, 2011) sang các năm cuối chuỗi dữ liệu (ví dụ: 2023). Điều này củng cố nhận xét trước đó về sự giảm sút trong tổng nhu cầu điện năng quốc gia trong dài hạn.

    • Nhu cầu Tập trung theo Buổi: Trong hầu hết các năm, hai nhóm buổi là Tối (Evening) và Chiều (Afternoon) chiếm phần lớn diện tích của treemap, cho thấy đây là hai khoảng thời gian có tổng nhu cầu điện lớn nhất. Điều này là hợp lý do sự trùng lặp của các hoạt động dân dụng, thương mại và công nghiệp vào các buổi này (ví dụ: nấu ăn, giải trí, kết thúc giờ làm việc).

    • Thay đổi Mức độ Chiếm ưu thế: Mặc dù Tối và Chiều là hai buổi lớn nhất, có thể thấy trong các năm gần đây, nhu cầu của buổi Sáng (Morning) và Trưa (Day) (các ô nhỏ hơn) có vẻ ổn định hơn hoặc giảm chậm hơn, trong khi buổi Tối (ô lớn nhất) giảm đáng kể nhất, dẫn đến sự thu hẹp khoảng cách tỷ lệ giữa các buổi. Sự thay đổi này có thể phản ánh sự thay đổi trong mô hình sử dụng điện hoặc sự ảnh hưởng của nguồn năng lượng phân tán (ví dụ: điện mặt trời nhúng hoạt động mạnh vào Buổi Trưa/Chiều, làm giảm nhu cầu ròng từ lưới điện).

    4.10: Biểu đồ Histogram và Mật độ Phân phối Nhu cầu Điện theo Mùa

    ggplot(processed_data, aes(x = nd, fill = season)) +                     
      geom_histogram(aes(y = ..density..), alpha = 0.6, bins = 50, position = 'identity') + 
      geom_density(alpha = 0.4, color = "black", linewidth = 0.5) +         
      labs(                                                                
        title = "Phân phối Nhu cầu Điện Quốc gia (nd) theo Mùa",
        subtitle = "Nhu cầu cao nhất vào Mùa Đông và thấp nhất vào Mùa Hè",
        x = "Nhu cầu Quốc gia (MW)",
        y = "Mật độ",
        fill = "Mùa"
      ) +
      scale_x_continuous(labels = comma) 

    Nhận xét:

    • Sự Dịch chuyển theo Mùa: Phân phối Nhu cầu (\(nd\)) dịch chuyển rõ rệt dọc theo trục X (trục Nhu cầu): Mùa Đông (Winter) có phân phối tập trung ở mức Nhu cầu cao nhất, với đường mật độ (màu đỏ) nằm xa nhất về phía bên phải. Mùa Hè (Summer) có phân phối tập trung ở mức Nhu cầu thấp nhất, với đường mật độ (màu xanh lá) nằm xa nhất về phía bên trái. Mùa Thu (Autumn)Mùa Xuân (Spring) có phân phối nằm ở giữa, với Mùa Thu (màu tím) hơi cao hơn Mùa Xuân (màu xanh dương).

    • Độ Biến thiên: Phân phối Nhu cầu trong Mùa Đông có vẻ rộng hơn và trải dài hơn (độ lệch chuẩn lớn hơn), cho thấy độ biến động cao hơn trong nhu cầu điện so với các mùa khác. Ngược lại, Mùa Hè có phân phối hẹp hơn, chỉ ra rằng nhu cầu điện ổn định hơn ở mức thấp trong mùa này.

    • Ý nghĩa: Sự khác biệt này phản ánh tác động mạnh mẽ của yếu tố nhiệt độ và ánh sáng đến nhu cầu điện, nơi sưởi ấm và chiếu sáng trong Mùa Đông đẩy nhu cầu lên mức cao hơn và biến động hơn. Điều này có ý nghĩa quan trọng trong việc lập kế hoạch vận hành và dự báo, đặc biệt là đối với việc cân bằng cung cầu trong những tháng lạnh.

    4.11: Biểu đồ Đường Tỷ lệ Năng lượng Tái tạo Nhúng Trung bình Hàng tháng trên Tổng Nhu cầu Quốc gia

    dothi11 <- processed_data %>%                                           
      group_by(year, month) %>%                                             
      summarise(avg_ratio = mean(embedded_ratio, na.rm = TRUE), .groups = 'drop') %>% 
      mutate(date = make_date(year, month))                                 
    dothi11 %>%
      ggplot(aes(x = date, y = avg_ratio)) +                                
      geom_line(color = "#0072B2", linewidth = 1) +                       
      geom_point(color = "#D55E00", size = 1.5) +                     
      geom_smooth(method = "loess", se = FALSE, color = "darkgreen", span = 0.3) + 
      labs(                                                               
        title = "Tỷ lệ Năng lượng Tái tạo trong Tổng Nhu cầu Quốc gia",
        subtitle = "Xu hướng tăng trưởng rõ rệt từ năm 2009 đến nay",
        x = "Năm",
        y = "Tỷ lệ trung bình hàng tháng"
      ) +
      scale_y_continuous(labels = percent_format(accuracy = 1)) 

    Nhận xét:

    • Xu hướng Tăng Trưởng Mạnh mẽ: Có một xu hướng tăng trưởng lũy tiến (tăng tốc) rõ rệt về tỷ lệ đóng góp của năng lượng tái tạo nhúng (đường màu xanh đậm). Bắt đầu từ mức rất thấp (gần 0%) vào năm 2009, tỷ lệ này đã tăng lên đáng kể, vượt qua mốc 10% vào khoảng năm 2017 và tiếp tục tăng trưởng mạnh mẽ, đạt gần 20% vào cuối chuỗi dữ liệu. Điều này phản ánh thành công của việc triển khai các nguồn năng lượng tái tạo phân tán (như điện gió và mặt trời nhúng).

    • Tính Mùa vụ Rõ rệt: Mặc dù xu hướng dài hạn là tăng, biểu đồ cho thấy sự biến động mùa vụ cao. Các điểm dữ liệu dao động lớn xung quanh đường xu hướng làm mịn (màu xanh lá cây đậm). Các đỉnh (tỷ lệ cao) thường xảy ra vào mùa hè, do sản lượng điện mặt trời nhúng đạt mức tối đa. Các đáy (tỷ lệ thấp) thường xảy ra vào mùa đông, khi sản lượng mặt trời giảm và mặc dù sản lượng gió tăng, nó không đủ để bù đắp sự sụt giảm tổng thể, đặc biệt khi nhu cầu điện cũng tăng cao vào mùa đông.

    • Ý nghĩa: Xu hướng tăng trưởng này là chỉ báo mạnh mẽ cho thấy năng lượng tái tạo đang ngày càng đóng vai trò quan trọng trong việc đáp ứng nhu cầu điện quốc gia. Tuy nhiên, tính biến động cao theo mùa của tỷ lệ này (do đặc tính nguồn gió/mặt trời) tạo ra những thách thức lớn về sự ổn định và cân bằng lưới điện.

    4.12: Biểu đồ Donut Phân bố Tỷ lệ Trạng thái Dòng chảy Liên kết theo Mùa

    dothi12 <- processed_data %>%                                           
      count(season, flow_group) %>%                                         
      group_by(season) %>%                                                  
      mutate(percentage = n / sum(n))                                       
    ggplot(dothi12, aes(x = 2, y = percentage, fill = flow_group)) +       
      geom_col(color = "white") +                                           
      coord_polar("y", start = 0) +                                         
      xlim(c(0.2, 2.5)) +                                                  
      facet_wrap(~ season, ncol = 4) +                                    
      labs(                                                                
        title = "So sánh Cấu trúc Dòng chảy Liên kết qua các Mùa",
        subtitle = "Sự khác biệt nhỏ trong tỷ lệ nhập/xuất khẩu điện",
        fill = "Trạng thái Dòng chảy"
      ) +
      theme_void() +                                                        
      theme(
        legend.position = "right",                                       
        strip.text = element_text(face = "bold", size = 12)                  
      ) +
      scale_fill_brewer(palette = "Spectral")                             

    Nhận xét:

    • Trạng thái Thống trị: Ở tất cả các mùa, trạng thái Nhập khẩu ròng (Net Import) (màu đỏ/cam) chiếm tỷ trọng lớn nhất và nổi bật nhất trong cấu trúc dòng chảy. Điều này chỉ ra rằng, phần lớn thời gian, hệ thống điện quốc gia là một người tiêu dùng ròng điện năng từ các liên kết quốc tế.

    • Sự Đồng nhất giữa các Mùa: Cấu trúc tỷ lệ phần trăm cho thấy sự đồng nhất đáng kể giữa bốn mùa. Không có sự khác biệt lớn về tỷ lệ giữa Nhập khẩu ròng và Xuất khẩu ròng/Cân bằng ròng. Điều này gợi ý rằng, mô hình sử dụng các liên kết quốc tế để cân bằng lưới điện là ổn định và ít bị ảnh hưởng bởi tính mùa vụ hơn so với các yếu tố khác (như nhu cầu cao điểm/thấp điểm hoặc sản lượng NLTT).

    • Trạng thái Cân bằng và Xuất khẩu: Tỷ lệ Xuất khẩu ròng (Net Export) (màu xanh lá) và Cân bằng ròng (Net Zero/Balanced) (màu xanh dương) đều chiếm tỷ lệ nhỏ, cho thấy hệ thống hiếm khi là nhà cung cấp ròng hoặc đạt trạng thái cân bằng hoàn hảo trên các liên kết.

    • Khác biệt Nhỏ theo Mùa: Mặc dù sự khác biệt nhỏ, có thể quan sát thấy Mùa Hè dường như có tỷ lệ Nhập khẩu ròng thấp nhất và tỷ lệ Xuất khẩu ròng/Cân bằng ròng cao nhất (màu đỏ/cam nhỏ hơn một chút so với các mùa khác). Điều này có thể liên quan đến nhu cầu nội địa thấp hơn và/hoặc sản lượng điện mặt trời nhúng cao vào mùa hè, làm giảm nhu cầu nhập khẩu để cân bằng lưới.

    4.13: Biểu đồ Vùng Xếp chồng Tỷ trọng Sản lượng Điện Gió và Điện Mặt trời Nhúng theo Thời gian

    dothi13 <- processed_data %>%                                         
      group_by(year, month) %>%                                             
      summarise(
        total_wind = sum(embedded_wind_generation, na.rm = TRUE),           
        total_solar = sum(embedded_solar_generation, na.rm = TRUE),        
        .groups = 'drop'                                                  
      ) %>%
      mutate(date = make_date(year, month)) %>%                             
      pivot_longer(cols = c(total_wind, total_solar), names_to = "source", values_to = "generation") 
    ggplot(dothi13, aes(x = date, y = generation, fill = source)) +        
      geom_area(position = "fill", color = "white") +                       
      labs(                                                                
        title = "Sự trỗi dậy của Năng lượng Mặt trời trong Cơ cấu Tái tạo",
        subtitle = "Tỷ trọng của Điện Gió và Mặt trời trong tổng sản lượng NLTT nhúng",
        x = "Năm",
        y = "Tỷ lệ Đóng góp",
        fill = "Nguồn Năng lượng"
      ) +
      scale_fill_manual(values = c("total_wind" = "#2171B5", "total_solar" = "#FDB813"),
                        labels = c("Điện Gió", "Điện Mặt trời")) +         
      scale_y_continuous(labels = scales::percent) +                        
      geom_hline(yintercept = 0.5, linetype = "dotted", color = "black") +  
      annotate("text", x = as.Date("2010-01-01"), y = 0.55, label = "Mức cân bằng", color = "black") + 
      stat_smooth(                                                         
        data = filter(dothi13, source == "total_wind"),                     
        aes(group = source),
        method = "loess", se = FALSE, color = "white",                     
        position = "fill", linetype = "dashed")                                                     

    Nhận xét:

    • Sự Trỗi dậy Đáng kể của Điện Mặt trời: Biểu đồ thể hiện sự gia tăng nhanh chóng và vượt bậc của tỷ trọng Điện Mặt trời (màu vàng/cam) trong cơ cấu năng lượng tái tạo nhúng. Vào những năm đầu (2009-2012), Điện Gió gần như chiếm toàn bộ tỷ trọng.

    • Điểm Cân Bằng (50%): Khoảng từ năm 2014 đến 2016, tỷ trọng Điện Mặt trời đã vượt qua mốc 50% (đường nét chấm), đánh dấu một bước ngoặt quan trọng khi Điện Mặt trời trở thành nguồn năng lượng tái tạo nhúng chiếm ưu thế về mặt sản lượng so với Điện Gió.

    • Tính Mùa vụ Rõ rệt: Cả hai nguồn đều thể hiện tính mùa vụ rõ rệt: Điện Mặt trời có tỷ trọng đóng góp cao hơn rõ rệt vào mùa hè (các đỉnh màu vàng/cam) và giảm mạnh vào mùa đông, phản ánh chu kỳ ánh sáng mặt trời. Ngược lại, Điện Gió có xu hướng chiếm tỷ trọng cao hơn vào mùa đông (các đỉnh màu xanh) khi tốc độ gió thường mạnh hơn.

    • Xu hướng Dài hạn: Bất chấp sự biến động theo mùa, đường xu hướng làm mịn (nét đứt) cho thấy tỷ trọng của Điện Gió đang có xu hướng giảm dần (hoặc tỷ trọng Mặt trời đang tăng dần) trong dài hạn, củng cố vị thế dẫn đầu của Điện Mặt trời trong tổng sản lượng tái tạo nhúng.

    4.14: Biểu đồ Mật độ Phân phối Nhu cầu Điện (nd) theo Năm và Giai đoạn

    ggplot(processed_data, aes(x = nd, fill = year)) +                     
      geom_density(alpha = 0.8, color = "white") +                        
      facet_wrap(~ year_group, ncol = 2) +                                
      geom_vline(                                                          
        data = . %>% group_by(year) %>% summarise(median_nd = median(nd)),  
        aes(xintercept = median_nd),                                       
        color = "red", linetype = "dashed", linewidth = 1                 
      ) +
      labs(                                                               
        title = "Sự thay đổi Phân phối Nhu cầu Điện qua các Giai đoạn",
        x = "Nhu cầu Quốc gia (MW)",
        y = "Mật độ"
      ) +
      scale_fill_brewer(palette = "YlGnBu") +                             
      scale_x_continuous(labels = comma) 

    Nhận xét: Có hai xu hướng quan trọng và liên quan đến nhau

    • Quan hệ Nhu cầu và Dòng chảy Liên kết: Biểu đồ tán xạ chỉ ra một mối quan hệ nghịch biến cơ bản giữa Nhu cầu Quốc gia (\(nd\)) và Tổng Dòng chảy (\(total\_flow\), tức là nhập/xuất khẩu ròng). Khi nhu cầu điện nội địa tăng, hệ thống có xu hướng giảm nhập khẩu ròng hoặc tăng xuất khẩu ròng. Tuy nhiên, mối quan hệ này trở nên yếu đi trong những giai đoạn có Tác động Cao của Năng lượng Tái tạo (NLTT). Điều này ngụ ý rằng, sự đóng góp của NLTT (như gió và mặt trời) đang làm giảm sự phụ thuộc của lưới điện vào việc điều chỉnh dòng chảy qua các liên kết để cân bằng nhu cầu, đặc biệt trong các mùa có NLTT dồi dào.

    • Sự thay đổi Phân phối Nhu cầu theo Giai đoạn: Biểu đồ mật độ minh họa rằng Nhu cầu Quốc gia trung bình có xu hướng giảm dần qua các giai đoạn, thể hiện qua sự dịch chuyển sang trái của đường trung vị từ 2009-2012 đến 2021-2024. Đồng thời, hình dạng phân phối trở nên tập trung và hẹp hơn trong các giai đoạn gần đây, cho thấy tính ổn định cao hơn và ít biến động hơn của nhu cầu điện quanh mức trung bình thấp hơn. Xu hướng này có thể là kết quả của các yếu tố như tăng hiệu suất năng lượng, hoặc sự phân tán của sản xuất điện nhờ NLTT nhúng (embedded generation), khiến nhu cầu ròng mà lưới điện trung tâm phải đối ứng giảm đi.

    4.15: Biểu đồ Tán xạ Quan hệ Nhu cầu và Tổng Dòng chảy Liên kết theo Mùa và Tác động của NLTT

    ggplot(processed_data, aes(x = nd, y = total_flow, color = season)) + 
      geom_point(alpha = 0.4, size = 1.5) +                                
      geom_smooth(method = "lm", se = FALSE, linewidth = 0.8) +            
      facet_wrap(~ em_ra_group, scales = "free_y") +                       
      geom_hline(yintercept = 0, linetype = "dashed", color = "black") +  
      labs(                                                                
        title = "Quan hệ Nhu cầu - Dòng chảy dưới Tác động của Năng lượng Tái tạo",
        x = "Nhu cầu Quốc gia (MW)",
        y = "Tổng Dòng chảy (MW)",
        color = "Mùa"
      ) +
      scale_color_brewer(palette = "Dark2") +                              
      scale_x_continuous(labels = comma) +                               
      scale_y_continuous(labels = comma) 

    Nhận xét: Biểu đồ thể hiện mối quan hệ giữa Nhu cầu Quốc gia (nd) và Tổng Dòng chảy (total_flow) qua các liên kết, được phân tích theo Mùa và Mức độ Tác động của NLTT (em_ra_group). Tổng dòng chảy là lượng điện nhập/xuất khẩu ròng qua các liên kết với nước ngoài, với giá trị dương (+) là nhập khẩu ròng và giá trị âm (-) là xuất khẩu ròng. Đường tham chiếu \(\mathbf{y = 0}\) đại diện cho trạng thái cân bằng dòng chảy ròng (nhập bằng xuất).

    • Mối quan hệ Tổng quát: Nhìn chung, ở hầu hết các nhóm tác động của NLTT, có một mối quan hệ nghịch biến rõ rệt giữa Nhu cầu Quốc gia (\(nd\)) và Tổng Dòng chảy (\(total\_flow\)). Khi nhu cầu tăng, tổng dòng chảy có xu hướng giảm (tức là chuyển từ nhập khẩu ròng sang xuất khẩu ròng hoặc ít nhập khẩu hơn). Điều này cho thấy khi nhu cầu nội địa cao, hệ thống có xu hướng giảm phụ thuộc vào nhập khẩu hoặc thậm chí tăng xuất khẩu để đáp ứng.

    • Tác động của NLTT (Facet Wrap): Ở nhóm Tác động Thấp và Trung bình, mối quan hệ nghịch biến giữa nhu cầu và dòng chảy là mạnh và rõ ràng nhất, thể hiện qua độ dốc âm lớn của đường xu hướng. Ở nhóm Tác động Cao, đường xu hướng có vẻ ít dốc hơn hoặc thậm chí gần như nằm ngang (đặc biệt trong Mùa Thu và Mùa Xuân), cho thấy khi NLTT đóng góp lớn, mối liên hệ giữa nhu cầu và dòng chảy liên kết trở nên lỏng lẻo hơn hoặc bị che mờ bởi vai trò của NLTT.

    • Tác động của Mùa: Các mùa có Nhu cầu cao hơn (Đông - màu xanh đậm) thường nằm ở phía phải của biểu đồ và có xu hướng cắt đường \(\mathbf{y = 0}\) ở mức nhu cầu cao hơn so với các mùa khác. Mùa Hè (màu đỏ) thường có Tổng Dòng chảy ròng ít dương nhất (gần \(0\) hoặc âm hơn), cho thấy ít nhập khẩu ròng nhất so với các mùa khác, đặc biệt khi nhu cầu ở mức trung bình. Mùa Đông và Mùa Thu (màu tím/xanh lá) có vẻ là những mùa có xu hướng nhập khẩu ròng nhiều hơn (điểm nằm phía trên \(\mathbf{y = 0}\)) ở mức nhu cầu thấp và trung bình.

    4.16: Bản đồ Trực quan hóa Nhu cầu Điện (Dot Map)

    world <- ne_countries(scale = "medium", returnclass = "sf") 
    uk_map <- world[world$sovereignt == "United Kingdom", ] 
    avg_ewdemand <- mean(processed_data$england_wales_demand, na.rm = TRUE) 
    center_point <- st_sfc(st_point(c(-1.5, 52.5)), crs = 4326) 
    ggplot(data = uk_map) + 
      geom_sf(fill = "antiquewhite") +
      geom_sf(data = center_point, aes(color = avg_ewdemand, size = avg_ewdemand), alpha = 0.6) + 
      labs(
        title = "Nhu cầu Điện Trung bình tại Anh & Wales",
        subtitle = paste0("Giá trị trung bình giai đoạn 2009-2024: ", round(avg_ewdemand, 0), " MW"), 
        caption = "Vị trí điểm là tượng trưng"
      ) +
      scale_color_gradient(low = "yellow", high = "red", name = "Nhu cầu TB (MW)") + 
      guides(size = "none") + 
      coord_sf(xlim = c(-8, 2), ylim = c(49, 59), expand = FALSE) + 
      theme(
        panel.background = element_rect(fill = "aliceblue"), 
        axis.text = element_blank(), 
        axis.ticks = element_blank(), 
        panel.grid.major = element_line(color = "white", linetype = "dashed") 
      )

    Nhận xét: Biểu đồ xác định rằng Nhu cầu Điện Trung bình cho khu vực Anh & Wales trong giai đoạn 15 năm này là khoảng 28,390 MW. Điểm dữ liệu tượng trưng được tô màu đỏ cam đậm và có kích thước lớn, theo thang màu được thiết lập, cho thấy nhu cầu này là một giá trị cao so với phạm vi dữ liệu tổng thể (nếu không có so sánh tương đối, ta chỉ biết giá trị tuyệt đối).

    4.17: “Bảng điều khiển Hiệu suất Năng lượng” (Energy Performance Dashboard).

    dothi17 <- processed_data %>%
      filter(year_group == "Recent Period") %>%
      summarise(
        avg_nd = mean(nd),        
        avg_flow = mean(total_flow), 
        avg_ratio = mean(embedded_ratio) 
      )
    p1 <- ggplot() + 
      geom_rect(aes(xmin=0,xmax=1,ymin=0,ymax=1), fill="#E6F5FF") + 
      annotate("text", x=0.5, y=0.6, label=paste0(round(dothi17$avg_nd/1000,1)," GW"), size=10) + 
      annotate("text", x=0.5, y=0.85, label="Nhu cầu TB", size=5) +
      theme_void() 
    p2 <- ggplot() + 
      geom_rect(aes(xmin=0,xmax=1,ymin=0,ymax=1), fill="#E6FFF5") +
      annotate("text", x=0.5, y=0.6, label=paste0(round(dothi17$avg_flow)," MW"), size=10, color="darkgreen") + 
      annotate("text", x=0.5, y=0.85, label="Dòng chảy Nhập ròng TB", size=5) + 
      theme_void() 
    p3 <- ggplot() + 
      geom_rect(aes(xmin=0,xmax=1,ymin=0,ymax=1), fill="#FFF5E6") + 
      annotate("text", x=0.5, y=0.6, label=scales::percent(dothi17$avg_ratio, 0.1), size=10, color="orange") + 
      annotate("text", x=0.5, y=0.85, label="Tỷ lệ NLTT TB", size=5) + 
      theme_void() 
    (p1 + p2 + p3) +
      plot_layout(ncol = 3) + 
      plot_annotation(
        title = 'Bảng điều khiển Hiệu suất Năng lượng (Giai đoạn 2021-2024)',
        theme = theme(plot.title = element_text(size = 18, face = "bold", hjust = 0.5)) 
      )

    Nhận xét: Bảng điều khiển xác nhận rằng trong giai đoạn 2021-2024, hệ thống điện Anh đang ở trạng thái chuyển đổi mạnh mẽ, với \(12.4\%\) nhu cầu được đáp ứng bởi các nguồn năng lượng tái tạo phân tán. Tuy nhiên, bất chấp sự tăng trưởng đó, quốc gia này vẫn duy trì tình trạng nhập khẩu ròng đáng kể (\(\approx 1300 \text{ MW}\)) để đáp ứng tổng nhu cầu trung bình \(\approx 26.8 \text{ GW}\), cho thấy sự phụ thuộc vào nguồn cung nước ngoài để cân bằng lưới điện vẫn còn cao trong quá trình giảm dần nhiên liệu hóa thạch.

    4.18: Biểu đồ đồng hồ đo (Gauge Chart) thể hiện tỷ lệ tận dụng công suất điện mặt trời trung bình trong một khoảng thời gian cụ thể (2017-2020).

    solar_utilization <- processed_data %>%
      filter(year_group == "Later Period" & embedded_solar_capacity > 0) %>% 
      summarise(util_rate = mean(embedded_solar_generation / embedded_solar_capacity, na.rm = TRUE)) %>% 
      pull(util_rate) 
    gauge_data_solar <- data.frame(value = c(solar_utilization, 1 - solar_utilization), category = c("Used", "Unused")) 
    ggplot(gauge_data_solar, aes(x = 1.2, y = value, fill = category)) + 
      geom_col(width = 0.8, color = "black") + 
      coord_polar("y", start = -pi / 2) + 
      ylim(c(-0.5, 1.5)) +
      annotate("text", x = 0, y = 0, label = scales::percent(solar_utilization, 0.1), size = 10, color = "#e6550d") + 
      annotate("text", x = 1.2, y = 1.05, label = "Max", size = 3) + 
      scale_fill_manual(values = c("Used" = "#fdae6b", "Unused" = "grey80")) + 
      labs(title = "Tỷ lệ Tận dụng Công suất Điện Mặt trời Trung bình (2017-2020)") 

    Nhận xét: Tỷ lệ Tận dụng Công suất Điện Mặt trời trung bình (Capacity Factor) trong giai đoạn 2017-2020 đạt mức 10.2%, một con số thấp nhưng mang tính thống kê hợp lý đối với công nghệ quang điện ở Vương quốc Anh. Tỷ lệ này xác nhận rằng, trung bình các hệ thống điện mặt trời chỉ hoạt động ở 10.2% công suất tối đa theo thiết kế do đặc tính gián đoạn (chỉ hoạt động vào ban ngày) và điều kiện khí hậu. Con số thấp này cho thấy điện mặt trời không thể là nguồn cung ứng nền ổn định (baseload power) và buộc hệ thống điện phải dựa vào các nguồn dự phòng (như nhiệt điện) để bù đắp cho khoảng 89.8% công suất còn lại. Đây là thách thức chính, nhấn mạnh tầm quan trọng của việc đầu tư vào công nghệ lưu trữ để tích trữ năng lượng từ ban ngày.

    4.19: Biểu đồ Vòng lặp Theo mùa

    seasonal_loop_ratio <- processed_data %>% 
      filter(year == 2023) %>% 
      group_by(month, season) %>% 
      summarise( 
        avg_nd = mean(nd, na.rm = TRUE), 
        avg_ratio = mean(embedded_ratio, na.rm = TRUE) 
      )
    ggplot(seasonal_loop_ratio, aes(x = avg_nd, y = avg_ratio)) + 
      geom_path(arrow = arrow(length = unit(0.2, "cm"))) + 
      geom_point(aes(color = season), size = 6) + 
      geom_text(aes(label = month), size = 3, color = "black") + 
      labs( 
        title = "Vòng lặp Nghịch đảo giữa Nhu cầu và Tỷ lệ NLTT (Năm 2023)",
        x = "Nhu cầu Quốc gia Trung bình (MW)", 
        y = "Tỷ lệ NLTT Trung bình", 
        color = "Mùa" 
      ) +
      scale_color_brewer(palette = "Set1") + 
      scale_y_continuous(labels = percent) 

    Nhận xét: Phân tích biểu đồ “Vòng lặp theo mùa” cho thấy một mối quan hệ nghịch đảo và mang tính chu kỳ rõ rệt giữa nhu cầu điện và tỷ lệ năng lượng tái tạo (NLTT) trong năm 2023. Cụ thể, vào Mùa Hè, nhu cầu tiêu thụ ở mức thấp nhất nhưng sản lượng điện mặt trời lại đạt đỉnh, đẩy tỷ lệ NLTT lên cao nhất. Ngược lại, Mùa Đông chứng kiến nhu cầu sưởi ấm và chiếu sáng tăng vọt, trong khi sản lượng mặt trời gần như bằng không, khiến tỷ lệ NLTT giảm mạnh. Kết quả này không chỉ minh họa một quy luật tự nhiên mà còn chỉ ra thách thức chiến lược cốt lõi của ngành năng lượng Anh: sự lệch pha giữa thời điểm sản xuất năng lượng sạch dồi dào và thời điểm nhu cầu tiêu thụ ở mức cao nhất, qua đó nhấn mạnh tầm quan trọng của các giải pháp lưu trữ năng lượng.

    PHẦN 2: PHÂN TÍCH CTCP CHỨNG KHOÁN SSI QUA BÁO CÁO TÀI CHÍNH: GIAI ĐOẠN 2015 - 2024

    Ở phần 2, em sử dụng bộ dữ liệu về các chỉ tiêu trong Bảng Kết quả Hoạt động Kinh doanh của CTCP Chứng khoán SSI từ năm 2015 - 2024 (10 năm). Dữ liệu được em thu thập và tổng hợp từ các báo cáo tài chính hợp nhất kiểm toán cuối năm được đăng tải công khai trên website chính thức của SSI. Bộ dữ liệu đã được xóa bỏ bớt đi một số chỉ tiêu và chỉ giữ lại những chỉ tiêu trọng tâm mà CTCP Chứng khoán SSI nói riêng và các công ty khác nói chung quan tâm đến để em tiến hành phân tích và đánh giá.

    Tải các gói thư viện cần thiết

    library(dplyr)
    library(lubridate)
    library(ggplot2)
    library(scales)
    library(knitr)
    library(kableExtra)
    library(sf)
    library(patchwork)
    library(tibble)
    library(tidyr)
    library(psych)
    library(tidyverse)
    library(corrr)
    library(gifski)
    library(readxl)
    library(ggrepel)
    library(reshape2)
    library(moments)

    1. Giới thiệu bộ dữ liệu (10 thao tác)

    1.1: Đọc dữ liệu từ tệp Excel

    data_SSI <- read_excel("dataofSSI.xlsx") 

    Giải thích code: dùng hàm read_excel để đọc dữ liệu từ tệp có định dạng Excel, sau đó dùng toán tử gán “<-” để tạo ra data frame có tên là data_SSI và lưu trữ toàn bộ nội dung đã đọc được từ tệp Excel.

    Ý nghĩa của kết quả: Bộ dữ liệu đã được đọc và được lưu trong một data frame tên là data_SSI để thuận tiện cho việc xử lý và phân tích ở các bước tiếp theo.

    1.2: Kiểm tra kích thước của bộ dữ liệu

    dim(data_SSI) 
    ## [1] 10 18

    Giải thích code: dùng hàm dim() để lấy ra một vector chứa 2 giá trị số nguyên: [số hàng, số cột] của data frame data_SSI.

    Ý nghĩa của kết quả: Bộ dữ liệu có tất cả 10 hàng (tức 10 quan sát ứng với 10 năm) và 18 cột (tức 18 biến).

    1.3: Kiểm tra các giá trị bị thiếu (NA) trên mỗi cột

    missing_values <- colSums(is.na(data_SSI)) 
    mv_table_count <- data.frame(
      Variable = names(missing_values),
      MV_Count = missing_values
    )
    print(mv_table_count) 
    ##                                                                                                                                                                                                                                                                                                    Variable
    ## Nam                                                                                                                                                                                                                                                                                                     Nam
    ## Lai ban cac tai san tai chinh FVTPL                                                                                                                                                                                                                                     Lai ban cac tai san tai chinh FVTPL
    ## Lai tu cac khoan cho vay va phai thu                                                                                                                                                                                                                                   Lai tu cac khoan cho vay va phai thu
    ## Doanh thu nghiep vu  moi gioi chung khoan                                                                                                                                                                                                                         Doanh thu nghiep vu  moi gioi chung khoan
    ## Doanh thu nghiep vu bao lanh, dai ly phat hanh chung khoan                                                                                                                                                                                       Doanh thu nghiep vu bao lanh, dai ly phat hanh chung khoan
    ## Doanh thu nghiep vu tu van dau tu chung khoan                                                                                                                                                                                                                 Doanh thu nghiep vu tu van dau tu chung khoan
    ## Cong doanh thu hoat dong                                                                                                                                                                                                                                                           Cong doanh thu hoat dong
    ## Lo ban cac tai san tai chinh FVTPL                                                                                                                                                                                                                                       Lo ban cac tai san tai chinh FVTPL
    ## Chi phi du phong tai san tai chinh, xu ly ton that cac khoan phai thu kho doi, lo suy giam tai san tai chinh va chi phi di vay duoi cac khoan cho vay Chi phi du phong tai san tai chinh, xu ly ton that cac khoan phai thu kho doi, lo suy giam tai san tai chinh va chi phi di vay duoi cac khoan cho vay
    ## Chi phi nghiep vu moi gioi chung khoan                                                                                                                                                                                                                               Chi phi nghiep vu moi gioi chung khoan
    ## Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan                                                                                                                                                                                           Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan
    ## Chi phi nghiep vu tu van dau tu chung khoan                                                                                                                                                                                                                     Chi phi nghiep vu tu van dau tu chung khoan
    ## Cong chi phi hoat dong                                                                                                                                                                                                                                                               Cong chi phi hoat dong
    ## Chi phi tai chinh                                                                                                                                                                                                                                                                         Chi phi tai chinh
    ## Tong loi nhuan ke toan truoc thue                                                                                                                                                                                                                                         Tong loi nhuan ke toan truoc thue
    ## Loi nhuan ke toan sau thue TNDN                                                                                                                                                                                                                                             Loi nhuan ke toan sau thue TNDN
    ## Loi nhuan sau thue phan bo cho chu so huu                                                                                                                                                                                                                         Loi nhuan sau thue phan bo cho chu so huu
    ## Lai co ban tren moi co phieu (VND/1 co phieu)                                                                                                                                                                                                                 Lai co ban tren moi co phieu (VND/1 co phieu)
    ##                                                                                                                                                       MV_Count
    ## Nam                                                                                                                                                          0
    ## Lai ban cac tai san tai chinh FVTPL                                                                                                                          0
    ## Lai tu cac khoan cho vay va phai thu                                                                                                                         0
    ## Doanh thu nghiep vu  moi gioi chung khoan                                                                                                                    0
    ## Doanh thu nghiep vu bao lanh, dai ly phat hanh chung khoan                                                                                                   0
    ## Doanh thu nghiep vu tu van dau tu chung khoan                                                                                                                0
    ## Cong doanh thu hoat dong                                                                                                                                     0
    ## Lo ban cac tai san tai chinh FVTPL                                                                                                                           0
    ## Chi phi du phong tai san tai chinh, xu ly ton that cac khoan phai thu kho doi, lo suy giam tai san tai chinh va chi phi di vay duoi cac khoan cho vay        0
    ## Chi phi nghiep vu moi gioi chung khoan                                                                                                                       0
    ## Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan                                                                                                     1
    ## Chi phi nghiep vu tu van dau tu chung khoan                                                                                                                  0
    ## Cong chi phi hoat dong                                                                                                                                       0
    ## Chi phi tai chinh                                                                                                                                            3
    ## Tong loi nhuan ke toan truoc thue                                                                                                                            0
    ## Loi nhuan ke toan sau thue TNDN                                                                                                                              0
    ## Loi nhuan sau thue phan bo cho chu so huu                                                                                                                    0
    ## Lai co ban tren moi co phieu (VND/1 co phieu)                                                                                                                0

    Một bảng tổng hợp số lượng các giá trị bị thiếu (NA) tương ứng với mỗi biến trong bộ dữ liệu “data_SSI” được tạo ra. Cụ thể, trong 18 biến của bộ dữ liệu, thì:

    • Biến “Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan” có 1 giá trị bị thiếu (NA).

    • Biến “Chi phi tai chinh” có 3 giá trị bị thiếu (NA).

    1.4: Đếm tổng số lượng missing values

    sum(is.na(data_SSI)) 
    ## [1] 4

    Giải thích code: dùng hàm is.na() để xác định các giá trị thiếu, sau đó dùng hàm Sum() để đếm tổng số lượng các giá trị thiếu của bộ dữ liệu.

    Ý nghĩa của kết quả: Bộ dữ liệu có 4 giá trị bị thiếu.

    1.5: Kiểm tra số lượng quan sát trùng lặp

    sum(duplicated(data_SSI))
    ## [1] 0

    Giải thích code: dùng hàm duplicated() để tìm tất cả các hàng trùng lặp, sau đó dùng hàm sum() để tổng số lượng các hàng trùng lặp đó.

    Ý nghĩa của kết quả: Bộ dữ liệu không có hiện tượng trùng lặp.

    1.6: Kiểm tra cấu trúc bộ dữ liệu

    glimpse(data_SSI)
    ## Rows: 10
    ## Columns: 18
    ## $ Nam                                                                                                                                                     <dbl> …
    ## $ `Lai ban cac tai san tai chinh FVTPL`                                                                                                                   <dbl> …
    ## $ `Lai tu cac khoan cho vay va phai thu`                                                                                                                  <dbl> …
    ## $ `Doanh thu nghiep vu  moi gioi chung khoan`                                                                                                             <dbl> …
    ## $ `Doanh thu nghiep vu bao lanh, dai ly phat hanh chung khoan`                                                                                            <dbl> …
    ## $ `Doanh thu nghiep vu tu van dau tu chung khoan`                                                                                                         <dbl> …
    ## $ `Cong doanh thu hoat dong`                                                                                                                              <dbl> …
    ## $ `Lo ban cac tai san tai chinh FVTPL`                                                                                                                    <dbl> …
    ## $ `Chi phi du phong tai san tai chinh, xu ly ton that cac khoan phai thu kho doi, lo suy giam tai san tai chinh va chi phi di vay duoi cac khoan cho vay` <dbl> …
    ## $ `Chi phi nghiep vu moi gioi chung khoan`                                                                                                                <dbl> …
    ## $ `Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan`                                                                                              <dbl> …
    ## $ `Chi phi nghiep vu tu van dau tu chung khoan`                                                                                                           <dbl> …
    ## $ `Cong chi phi hoat dong`                                                                                                                                <dbl> …
    ## $ `Chi phi tai chinh`                                                                                                                                     <dbl> …
    ## $ `Tong loi nhuan ke toan truoc thue`                                                                                                                     <dbl> …
    ## $ `Loi nhuan ke toan sau thue TNDN`                                                                                                                       <dbl> …
    ## $ `Loi nhuan sau thue phan bo cho chu so huu`                                                                                                             <dbl> …
    ## $ `Lai co ban tren moi co phieu (VND/1 co phieu)`                                                                                                         <dbl> …

    Giải thích code: đoạn code được dùng để liệt kê kiểu dữ liệu của mọi biến (cột) trong data frame data_SSI.

    Ý nghĩa của kết quả: Bộ dữ liệu có 18 biến định lượng (numberic).

    1.7: Xem 2 dòng dữ liệu đầu tiên & Xem 2 dòng dữ liệu cuối cùng

    data_SSI %>%
      head(2) %>%
      select(`Cong doanh thu hoat dong`, `Cong chi phi hoat dong`, `Loi nhuan ke toan sau thue TNDN`) %>%
      kable(format = "latex", booktabs = TRUE, caption = "2 dòng đầu tiên của bộ dữ liệu") %>%
      kable_styling(latex_options = c("hold_position", "striped", "scale_down"), position = "center", font_size = 9)

    Giải thích code:

    • (2): dùng hàm head() để chọn và lấy 2 dòng đầu tiên của data frame data_SSI

    • (3): dùng hàm select() để chọn lọc và giữ lại 3 biến cần quan sát từ 2 dòng dữ liệu vừa trích xuất.

    • (4): dùng hàm kable() để chuyển đổi tập dữ liệu đã lọc thành một bảng; tham số format = “latex” được dùng để định dạng đầu ra cho bảng; tham số booktabs = TRUE được dùng để sử dụng các quy tắc định dạng bảng chất lượng cao; tham số caption = “…” được dùng để thêm tiêu đề cho bảng.

    • (5): dùng hàm kable_styling để áp dụng các tùy chỉnh định dạng nâng cao cho bảng; tham số latex_options = c(…) dùng để thêm các tùy chỉnh đặc biệt như “hold_position”, “striped” - tạo hiệu ứng sọc ngang, “scale_down” - thu nhỏ kích thước bảng; tham số position = “center” dùng để căn giữa bảng trên trang; tham số font_size = 9 dùng để đặt cỡ chữ của bảng là 9 point.

    Ý nghĩa của kết quả: Kết quả cho ra bảng xem trước của 2 dòng dữ liệu đầu tiên..

    1.8: Kiểm tra tên các biến (cột)

    colnames(data_SSI) # sử dụng hàm "colnames" để truy xuất tên của các biến (cột) trong bộ dữ liệu "data_SSI".
    ##  [1] "Nam"                                                                                                                                                  
    ##  [2] "Lai ban cac tai san tai chinh FVTPL"                                                                                                                  
    ##  [3] "Lai tu cac khoan cho vay va phai thu"                                                                                                                 
    ##  [4] "Doanh thu nghiep vu  moi gioi chung khoan"                                                                                                            
    ##  [5] "Doanh thu nghiep vu bao lanh, dai ly phat hanh chung khoan"                                                                                           
    ##  [6] "Doanh thu nghiep vu tu van dau tu chung khoan"                                                                                                        
    ##  [7] "Cong doanh thu hoat dong"                                                                                                                             
    ##  [8] "Lo ban cac tai san tai chinh FVTPL"                                                                                                                   
    ##  [9] "Chi phi du phong tai san tai chinh, xu ly ton that cac khoan phai thu kho doi, lo suy giam tai san tai chinh va chi phi di vay duoi cac khoan cho vay"
    ## [10] "Chi phi nghiep vu moi gioi chung khoan"                                                                                                               
    ## [11] "Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan"                                                                                             
    ## [12] "Chi phi nghiep vu tu van dau tu chung khoan"                                                                                                          
    ## [13] "Cong chi phi hoat dong"                                                                                                                               
    ## [14] "Chi phi tai chinh"                                                                                                                                    
    ## [15] "Tong loi nhuan ke toan truoc thue"                                                                                                                    
    ## [16] "Loi nhuan ke toan sau thue TNDN"                                                                                                                      
    ## [17] "Loi nhuan sau thue phan bo cho chu so huu"                                                                                                            
    ## [18] "Lai co ban tren moi co phieu (VND/1 co phieu)"

    Danh sách tên của 18 biến, tương ứng với 18 cột trong bộ dữ liệu lần lượt là:

    1. Nam

    2. Lai ban cac tai san tai chinh FVTPL

    3. Lai tu cac khoan cho vay va phai thu

    4. Doanh thu nghiep vu moi gioi chung khoan

    5. Doanh thu nghiep vu bao lanh, dai ly phat hanh chung khoan

    6. Doanh thu nghiep vu tu van dau tu chung khoan

    7. Cong doanh thu hoat dong

    8. Lo ban cac tai san tai chinh FVTPL

    9. Chi phi du phong tai san tai chinh, xu ly ton that cac khoan phai thu kho doi, lo suy giam tai san tai chinh va chi phi di vay duoi cac khoan cho vay

    10. Chi phi nghiep vu moi gioi chung khoan

    11. Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan

    12. Chi phi nghiep vu tu van dau tu chung khoan

    13. Cong chi phi hoat dong

    14. Chi phi tai chinh

    15. Tong loi nhuan ke toan truoc thue

    16. Loi nhuan ke toan sau thue TNDN

    17. Loi nhuan sau thue phan bo cho chu so huu

    18. Lai co ban tren moi co phieu (VND/1 co phieu)

    1.9: Kiểm tra thứ tự các năm

    year_vector <- data_SSI[, 1] 
    is_not_sorted <- is.unsorted(year_vector)
    cat("Dữ liệu có bị xáo trộn (TRUE) hay không (FALSE)?\n")
    ## Dữ liệu có bị xáo trộn (TRUE) hay không (FALSE)?
    print(is_not_sorted) 
    ## [1] FALSE
    is_consecutive <- all(diff(year_vector) == 1)
    cat("\nDữ liệu có liền mạch theo từng năm (TRUE) hay không (FALSE)?\n")
    ## 
    ## Dữ liệu có liền mạch theo từng năm (TRUE) hay không (FALSE)?
    print(is_consecutive) 
    ## [1] TRUE

    Giải thích code:

    • (1): dùng toán tử “[” và “,” để truy cập và chọn tất cả cách hàng ở cột thứ nhất từ data frame data_SSI, sau đó dùng toán tử gán “<-” để lưu trữ cột dữ liệu đã trích xuất đó vào đối tượng mới tên là year_vector.

    • (2):dùng hàm is.unsorted() để kiểm tra xem các phần tử trong year_vector có không được sắp xếp theo thứ tự tăng dần hay không, dùng toán tử gán “<-” để lưu trữ kết quả logic vào biến is_not_unsorted.

    • (3): dùng hàm cat() để in ra một chuỗi ký tự cố định để giải thích kết quả sắp được hiển thị.

    • (4): dùng hàm print() để hiển thị giá trị TRUE hoặc FALSE của biến is_not_unsorted.

    • (5): dùng hàm diff() để kiểm tra xem tất cả các hiệu số được tính bởi diff() có bằng 1 hay không, sau đó dùng hàm all() để kiểm tra xem tất cả các giá trị logic (từ phép so sánh == 1) có đều là TRUE hay không và dùng toán từ gán “<-” để lưu trữ kết quả logic cuối cùng vào biến is_consecutive.

    • (6): dùng hàm cat() để in ra một chuỗi ký tự cố định để giải thích kết quả sắp được hiển thị.

    • (7): dùng hàm print() để hiển thị giá trị TRUE hoặc FALSE của biến is_concsecutive.

    Ý nghĩa của kết quả: Bộ dữ liệu không bị xáo trộn và đã được sắp xếp theo thứ tự từng năm một cách liền mạch.

    1.10: Bảng tổng hợp đơn vị tính của các biến

    Kết quả: Bảng tổng hợp đơn vị tính của các biến trong bộ dữ liệu.

    2. Xử lý dữ liệu, mã hóa dữ liệu

    2.1: Đổi tên biến

    colnames(data_SSI)[colnames(data_SSI) == "Lai ban cac tai san tai chinh FVTPL"] <- "FVTPL_lai"
    colnames(data_SSI)[colnames(data_SSI) == "Lo ban cac tai san tai chinh FVTPL"] <- "FVTPL_lo"
    colnames(data_SSI)[colnames(data_SSI) == "Tong loi nhuan ke toan truoc thue"] <- "EBIT"
    colnames(data_SSI)[colnames(data_SSI) == "Loi nhuan ke toan sau thue TNDN"] <- "EAT"
    colnames(data_SSI)[colnames(data_SSI) == "Lai co ban tren moi co phieu (VND/1 co phieu)"] <- "EPS"
    colnames(data_SSI)[colnames(data_SSI) == "Cong chi phi hoat dong"] <- "OPEX"

    Giải thích code: Sử dụng hàm colnames() để truy cập vào vector chứa tất cả tên cột của data frame data_SSI, dùng toán tử so sánh “==” để tìm vị trí của các biến (cột) muốn đổi tên, sau đó dùng toán tử gán “<-” để thay thế tên cũ bằng tên mới.

    Ý nghĩa của kết quả: Chuẩn hóa tên một số biến theo thông lệ phân tích tài chính:

    • FVTPL_lai, FVTPL_lo: Lãi/Lỗ bán tài sản tài chính FVTPL.

    • EBIT (Earnings Before Interest and Taxes): Lợi nhuận trước thuế và lãi vay (tương ứng với Tổng lợi nhuận kế toán trước thuế).

    • EAT (Earnings After Taxes): Lợi nhuận sau thuế.

    • EPS (Earnings Per Share): Lãi cơ bản trên mỗi cổ phiếu.

    • OPEX (Operating Expenses): Chi phí hoạt động.

    2.2: Xử lý các missing values

    data_SSI$`Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan`[is.na(data_SSI$`Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan`)] <- mean(data_SSI$`Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan`, na.rm = TRUE)
    data_SSI$`Chi phi tai chinh`[is.na(data_SSI$`Chi phi tai chinh`)] <- mean(data_SSI$`Chi phi tai chinh`, na.rm = TRUE)

    Giải thích code:

    • (1): dùng hàm is.na() để kiểm tra từng phần tử của cột “Chi phi nghiep vu bao lanh, dai ly phat hanh chung khoan”, dùng toán tử “[” và ”]” để chọn những hàng có giá trị bị thiếu (NA) trong cột này, sau đó dùng hàm mean() để tính toán giá trị trung bình của cột với tham số na.rm = TRUE được dùng để bỏ qua các giá trị NA khi tính trung bình và dùng toán tử gán “<-” để thay thế tất cả các giá trị thiếu đã được chọn bằng giá trị trung bình vừa tính được.

    • (2): lặp lại việc thay thế các giá trị thiếu NA bằng giá trị trung bình với cột “Chi phi tai chinh”.

    Ý nghĩa của kết quả: Các giá trị thiếu (NA) trong bộ dữ liệu đã được lấp đầy.

    2.3: Tạo biến mới

    data_SSI <- data_SSI %>% 
      mutate(
        EBT = (EBIT/`Cong doanh thu hoat dong`)*100,
        PAT = (EAT/`Cong doanh thu hoat dong`)*100,
        `OPEX ratio` = (OPEX/`Cong doanh thu hoat dong`)*100
    )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(5): dùng hàm mutate() để tạo 3 cột mới có tên lần lượt là EBT (Tỷ suất lợi nhuận trước thuế so với tổng doanh thu hoạt động: \(\frac{EBIT}{\text{Tổng doanh thu hoạt động}} \times 100\)), PAT (Tỷ suất lợi nhuận sau thuế so với tổng doanh thu hoạt động): \(\frac{EAT}{\text{Tổng doanh thu hoạt động}} \times 100\)OPEX ratio (Tỷ lệ chi phí hoạt động so với doanh thu hoạt động): \(\frac{OPEX}{\text{Tổng doanh thu hoạt động}} \times 100\)

    Ý nghĩa của kết quả: 3 biến mới xuất hiện trong data frame data_SSI, trong đó:

    • EBT thể hiện hiệu quả sinh lời của hoạt động kinh doanh.

    • PAT thể hiện phần trăm lợi nhuận ròng cuối cùng mà công ty thu được từ doanh thu.

    • OPEX ratio thể hiện mức độ kiểm soát chi phí hoạt động của doanh nghiệp.

    2.4: Phân tổ theo Tổng doanh thu từ các hoạt động của công ty

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom doanh thu` = cut(`Cong doanh thu hoat dong`, 
                              breaks = quantile(`Cong doanh thu hoat dong`, probs = 0:4/4, na.rm = TRUE),
                              include.lowest = TRUE,
                              labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom doanh thu, dùng hàm cut() để chuyển đổi dữ liệu liên tục “Cong doanh thu hoat dong” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “Cong doanh thu hoat dong” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Quy mô doanh thu, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.5: Phân tổ theo Chi phí hoạt động của công ty

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom OPEX` = cut(OPEX, 
                          breaks = quantile(OPEX, probs = 0:4/4, na.rm = TRUE),
                          include.lowest = TRUE,
                          labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom OPEX, dùng hàm cut() để chuyển đổi dữ liệu liên tục “OPEX” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “OPEX” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Quy mô chi phí hoạt động, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.6: Phân tổ theo EBIT (Lợi nhuận trước thuế)

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom EBIT` = cut(EBIT, 
                          breaks = quantile(EBIT, probs = 0:4/4, na.rm = TRUE),
                          include.lowest = TRUE,
                          labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom EBIT, dùng hàm cut() để chuyển đổi dữ liệu liên tục “EBIT” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “EBIT” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Mức độ lợi nhuận trước thuế, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.7: Phân tổ theo EAT (Lợi nhuận sau thuế)

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom EAT` = cut(EAT, 
                         breaks = quantile(EAT, probs = 0:4/4, na.rm = TRUE),
                         include.lowest = TRUE,
                         labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom EAT, dùng hàm cut() để chuyển đổi dữ liệu liên tục “EAT” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “EAT” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Mức độ lợi nhuận sau thuế, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.8: Phân tổ theo EPS (Lợi nhuận sau thuế của công ty trên mỗi cổ phiếu phổ thông đang lưu hành trên thị trường)

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom EPS` = cut(EPS, 
                         breaks = quantile(EPS, probs = 0:4/4, na.rm = TRUE),
                         include.lowest = TRUE,
                         labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom EPS, dùng hàm cut() để chuyển đổi dữ liệu liên tục “EPS” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “EPS” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Mức độ lãi trên mỗi cổ phiếu, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.9: Phân tổ theo EBT (Biên lợi nhuận trước thuế)

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom EBT Margin` = cut(EBT, 
                                breaks = quantile(EBT, probs = 0:4/4, na.rm = TRUE),
                                include.lowest = TRUE,
                                labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom EBT Margin, dùng hàm cut() để chuyển đổi dữ liệu liên tục “EBT” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “EBT” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Mức độ biên lợi nhuận trước thuế, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.10: Phân tổ theo PAT (Biên lợi nhuận sau thuế)

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom PAT Margin` = cut(PAT, 
                                breaks = quantile(PAT, probs = 0:4/4, na.rm = TRUE),
                                include.lowest = TRUE,
                                labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom PAT Margin, dùng hàm cut() để chuyển đổi dữ liệu liên tục “PAT” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “PAT” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Mức độ biên lợi nhuận sau thuế, làm tiền đề cho các phân tích chuyên sâu về sau.

    2.11: Phân tổ theo OPEX ratio (Tỷ lệ chi phí hoạt động trên doanh thu)

    data_SSI <- data_SSI %>%
      mutate(
        `Nhom OPEX Ratio` = cut(`OPEX ratio`, 
                                breaks = quantile(`OPEX ratio`, probs = 0:4/4, na.rm = TRUE),
                                include.lowest = TRUE,
                                labels = c("Q1: Thấp", "Q2: Trung bình thấp", "Q3: Trung bình cao", "Q4: Cao"))
      )

    Giải thích code:

    • (1): cập nhật chính data frame data_SSI.

    • (2)->(6): dùng hàm mutate() để tạo cột mới có tên là Nhom OPEX ratio, dùng hàm cut() để chuyển đổi dữ liệu liên tục “OPEX ratio” thành một biến phân loại (Factor) bằng cách phân loại các giá trị vào các khoảng (bins) xác định. Cụ thể bên trong hàm cut(): dùng hàm quantile() để tính toán các điểm cắt (breaks) dựa trên phân vị; tham số probs = 0:4/4 được dùng để xác định các phân vị cần tính là 0%, 25%, 50%, 75%, và 100%; tham số na.rm = TRUE được dùng để loại bỏ các giá trị NA khi tính phân vị; include.lowest = TRUE được dùng để đảm bảo giá trị nhỏ nhất của “OPEX ratio” được bao gồm trong khoảng đầu tiên; labels = c(…) được dùng để gán nhãn cho 4 khoảng đã được tạo ra.

    Ý nghĩa của kết quả: Phân loại theo Mức độ hiệu quả chi phí hoạt động, làm tiền đề cho các phân tích chuyên sâu về sau.

    3. Thống kê cơ bản (20 thao tác)

    3.1: Tính toán và hiển thị các thống kê mô tả cơ bản cho biến “Cong doanh thu hoat dong”

    describe(data_SSI$`Cong doanh thu hoat dong`)
    ##    vars  n         mean           sd      median     trimmed          mad
    ## X1    1 10 4.740296e+12 2.439313e+12 4.01982e+12 4.66577e+12 3.053455e+12
    ##             min         max        range skew kurtosis           se
    ## X1 1.547519e+12 8.52928e+12 6.981761e+12 0.23    -1.69 771378510034

    Ý nghĩa thống kê: Trong giai đoạn 2015 - 2024, chỉ tiêu “Cộng doanh thu hoạt động” có một số đặc điểm sau:

    - Trung bình (mean): Tổng doanh thu hoạt động trung bình của công ty là \[4.740296e+12 = 4.740.296.000.000 VND\] .

    - Độ lệch chuẩn (Sd):\[2.439313e+12 = 2.439.313.000.000 VND\], độ biến động tương đối cao.

    - Trung bình xén bớt (trimmed): là \[4.66577e+12 = 4.665.770.000.000\], có sự chênh lệch dương so với giá trị mean.

    3.2: Tính toán và hiển thị các thống kê mô tả cơ bản cho biến “Cong chi phi hoat dong”

    describe(data_SSI$OPEX) 
    ##    vars  n        mean           sd       median      trimmed          mad
    ## X1    1 10 1.87858e+12 982385887539 1.776413e+12 1.875354e+12 1.176128e+12
    ##             min          max        range skew kurtosis           se
    ## X1 495009251967 3.287962e+12 2.792952e+12 0.12    -1.66 310657694583

    Kết quả: Các giá trị thống kê mô tả của biến OPEX.

    3.3: Tính toán và hiển thị các thống kê mô tả cơ bản cho biến “EBIT”

    describe(data_SSI$EBIT) 
    ##    vars  n         mean           sd       median      trimmed          mad
    ## X1    1 10 1.966877e+12 957057343992 1.590383e+12 1.883931e+12 780498114221
    ##             min          max       range skew kurtosis           se
    ## X1 1.053798e+12 3.543527e+12 2.48973e+12 0.56    -1.49 302648105841

    Kết quả: Các giá trị thống kê mô tả của biến EBIT.

    3.4: Tính toán và hiển thị các thống kê mô tả cơ bản cho biến “EAT”

    describe(data_SSI$EAT) 
    ##    vars  n         mean           sd       median      trimmed          mad
    ## X1    1 10 1.587427e+12 761762641884 1.279435e+12 1.523663e+12 609864907219
    ##             min          max        range skew kurtosis           se
    ## X1 839860081125 2.845109e+12 2.005249e+12 0.56    -1.49 240890498478

    Kết quả: Các giá trị thống kê mô tả của biến EAT.

    3.5: Tính toán và hiển thị các thống kê mô tả cơ bản cho biến “EPS”

    describe(data_SSI$EPS) 
    ##    vars  n   mean    sd median trimmed   mad  min  max range skew kurtosis
    ## X1    1 10 1841.5 487.1 1660.5 1771.75 263.9 1389 2852  1463 0.91    -0.75
    ##        se
    ## X1 154.04

    Kết quả: Các giá trị thống kê mô tả của biến EPS.

    3.6: Hệ số Biến thiên (Coefficient of Variation - CV) của các biến Lợi nhuận

    cv_results <- data_SSI %>%
      summarise(
        CV_EBIT = sd(EBIT, na.rm = TRUE) / mean(EBIT, na.rm = TRUE) * 100, 
        CV_EAT = sd(EAT, na.rm = TRUE) / mean(EAT, na.rm = TRUE) * 100, 
        CV_EPS = sd(EPS, na.rm = TRUE) / mean(EPS, na.rm = TRUE) * 100
      ) %>%
      pivot_longer(
        cols = everything(), names_to = "Variable", values_to = "CV (%)"
      ) 
    cv_results %>%
      mutate(Variable = gsub("CV_", "", Variable)) %>%
      kable("latex", caption = "Hệ Số Biến Thiên (CV) của Lợi Nhuận", digits = 2, align = 'c') %>%
      kable_styling("striped", full_width = F) 

    3.7: Tốc độ Tăng trưởng Bình quân Năm (CAGR-like) của Doanh thu

    data_sorted <- data_SSI %>% arrange(Nam)
    start_year <- min(data_sorted$Nam)
    end_year <- max(data_sorted$Nam)
    start_revenue <- data_sorted$`Cong doanh thu hoat dong`[data_sorted$Nam == start_year]
    end_revenue <- data_sorted$`Cong doanh thu hoat dong`[data_sorted$Nam == end_year]
    num_years <- end_year - start_year
    if (num_years > 0) {
      cagr_revenue <- ((end_revenue / start_revenue)^(1/num_years) - 1) * 100
    } else {
      cagr_revenue <- 0
    }
    cagr_result <- data.frame(
      Biến = "Cong doanh thu hoat dong",
      Nam_Bat_Dau = start_year,
      Nam_Ket_Thuc = end_year,
      CAGR_Percent = cagr_revenue
    )
    cagr_result %>%
      kable("latex", caption = "Tốc Độ Tăng Trưởng Kép Hàng Năm (CAGR) của Doanh Thu", digits = 2) %>%
      kable_styling("striped", full_width = F)

    3.8: Tính Khoảng Tứ phân vị (IQR) cho Chi phí Hoạt động (OPEX)

    iqr_opex <- data_SSI %>%
      summarise(
        IQR_OPEX = IQR(OPEX, na.rm = TRUE),
        Q3 = quantile(OPEX, 0.75, na.rm = TRUE),
        Q1 = quantile(OPEX, 0.25, na.rm = TRUE)
      )
    iqr_opex %>%
      kable("latex", caption = "Khoảng Tứ Phân Vị (IQR) của Chi Phí Hoạt Động (OPEX)", digits = 0) %>%
      kable_styling("striped", full_width = F)

    3.9: Tỷ lệ phân phối Tỷ lệ OPEX theo nhóm EBIT

    opex_ratio_by_ebit <- data_SSI %>%
      group_by(`Nhom EBIT`, `Nhom OPEX Ratio`) %>%
      summarise(Count = n(), .groups = 'drop_last') %>%
      mutate(Percent = Count / sum(Count) * 100) %>%
      ungroup() %>%
      pivot_wider(names_from = `Nhom OPEX Ratio`, values_from = Percent, values_fill = 0) %>%
      rename(Nhom_EBIT = `Nhom EBIT`)
    opex_ratio_by_ebit %>%
      kable("latex", caption = "Phân Phối Tỷ Lệ OPEX Ratio Theo Nhóm EBIT (%)", digits = 1) %>%
      kable_styling("striped", full_width = F)
    \begin{table} \caption{Phân Phối Tỷ Lệ OPEX Ratio Theo Nhóm EBIT (%)}

    \end{table}

    3.10: EAT trung bình theo Nhóm Chi phí hoạt động (OPEX)

    mean_eat_by_opex <- data_SSI %>%
      group_by(`Nhom OPEX`) %>%
      summarise(
        Mean_EAT = mean(EAT, na.rm = TRUE),
        Count = n()
      ) %>%
      ungroup()
    mean_eat_by_opex %>%
      kable("latex", caption = "EAT Trung Bình Theo Nhóm Chi Phí Hoạt Động (OPEX)", digits = 0) %>%
      kable_styling("striped", full_width = F)

    3.11: Phân tích Sự khác biệt giữa EBT và PAT (Hiệu suất Thuế) theo Năm

    tax_efficiency <- data_SSI %>%
      mutate(
        EBT_minus_PAT = EBT - PAT,
        Tax_Rate_Effective = (EBT_minus_PAT / EBT) * 100 # Tỷ lệ thuế hiệu dụng
      ) %>%
      select(Nam, EBT, PAT, Tax_Rate_Effective)
    tax_efficiency %>%
      kable("latex", caption = "Tỷ Lệ Thuế Hiệu Dụng (EBT - PAT) Theo Năm", digits = 2) %>%
      kable_styling("striped", full_width = F)

    3.12: Khoảng cách giữa Max và Min (Range) của các biến cốt lõi

    range_core <- data_SSI %>%
      select(`Cong doanh thu hoat dong`, OPEX, EBIT, EAT, EPS) %>%
      summarise(
        across(everything(), list(
          Range = ~ max(., na.rm = TRUE) - min(., na.rm = TRUE)
        ))
      ) %>%
      pivot_longer(
        cols = everything(),
        names_to = c("Variable", "Statistic"),
        names_sep = "_",
        values_to = "Range"
      ) %>%
      mutate(Variable = gsub("_Range", "", Variable))
    range_core %>%
      kable("latex", caption = "Khoảng Biến Thiên (Range) của các Chỉ Số Cốt Lõi", digits = 0) %>%
      kable_styling("striped", full_width = F)

    3.13: Tốc độ Tăng trưởng Hàng năm (YoY Growth Rate) của EBIT

    data_sorted <- data_SSI %>% arrange(Nam)
    EBIT_growth <- data_sorted %>%
      mutate(
        EBIT_Lag = lag(EBIT, 1), # Lợi nhuận của năm trước
        EBIT_YoY_Growth = ((EBIT / EBIT_Lag) - 1) * 100
      ) %>%
      select(Nam, EBIT, EBIT_YoY_Growth)
    EBIT_growth %>%
      kable("latex", caption = "Tốc Độ Tăng Trưởng EBIT Hàng Năm (YoY %)", digits = 2) %>%
      kable_styling("striped", full_width = F)
    \begin{table} \caption{Tốc Độ Tăng Trưởng EBIT Hàng Năm (YoY %)}

    \end{table}

    3.14: Tính Tỷ trọng đóng góp của FVTPL (Lãi ròng) vào EBIT

    fvtpl_contribution <- data_SSI %>%
      mutate(
        FVTPL_Net = FVTPL_lai - FVTPL_lo,
        FVTPL_to_EBIT_Ratio = (FVTPL_Net / EBIT) * 100
      ) %>%
      select(Nam, EBIT, FVTPL_Net, FVTPL_to_EBIT_Ratio)
    fvtpl_contribution %>%
      kable("latex", caption = "Tỷ Trọng Đóng Góp của Lãi Ròng FVTPL vào EBIT (%)", digits = 2) %>%
      kable_styling("striped", full_width = F)
    \begin{table} \caption{Tỷ Trọng Đóng Góp của Lãi Ròng FVTPL vào EBIT (%)}

    \end{table}

    3.15: Tương quan giữa EBIT và OPEX Ratio

    corr_ebit_opex_ratio <- data_SSI %>%
      summarise(
        Pearson_Corr = cor(EBIT, `OPEX ratio`, use = "complete.obs")
      )
    corr_ebit_opex_ratio %>%
      kable("latex", caption = "Tương Quan giữa EBIT và OPEX Ratio", digits = 2) %>%
      kable_styling("striped", full_width = F)

    3.16: Dự đoán EBIT dựa trên Doanh thu (Hồi quy Tuyến tính Đơn giản)

    model_EBIT_Revenue <- lm(EBIT ~ `Cong doanh thu hoat dong`, data = data_SSI)
    summary_model_EBIT <- summary(model_EBIT_Revenue)$coefficients
    r_squared <- summary(model_EBIT_Revenue)$r.squared
    model_summary <- data.frame(
      Variable = rownames(summary_model_EBIT),
      Estimate = summary_model_EBIT[, "Estimate"]
    )
    model_summary_formatted <- model_summary %>%
      filter(Variable == "`Cong doanh thu hoat dong`") %>%
      mutate(R_Squared = r_squared)
    model_summary_formatted %>%
      kable("latex", caption = "Ước lượng Hồi quy: EBIT ~ Doanh Thu", digits = c(0, 4, 3)) %>%
      kable_styling("striped", full_width = F)

    3.17: Phân tích Tác động của OPEX Ratio lên EAT (Hồi quy)

    model_EAT_OPEXRatio <- lm(EAT ~ `OPEX ratio`, data = data_SSI)
    summary_model_EAT <- summary(model_EAT_OPEXRatio)$coefficients
    model_summary_EAT <- data.frame(
      Variable = rownames(summary_model_EAT),
      Estimate = summary_model_EAT[, "Estimate"]
    )
    model_summary_EAT_formatted <- model_summary_EAT %>%
      filter(Variable == "`OPEX ratio`") %>%
      mutate(R_Squared = summary(model_EAT_OPEXRatio)$r.squared)
    model_summary_EAT_formatted %>%
      kable("latex", caption = "Ước lượng Hồi quy: EAT ~ OPEX Ratio", digits = c(0, 4, 3)) %>%
      kable_styling("striped", full_width = F)

    3.18:

    growth_data <- data_SSI %>% arrange(Nam) %>%
      mutate(
        EBIT_Growth = (EBIT - lag(EBIT)) / lag(EBIT),
        Revenue_Growth = (`Cong doanh thu hoat dong` - lag(`Cong doanh thu hoat dong`)) / lag(`Cong doanh thu hoat dong`),
        DOL = EBIT_Growth / Revenue_Growth
      ) %>%
      filter(is.finite(DOL)) 
    mean_dol <- mean(growth_data$DOL, na.rm = TRUE)
    dol_df <- data.frame(
      Biến = "DOL (Tăng trưởng EBIT/Tăng trưởng Doanh thu)",
      DOL_Trung_binh = mean_dol
    )
    dol_df %>%
      kable("latex", caption = "Mức Độ Đòn Bẩy Hoạt Động (DOL) Trung Bình", digits = 2) %>%
      kable_styling("striped", full_width = F)

    3.19: Phân tích Tỷ trọng Chi phí Hoạt động (OPEX) trên Doanh thu theo từng năm

    yearly_opex_ratio <- data_SSI %>%
      select(Nam, `Cong doanh thu hoat dong`, OPEX, `OPEX ratio`) %>%
      mutate(
        OPEX_Ratio_Recalculated = (OPEX / `Cong doanh thu hoat dong`) * 100
      ) %>%
      select(Nam, `OPEX ratio`) 
    yearly_opex_ratio %>%
      kable("latex", caption = "Tỷ Lệ Chi Phí Hoạt Động (OPEX Ratio) Theo Năm", digits = 2) %>%
      kable_styling("striped", full_width = F)

    3.20: Giá trị trung bình của EBIT và EAT trong 3 năm gần nhất so với trung bình toàn bộ giai đoạn

    mean_EBIT_total <- mean(data_SSI$EBIT, na.rm = TRUE)
    mean_EAT_total <- mean(data_SSI$EAT, na.rm = TRUE)
    latest_years <- data_SSI %>% arrange(desc(Nam)) %>% head(3)
    mean_EBIT_recent <- mean(latest_years$EBIT, na.rm = TRUE)
    mean_EAT_recent <- mean(latest_years$EAT, na.rm = TRUE)
    performance_comparison <- data.frame(
      Giai_Đoạn = c("Toàn Giai Đoạn", "3 Năm Gần Nhất"),
      EBIT_Mean = c(mean_EBIT_total, mean_EBIT_recent),
      EAT_Mean = c(mean_EAT_total, mean_EAT_recent)
    )
    performance_comparison %>%
      kable("latex", caption = "So Sánh Lợi Nhuận Trung Bình (Toàn Giai Đoạn vs 3 Năm Gần Nhất)", digits = 0) %>%
      kable_styling("striped", full_width = F)

    4. Trực quan hóa dữ liệu (20 biểu đồ)

    4.1: Biểu đồ Đường (Line Chart) - Xu hướng Doanh thu hoạt động

    data_SSI$Nam <- as.numeric(data_SSI$Nam)
    ggplot(data_SSI, aes(x = Nam, y = `Cong doanh thu hoat dong`)) +
      geom_line(color = "#0072B2", linewidth = 1.2) +
      geom_point(color = "#D55E00", size = 3) +
      labs(title = "Xu Hướng Tổng Doanh Thu Hoạt Động (SSI) Theo Năm",
           x = "Năm",
           y = "Doanh Thu Hoạt Động (Tỷ VND)",
           caption = "Nguồn dữ liệu: data_SSI") +
      scale_y_continuous(labels = scales::unit_format(unit = "Tỷ", scale = 1e-9)) +
      scale_x_continuous(
        breaks = unique(data_SSI$Nam), 
        labels = unique(data_SSI$Nam)) 

    Nhận xét: Tổng doanh thu hoạt động của SSI có xu hướng tăng trưởng mạnh từ năm 2015 đến 2024, nhưng doanh thu không tăng trưởng tuyến tính mà có những biến động đáng kể qua các năm.

    Các giai đoạn đáng chú ý:

    • Giai đoạn Tăng trưởng ổn định (2015 - 2018): Doanh thu tăng đều đặn qua các năm, từ mức khoảng 1.500 Tỷ (2015) lên gần 4.000 Tỷ (2018).

    • Giai đoạn Suy giảm ngắn hạn (2018 - 2019): Có sự sụt giảm nhẹ về doanh thu từ 2018 xuống 2019, có thể do điều kiện thị trường không thuận lợi trong giai đoạn đó.

    • Giai đoạn Tăng trưởng vượt bậc (2019 - 2021): Đây là giai đoạn tăng trưởng mạnh nhất, đặc biệt là từ 2020 đến 2021. Doanh thu đã tăng hơn gấp đôi trong khoảng thời gian này, đạt đỉnh cao nhất trong giai đoạn 10 năm tại năm 2021 (ước tính trên 7.000 Tỷ VND). Sự tăng trưởng này thường phản ánh sự bùng nổ của thị trường chứng khoán (như giai đoạn 2020-2021).

    • Giai đoạn Điều chỉnh và Phục hồi (2021 - 2024): Doanh thu bắt đầu phục hồi và tăng trưởng trở lại, vượt qua mức đỉnh 2021 để đạt mức cao nhất mọi thời đại vào năm 2024 (ước tính gần 8.000 Tỷ VND), khẳng định lại xu hướng tăng trưởng dài hạn của công ty.

    4.2: Biểu đồ thanh - Lãi cơ bản trên Cổ phiếu (EPS) của SSI (2015-2024)

    ggplot(data_SSI, aes(x = factor(Nam), y = EPS, fill = EPS)) +
      geom_col(width = 0.7) + 
      geom_text(aes(label = scales::number(EPS, big.mark = ",", accuracy = 1)), 
                vjust = -0.5, color = "black", fontface = "bold", size = 4) +
      scale_fill_gradient(low = "lightblue", high = "navy") + 
      scale_y_continuous(expand = expansion(mult = c(0, 0.1))) + 
      labs(
        title = "Lãi cơ bản trên Cổ phiếu (EPS) của SSI (2015-2024)",
        x = "Năm",
        y = "EPS (VND/cổ phiếu)") 

    Nhận xét: EPS của SSI có sự biến động mạnh trong giai đoạn 2015–2024, cho thấy hiệu quả hoạt động theo năm chịu ảnh hưởng lớn từ chu kỳ thị trường. Năm 2021 là năm có EPS cao nhất với 2.852 VND/cổ phiếu, cao hơn đáng kể so với tất cả các năm khác, khẳng định năm này là năm hoạt động hiệu quả nhất trong thập kỷ. Năm 2022 là năm có EPS thấp nhất trong giai đoạn phục hồi gần đây với 1.389 VND/cổ phiếu, thấp hơn cả mức năm 2020 (1.434 VND).

    4.3: Biểu đồ Tương quan giữa Chi phí Hoạt động và Biên Lợi nhuận (2015-2024)

    ggplot(data_SSI, aes(x = `OPEX ratio`, y = EBT)) +
      geom_path(arrow = arrow(type = "closed", length = unit(0.15, "inches")), 
                color = "gray", linetype = "dashed") +
      geom_point(aes(color = factor(Nam)), size = 5, alpha = 0.8) + 
      geom_text_repel(aes(label = Nam), fontface = "bold", size = 3.5) + 
      scale_x_continuous(labels = label_percent(scale = 1)) + 
      scale_y_continuous(labels = label_percent(scale = 1)) +
      scale_color_viridis_d(direction = -1) + 
      labs(
        title = "Tương quan giữa Chi phí Hoạt động và Biên Lợi nhuận (2015-2024)",
        subtitle = "Mũi tên chỉ xu hướng từ 2015 -> 2024",
        x = "Tỷ lệ Chi phí Hoạt động (OPEX Ratio)",
        y = "Biên Lợi nhuận Trước thuế (EBT Margin)",
        color = "Năm") 

    Nhận xét: Không có mối tương quan tuyến tính rõ ràng giữa OPEX Ratio và EBT Margin trong suốt giai đoạn. Thay vào đó, dữ liệu thể hiện một quỹ đạo chu kỳ và biến động phức tạp. Các năm có Biên Lợi nhuận (Trục Y) cao nhất thường đi kèm với OPEX Ratio (Trục X) thấp hơn, hàm ý rằng trong những năm hiệu suất tốt, công ty quản lý chi phí hoạt động hiệu quả hoặc có doanh thu tăng trưởng vượt bậc hơn chi phí.

    4.4: Biểu đồ Bảng điều khiển KPI các Tỷ lệ của SSI (2015-2024)

    data_bieudo4 <- data_SSI %>%
      select(Nam, EBT, PAT, `OPEX ratio`) %>%
      pivot_longer(cols = -Nam, names_to = "ChiTieu", values_to = "GiaTri")
    ggplot(data_bieudo4, aes(x = factor(Nam), y = ChiTieu, fill = GiaTri)) +
      geom_tile(color = "white", lwd = 1.5) + 
      geom_text(aes(label = scales::percent(GiaTri, scale = 1, accuracy = 0.1)), 
                color = "black", fontface = "bold", size = 4) +
      scale_fill_gradient2(low = "red", mid = "grey", high = "forestgreen", 
                           midpoint = mean(data_bieudo4$GiaTri)) +
      scale_x_discrete(position = "top") + 
      labs(
        title = "Bảng điều khiển KPI các Tỷ lệ của SSI (2015-2024)",
        x = "Năm",
        y = "Chỉ tiêu Tỷ lệ",
        fill = "Giá trị (%)") 

    Nhận xét:

    • 2015 (Năm tốt nhất): Cột xanh đậm nhất trên cả 3 chỉ tiêu. Đây là năm SSI đạt hiệu suất lợi nhuận và quản lý chi phí vượt trội.

    • 2018 (Chi phí cao): OPEX Ratio ở mức cao nhất (45.0% - Màu cam đậm), trong khi các chỉ số lợi nhuận khác chỉ ở mức trung bình.

    • 2021 (Năm bùng nổ): Cả PAT (36.2%) và EBT (45.2%) đều tăng vọt so với năm 2020, cho thấy sự cải thiện lớn về lợi nhuận, nhưng vẫn chưa bằng hiệu suất của giai đoạn 2015-2017.

    • 2022 (Năm kém nhất): Cột Đỏ đậm nhất trên cả 3 chỉ tiêu lợi nhuận (PAT: 26.8%, EBT: 33.3%). Đồng thời, OPEX Ratio cũng ở mức cao (42.7%). Điều này cho thấy sự sụt giảm hiệu suất tổng thể nghiêm trọng nhất trong giai đoạn này.

    4.5: Biểu Đồ Nhiệt tần suất (Frequency Heatmap) - Mối liên hệ tần suất giữa Nhóm Doanh thu và Nhóm EBIT

    data_bieudo5 <- data_SSI %>%
      group_by(`Nhom doanh thu`, `Nhom EBIT`) %>%
      summarise(Count = n(), .groups = 'drop')
    ggplot(data_bieudo5, aes(x = `Nhom doanh thu`, y = `Nhom EBIT`, fill = Count)) +
      geom_tile(color = "white", linewidth = 1) +
      scale_fill_gradient2(low = "#fee090", mid = "#fdae61", high = "#d73027",
                           midpoint = median(data_bieudo5$Count), name = "Số lượng năm") +
      geom_text(aes(label = Count), color = "black", size = 4) +
      labs(
        title = "Mối liên hệ Tần suất giữa Nhóm Doanh thu và Nhóm EBIT",
        x = "Nhóm Doanh thu Hoạt động",
        y = "Nhóm Lợi nhuận trước thuế (EBIT)") 

    Nhận xét: Biểu đồ này xác nhận một mối quan hệ đồng biến (positive correlation) mạnh mẽ giữa Doanh thu và EBIT. Điều này được thể hiện qua việc phần lớn các năm tập trung dọc theo đường chéo từ góc dưới bên trái (Q1/Thấp) lên góc trên bên phải (Q4/Cao).

    • Tập trung ở mức Cao (Q4/Cao): Sự kết hợp Doanh thu cao (Q4: Cao) và EBIT cao (Q4: Cao) là sự kết hợp phổ biến nhất với tần suất 3 năm (ô Đỏ đậm nhất). Điều này cho thấy khi doanh thu đạt mức cao nhất, khả năng cao là lợi nhuận (EBIT) cũng đạt mức cao nhất.

    • Tập trung ở mức Thấp (Q1/Thấp): Sự kết hợp Doanh thu thấp (Q1: Thấp) và EBIT thấp (Q1: Thấp) là sự kết hợp phổ biến thứ hai với tần suất 2 năm.

    4.6: Biểu đồ Tọa độ Song song (Parallel Coordinates Plot) - Xu hướng 3 Tỷ lệ Chính qua các năm

    data_bieudo6 <- data_SSI %>%
      select(Nam, EBT, PAT, `OPEX ratio`) %>%
      pivot_longer(-Nam, names_to = "Bien_Ty_Le", values_to = "Ty_Le") %>%
      mutate(
        Bien_Ty_Le = factor(Bien_Ty_Le, levels = c("OPEX ratio", "EBT", "PAT")) 
      )
    ggplot(data_bieudo6, aes(x = Bien_Ty_Le, y = Ty_Le, group = Nam, color = factor(Nam))) +
      geom_line(size = 1.2) +
      geom_point(size = 3) +
      scale_y_continuous(labels = label_number(suffix = "%")) +
      scale_color_brewer(palette = "Dark2") +
      labs(
        title = "Biến động của 3 Tỷ lệ Hiệu suất chính qua các năm (Parallel Coordinates)",
        x = "Biến Tỷ lệ",
        y = "Giá trị Tỷ lệ (%)",
        color = "Năm") 

    Nhận xét: Tập trung: Hầu hết các năm đều tập trung trong phạm vi OPEX Ratio \(35\% - 45\%\) và EBT/PAT \(30\% - 50\%\). Phân cực: Biểu đồ làm nổi bật sự phân cực của dữ liệu: 2015 là một điểm outlier về Hiệu suất (EBT), trong khi các năm 2019-2024 nằm ở khu vực chi phí cao/lợi nhuận thấp hơn.

    4.7: Biểu đồ Bách phân vị Xếp chồng (Stacked Percent Bar) - Phân phối Nhóm EAT theo Nhóm OPEX Ratio

    ggplot(data_SSI, aes(x = `Nhom OPEX Ratio`, fill = `Nhom EAT`)) +
      geom_bar(position = "fill", color = "black", linewidth = 0.2) +
      scale_y_continuous(labels = percent) +
      scale_fill_brewer(palette = "RdYlGn") +
      labs(
        title = "Phân phối Tỷ trọng Nhóm EAT Margin theo Nhóm OPEX Ratio",
        x = "Nhóm OPEX Ratio",
        y = "Tỷ trọng (%)",
        fill = "Nhóm EAT") 

    Nhận xét: Mặc dù có mối quan hệ nghịch đảo thông thường, sự phân phối lợi nhuận trong nhóm OPEX rất cao (Q4) cho thấy: Trong những năm thị trường bùng nổ, lợi nhuận ròng cao vẫn đạt được, ngay cả khi chi phí hoạt động cũng tăng lên đáng kể.

    4.8: Biểu đồ Donut (Vòng) - Phân phối Nhóm Lợi nhuận trước thuế (EBIT)

    data_bieudo8 <- data_SSI %>%
      group_by(`Nhom EBIT`) %>%
      summarise(Count = n(), .groups = 'drop') %>%
      mutate(
        fraction = Count / sum(Count),
        percentage = paste0(round(fraction * 100, 1), "%"),
        ymax = cumsum(fraction),
        ymin = c(0, head(ymax, n=-1)),
        label_position = (ymax + ymin) / 2
      )
    ggplot(data_bieudo8, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=`Nhom EBIT`)) +
      geom_rect(color = "white") +
      coord_polar(theta="y") +
      geom_text(x=3.5, aes(y=label_position, label=percentage), color="black", size=4) +
      scale_fill_brewer(palette="YlOrRd") +
      xlim(c(2, 4)) +
      labs(
        title = "Phân phối Tần suất của Lợi nhuận trước thuế (EBIT) theo các nhóm phân vị",
        fill = "Nhóm EBIT") 

    Nhận xét: Phân phối tập trung ở hai cực: Sự phân phối của EBIT cho thấy tính phân cực rõ rệt: \(60\%\) số năm (Q1 và Q4) nằm ở hai thái cực (Rất cao và Rất thấp). Điều này cho thấy hoạt động kinh doanh của SSI chịu ảnh hưởng lớn từ các chu kỳ thị trường, dẫn đến lợi nhuận thường rơi vào tình trạng “thắng lớn” hoặc “thua kém” mà ít khi ổn định ở mức trung bình. Thiếu tính ổn định: Chỉ \(40\%\) số năm nằm ở mức lợi nhuận trung bình, củng cố nhận định về sự biến động cao trong hiệu suất lợi nhuận trước thuế.

    4.9: Biểu đồ Xu hướng Tỷ lệ Chi phí hoạt động trên Doanh thu (OPEX Ratio) qua các năm

    ggplot(data_SSI, aes(x = Nam, y = `OPEX ratio`)) +
      geom_area(fill = "#99d8c9", alpha = 0.7) +
      geom_line(color = "#00441b", size = 1.2) +
      geom_point(size = 3, color = "#00441b", shape = 19) +
      scale_x_continuous(breaks = data_SSI$Nam) +
      scale_y_continuous(labels = label_number(suffix = "%")) +
      labs(
        title = "Xu hướng Tỷ lệ Chi phí hoạt động trên Doanh thu (OPEX Ratio) qua các năm",
        x = "Năm",
        y = "OPEX Ratio (%)") 

    Nhận xét: OPEX Ratio dao động trong khoảng từ \(\approx 32\%\) đến \(\approx 45\%\). Mức OPEX Ratio có sự biến động đáng kể, cho thấy sự linh hoạt (hoặc thiếu ổn định) trong quản lý chi phí hoạt động theo điều kiện kinh doanh hàng năm.

    4.10: Biểu đồ Phân Tán (Scatter Plot) - Mối quan hệ giữa OPEX và Doanh thu

    ggplot(data_SSI, aes(x = OPEX, y = `Cong doanh thu hoat dong`)) +
      geom_point(aes(color = factor(Nam)), size = 4, alpha = 0.7) +
      geom_smooth(method = "lm", se = TRUE, color = "gray30", linetype = "dashed") +
      geom_text_repel(aes(label = Nam), size = 3, max.overlaps = 10) +
      labs(title = "Mối Quan Hệ giữa Chi Phí Hoạt Động (OPEX) và Doanh Thu",
           x = "OPEX (Tỷ VND)",
           y = "Doanh Thu Hoạt Động (Tỷ VND)",
           color = "Năm") +
      scale_x_continuous(labels = unit_format(unit = "Tỷ", scale = 1e-9)) +
      scale_y_continuous(labels = unit_format(unit = "Tỷ", scale = 1e-9)) 

    Nhận xét: Tương quan dương mạnh: Các điểm dữ liệu gần như nằm dọc theo đường hồi quy tuyến tính. Điều này xác nhận một mối quan hệ tương quan dương rất mạnh giữa Chi phí Hoạt động (OPEX) và Doanh thu Hoạt động. Trong hoạt động kinh doanh của SSI, khi Chi phí Hoạt động tăng lên, Doanh thu Hoạt động cũng tăng lên (và ngược lại). Điều này là hợp lý đối với các công ty dịch vụ tài chính, nơi việc tăng chi phí (ví dụ: chi phí hoa hồng, chi phí mở rộng mạng lưới, chi phí công nghệ) thường đi kèm với việc mở rộng thị trường và tăng doanh thu.

    4.11: Line Chart with Confidence Interval - Xu hướng EPS và Khoảng biến động

    line_ci_chart_1 <- ggplot(data_SSI, aes(x = Nam, y = EPS)) +
      geom_line(color = "darkgreen", linewidth = 1.2) + 
      geom_point(aes(color = `Nhom EPS`), size = 4) + 
      geom_smooth(method = "loess", se = TRUE, color = "blue", linetype = "dotted", fill = "lightblue", alpha = 0.3) + 
      scale_y_continuous(labels = comma) + 
      scale_x_continuous(breaks = unique(data_SSI$Nam)) + 
      labs(title = "Xu hướng EPS của SSI qua các năm với khoảng biến động", 
           x = "Năm", y = "EPS (VND/cổ phiếu)", color = "Nhóm EPS") 
    print(line_ci_chart_1)

    Nhận xét: EPS của SSI không tăng trưởng ổn định mà có tính chu kỳ rất rõ rệt, chịu ảnh hưởng mạnh mẽ bởi các yếu tố bên ngoài (thị trường chứng khoán). Biểu đồ trực quan hóa thành công tính phân cực này bằng cách sử dụng màu sắc (Tím vs. Đỏ) tại các điểm đỉnh và đáy.

    4.12:

    data_cor_full <- data_SSI %>%
      select(EBIT, EAT, `Cong doanh thu hoat dong`, OPEX, FVTPL_lai, FVTPL_lo, EPS, `OPEX ratio`, EBT, PAT)
    cor_matrix_full <- cor(data_cor_full, use = "complete.obs")
    melted_cor_full <- melt(cor_matrix_full)
    var_names <- c("EBIT", "EAT", "Doanh thu", "OPEX", "Lãi FVTPL", "Lỗ FVTPL", "EPS", "OPEX Ratio", "EBT", "PAT")
    melted_cor_full$Var1 <- factor(melted_cor_full$Var1, levels = unique(melted_cor_full$Var1), labels = var_names)
    melted_cor_full$Var2 <- factor(melted_cor_full$Var2, levels = unique(melted_cor_full$Var2), labels = var_names)
    correlogram_chart_1 <- ggplot(melted_cor_full, aes(x = Var1, y = Var2, fill = value)) + 
      geom_tile(color = "gray", linewidth = 0.5) + 
      scale_fill_gradient2(low = "#1C4E80", high = "#A5375A", mid = "white", 
                           midpoint = 0, limit = c(-1, 1), space = "Lab",
                           name = "Hệ số R") +
      geom_text(aes(label = sprintf("%.2f", value)), color = "black", size = 3) + 
      coord_fixed() + 
      labs(title = "Korelôgram: Ma trận Tương quan Đa biến của các Chỉ số Tài chính",
           x = "", y = "") 
    print(correlogram_chart_1)

    4.13: Facet Grid Plot - Xu hướng Biên Lợi nhuận (EBT, PAT) theo Nhóm OPEX Ratio

    data_long_margin <- data_SSI %>%
      select(Nam, EBT, PAT, `Nhom OPEX`) %>%
      melt(id.vars = c("Nam", "Nhom OPEX"), variable.name = "Loai_Margin", value.name = "Phan_Tram")
    facet_chart_1 <- ggplot(data_long_margin, aes(x = Nam, y = Phan_Tram, color = Loai_Margin)) + 
      geom_line(linewidth = 1) + 
      geom_point(size = 2) + 
      facet_wrap(~ `Nhom OPEX`, ncol = 4) + 
      scale_y_continuous(labels = scales::percent_format(scale = 1)) + 
      scale_x_continuous(breaks = unique(data_long_margin$Nam)) + 
      labs(title = "Xu hướng Biên Lợi nhuận (EBT vs PAT) theo Nhóm OPEX Ratio", 
           x = "Năm", y = "Tỷ Lệ Lợi Nhuận (%)", color = "Loại Biên Lợi Nhuận")
    print(facet_chart_1)

    4.14: Tỷ trọng Biên Lợi nhuận và Tỷ lệ Chi phí (EBT Margin vs OPEX Ratio)

    data_stacked_ratio <- data_SSI %>%
      select(Nam, EBT, `OPEX ratio`) %>%
      melt(id.vars = "Nam", variable.name = "Loai_Ty_Le", value.name = "Ty_Le")
    column_chart_2 <- ggplot(data_stacked_ratio, aes(x = factor(Nam), y = Ty_Le, fill = Loai_Ty_Le)) + 
      geom_col(position = "stack", width = 0.7) + 
      geom_text(aes(label = paste0(round(Ty_Le, 1), "%")), 
                position = position_stack(vjust = 0.5), size = 3) +
      scale_y_continuous(labels = scales::percent_format(scale = 1)) + 
      scale_fill_manual(values = c("EBT" = "red", "OPEX ratio" = "maroon")) + 
      labs(title = "Tỷ trọng Biên Lợi nhuận (EBT) và OPEX Ratio trong Tổng Tỷ lệ Doanh thu",
           x = "Năm", y = "Tỷ Lệ (%)", fill = "Loại Tỷ Lệ")
    print(column_chart_2)

    4.15: Biểu đồ Histogram với Phân Tách (Facet Histogram) - Phân phối EPS theo Nhóm Biên Lợi nhuận Trước thuế (EBT Margin)

    bieudo15 <- ggplot(data_SSI, aes(x = EPS, fill = `Nhom EBT Margin`)) + 
      geom_histogram(position = "identity", bins = 5, color = "black", alpha = 0.7) + 
      facet_wrap(~ `Nhom EBT Margin`, scales = "free_y", ncol = 4) + 
      scale_x_continuous(labels = comma) + 
      labs(title = "Phân phối EPS theo Nhóm Biên Lợi nhuận Trước thuế (EBT Margin)",
           x = "EPS (VND/cổ phiếu)", y = "Số Lượng Quan Sát (Năm)") + 
      scale_fill_brewer(palette = "YlOrRd")
    print(bieudo15)

    Nhận xét: Mối liên hệ dương (Positive Correlation) mạnh mẽ: Rõ ràng EPS cao nhất chỉ xuất hiện khi EBT Margin đạt mức Q3 (Trung bình cao) trở lên.

    4.16:

    hist_density_chart_1 <- ggplot(data_SSI, aes(x = PAT)) + 
      geom_histogram(aes(y = after_stat(density)), bins = 5, fill = "#00BFC4", color = "black", alpha = 0.7) + 
      geom_density(aes(y = after_stat(density)), color = "red", linewidth = 1.2) + 
      geom_vline(aes(xintercept = mean(PAT, na.rm = TRUE)), 
                 color = "red", linetype = "dashed", linewidth = 1) +
      geom_text(aes(x = mean(PAT, na.rm = TRUE), y = 0.05, 
                    label = paste0("Mean: ", round(mean(PAT, na.rm = TRUE), 1), "%")),
                color = "red", hjust = -0.1, size = 3.5) +
      scale_x_continuous(labels = scales::percent_format(scale = 1)) + 
      labs(title = "Phân phối của Biên Lợi nhuận Sau Thuế (PAT Margin)",
           x = "PAT Margin (%)", y = "Mật Độ / Tần Suất Chuẩn Hóa") 
    print(hist_density_chart_1)

    Nhận xét:

    PAT Margin của SSI thể hiện sự không ổn định và phụ thuộc vào các năm bùng nổ (như 2015, 2016, 2017) để duy trì mức trung bình \(35.5\%\). Phần lớn các năm còn lại có lợi nhuận sau thuế ở mức trung bình hoặc thấp hơn.

    4.17: Dumbbell Plot - So sánh Biên Lợi nhuận Trước thuế và Sau thuế (EBT vs PAT) theo từng năm

    data_dumbbell <- data_SSI %>%
      select(Nam, EBT, PAT)
    dumbbell_chart_1 <- ggplot(data_dumbbell) + 
      geom_segment(aes(x = EBT, xend = PAT, y = Nam, yend = Nam), color = "gray", linewidth = 1) + 
      geom_point(aes(x = EBT, y = Nam), color = "red", size = 4) + 
      geom_point(aes(x = PAT, y = Nam), color = "blue", size = 4) + 
      scale_x_continuous(labels = scales::percent_format(scale = 1)) + 
      scale_y_continuous(breaks = unique(data_dumbbell$Nam)) + 
      geom_text(aes(x = EBT, y = Nam, label = round(EBT, 1)), hjust = -0.5, color = "red", size = 3) + 
      geom_text(aes(x = PAT, y = Nam, label = round(PAT, 1)), hjust = 1.5, color = "blue", size = 3) + 
      labs(title = "So sánh Biên lợi nhuận trước thuế (EBT) và sau thuế (PAT) theo năm",
           x = "Tỷ Lệ Lợi Nhuận (%)", y = "Năm")
    print(dumbbell_chart_1)

    4.18: Biểu đồ Violin - Phân phối EBIT theo Nhóm OPEX Ratio

    ggplot(data_SSI, aes(x = `Nhom OPEX Ratio`, y = EBIT, fill = `Nhom OPEX Ratio`)) +
      geom_violin(trim = TRUE, alpha = 0.7, color = "gray") +
      geom_boxplot(width = 0.1, fill = "white", color = "black") +
      stat_summary(fun = "mean", geom = "point", shape = 23, size = 3, fill = "red") +
      labs(title = "Phân Phối EBIT Theo Nhóm Tỷ Lệ OPEX",
           x = "Nhóm OPEX Ratio (Quartile)",
           y = "EBIT (Tỷ VND)",
           fill = "Nhóm OPEX Ratio") +
      scale_y_continuous(labels = unit_format(unit = "Tỷ", scale = 1e-9)) 

    Nhận xét:

    Tối ưu hóa lợi nhuận: EBIT tuyệt đối (trung bình và trung vị) đạt tối ưu khi OPEX Ratio nằm trong phạm vi Trung bình thấp (Q2) và Trung bình cao (Q3). Chi phí quá cao (Q4) làm giảm lợi nhuận tuyệt đối và ổn định hóa nó ở mức thấp hơn, trong khi Chi phí quá thấp (Q1) lại đi kèm với lợi nhuận phân tán nhưng có xu hướng thấp.

    4.19: Biểu đồ Mật độ và Hộp Kết hợp (Faceted) - OPEX Ratio theo Nhóm OPEX Ratio

    ggplot(data_SSI, aes(x = `OPEX ratio`)) +
      geom_density(aes(fill = `Nhom OPEX Ratio`), alpha = 0.6) +
      geom_boxplot(aes(y = -0.001, fill = `Nhom OPEX Ratio`), height = 0.0005, alpha = 0.8) +
      facet_wrap(~ `Nhom OPEX Ratio`, scales = "free_y") +
      labs(title = "Phân Phối Tỷ Lệ OPEX (Density & Boxplot) Theo Nhóm",
           x = "OPEX Ratio (%)",
           y = "Mật Độ",
           fill = "Nhóm OPEX Ratio") +
      scale_y_continuous(limits = c(-0.0015, NA)) + 
      scale_fill_brewer(palette = "Accent") 

    Nhận xét:

    OPEX Ratio có tính tập trung cao: Trong các nhóm Q2, Q3 và Q4, OPEX Ratio có xu hướng tập trung vào một hoặc hai giá trị cụ thể thay vì phân tán đều, cho thấy cơ cấu chi phí của SSI có tính chu kỳ hoặc cố định tại một số mốc nhất định. Biến động theo Năm: Việc OPEX Ratio thay đổi qua các năm tạo ra sự phân bố không đối xứng và đa đỉnh trong các nhóm tứ phân vị, phản ánh sự biến động của chi phí hoạt động theo chu kỳ kinh doanh của công ty.

    4.20: Biểu đồ Bong bóng - EBIT vs OPEX Ratio (Kích thước theo EPS)

    year_breaks <- unique(as.integer(data_SSI$Nam))
    ggplot(data_SSI, aes(x = `OPEX ratio`, y = EBIT, size = EPS, color = Nam)) +
      geom_point(alpha = 0.8) +
      geom_smooth(method = "gam", se = FALSE, color = "gray50", linetype = "dashed") +
      scale_size(range = c(2, 10), name = "EPS (VND)") +
      scale_color_viridis_c(
        option = "cividis",
        name = "Năm",
        breaks = year_breaks,            
        labels = year_breaks,             
        guide = guide_colorbar(nbin = length(year_breaks), draw.ulim = FALSE, draw.llim = FALSE)) +
      labs(title = "Quan Hệ giữa EBIT và Tỷ Lệ OPEX (Kích thước theo EPS)", x = "OPEX Ratio (%)", y = "EBIT (Tỷ VND)") 

    Nhận xét:

    Hiệu suất tối ưu của SSI (kết hợp EBIT cao và EPS cao) đạt được khi công ty duy trì OPEX Ratio ở mức Trung bình Cao (khoảng \(40\% - 42\%\)), cho phép chi phí đủ lớn để thúc đẩy doanh thu, nhưng không quá cao để ăn mòn lợi nhuận. Khi OPEX Ratio vượt quá \(42\%\), rủi ro về lợi nhuận (EBIT và EPS) tăng lên đáng kể.