Trong bối cảnh ngành công nghiệp âm nhạc số phát triển mạnh mẽ, dữ liệu từ các nền tảng streaming như Spotify là một nguồn tài nguyên quý giá để phân tích xu hướng và hành vi người nghe. Bộ dữ liệu “Spotify Dataset 1921-2020” cung cấp thông tin chi tiết về hơn 170,000 bài hát, bao gồm các thuộc tính âm nhạc và năm phát hành. Trong chương này, nhóm sẽ tiến hành các bước đầu tiên để nhập và khám phá sơ bộ bộ dữ liệu, tạo nền tảng cho các phân tích sâu hơn ở các chương sau. Ở giai đoạn này, chúng ta sẽ tải bộ dữ liệu Spotify vào môi trường R và thực hiện các bước kiểm tra cơ bản để hiểu rõ về cấu trúc và nội dung của nó.
# Tải thư viện và đọc dữ liệu
library(tidyverse)
spotify_data <- read_csv("data.csv")
dim(spotify_data)
## [1] 170653 19
Bộ dữ liệu này có tổng cộng 170,653 dòng và 19 cột, bao gồm các thông tin về các bài hát trên nền tảng Spotify từ năm 1921 đến 2020
glimpse(spotify_data)
## Rows: 170,653
## Columns: 19
## $ valence <dbl> 0.0594, 0.9630, 0.0394, 0.1650, 0.2530, 0.1960, 0.406…
## $ year <dbl> 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921,…
## $ acousticness <dbl> 0.9820, 0.7320, 0.9610, 0.9670, 0.9570, 0.5790, 0.996…
## $ artists <chr> "['Sergei Rachmaninoff', 'James Levine', 'Berliner Ph…
## $ danceability <dbl> 0.279, 0.819, 0.328, 0.275, 0.418, 0.697, 0.518, 0.38…
## $ duration_ms <dbl> 831667, 180533, 500062, 210000, 166693, 395076, 15950…
## $ energy <dbl> 0.2110, 0.3410, 0.1660, 0.3090, 0.1930, 0.3460, 0.203…
## $ explicit <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,…
## $ id <chr> "4BJqT0PrAfrxzMOxytFOIz", "7xPhfUan2yNtyFG0cUWkt8", "…
## $ instrumentalness <dbl> 8.78e-01, 0.00e+00, 9.13e-01, 2.77e-05, 1.68e-06, 1.6…
## $ key <dbl> 10, 7, 3, 5, 3, 2, 0, 1, 5, 8, 9, 10, 5, 8, 7, 7, 2, …
## $ liveness <dbl> 0.6650, 0.1600, 0.1010, 0.3810, 0.2290, 0.1300, 0.115…
## $ loudness <dbl> -20.096, -12.441, -14.850, -9.316, -10.096, -12.506, …
## $ mode <dbl> 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,…
## $ name <chr> "Piano Concerto No. 3 in D Minor, Op. 30: III. Finale…
## $ popularity <dbl> 4, 5, 5, 3, 2, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0,…
## $ release_date <chr> "1921", "1921", "1921", "1921", "1921", "1921", "1921…
## $ speechiness <dbl> 0.0366, 0.4150, 0.0339, 0.0354, 0.0380, 0.0700, 0.061…
## $ tempo <dbl> 80.954, 60.936, 110.339, 100.109, 101.665, 119.824, 6…
library(tibble)
spotify_metadata <- tribble(
~Variable, ~Data_Type, ~Description,
"valence", "double", "Mức độ tích cực trong âm nhạc (0 = buồn, 1 = vui)",
"year", "double", "Năm phát hành của bài hát",
"acousticness", "double", "Khả năng bài hát là acoustic (âm thanh mộc)",
"artists", "character","Danh sách nghệ sĩ thể hiện bài hát",
"danceability", "double", "Mức độ dễ nhảy theo bài hát (0 đến 1)",
"duration_ms", "double", "Thời lượng bài hát (miligiây)",
"energy", "double", "Mức năng lượng của bài hát",
"explicit", "double", "Bài hát có nội dung nhạy cảm không (0 = không, 1 = có)",
"id", "character","Mã định danh bài hát trên Spotify",
"instrumentalness", "double", "Xác suất bài hát là nhạc không lời",
"key", "double", "Tông nhạc chính của bài hát (0 = C, 1 = C#, ..., 11 = B)",
"liveness", "double", "Khả năng bài hát được thu âm trực tiếp",
"loudness", "double", "Mức âm lượng trung bình (đơn vị decibel)",
"mode", "double", "Thang âm chính (1) hoặc phụ (0)",
"name", "character","Tên bài hát",
"popularity", "double", "Mức độ phổ biến (0-100)",
"release_date", "character","Ngày phát hành bài hát",
"speechiness", "double", "Mức độ chứa lời thoại trong bài hát",
"tempo", "double", "Tốc độ của bài hát (nhịp/phút - BPM)"
)
print(spotify_metadata, n = Inf)
## # A tibble: 19 × 3
## Variable Data_Type Description
## <chr> <chr> <chr>
## 1 valence double Mức độ tích cực trong âm nhạc (0 = buồn, 1 = vui)
## 2 year double Năm phát hành của bài hát
## 3 acousticness double Khả năng bài hát là acoustic (âm thanh mộc)
## 4 artists character Danh sách nghệ sĩ thể hiện bài hát
## 5 danceability double Mức độ dễ nhảy theo bài hát (0 đến 1)
## 6 duration_ms double Thời lượng bài hát (miligiây)
## 7 energy double Mức năng lượng của bài hát
## 8 explicit double Bài hát có nội dung nhạy cảm không (0 = không, 1 …
## 9 id character Mã định danh bài hát trên Spotify
## 10 instrumentalness double Xác suất bài hát là nhạc không lời
## 11 key double Tông nhạc chính của bài hát (0 = C, 1 = C#, ..., …
## 12 liveness double Khả năng bài hát được thu âm trực tiếp
## 13 loudness double Mức âm lượng trung bình (đơn vị decibel)
## 14 mode double Thang âm chính (1) hoặc phụ (0)
## 15 name character Tên bài hát
## 16 popularity double Mức độ phổ biến (0-100)
## 17 release_date character Ngày phát hành bài hát
## 18 speechiness double Mức độ chứa lời thoại trong bài hát
## 19 tempo double Tốc độ của bài hát (nhịp/phút - BPM)
head(spotify_data)
## # A tibble: 6 × 19
## valence year acousticness artists danceability duration_ms energy explicit
## <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 0.0594 1921 0.982 ['Sergei … 0.279 831667 0.211 0
## 2 0.963 1921 0.732 ['Dennis … 0.819 180533 0.341 0
## 3 0.0394 1921 0.961 ['KHP Kri… 0.328 500062 0.166 0
## 4 0.165 1921 0.967 ['Frank P… 0.275 210000 0.309 0
## 5 0.253 1921 0.957 ['Phil Re… 0.418 166693 0.193 0
## 6 0.196 1921 0.579 ['KHP Kri… 0.697 395076 0.346 0
## # ℹ 11 more variables: id <chr>, instrumentalness <dbl>, key <dbl>,
## # liveness <dbl>, loudness <dbl>, mode <dbl>, name <chr>, popularity <dbl>,
## # release_date <chr>, speechiness <dbl>, tempo <dbl>
colnames(spotify_data)
## [1] "valence" "year" "acousticness" "artists"
## [5] "danceability" "duration_ms" "energy" "explicit"
## [9] "id" "instrumentalness" "key" "liveness"
## [13] "loudness" "mode" "name" "popularity"
## [17] "release_date" "speechiness" "tempo"
sum(is.na(spotify_data))
## [1] 0
Không có giá trị thiếu trong bộ dữ liệu
duplicated_rows <- sum(duplicated(spotify_data))
print(paste("Số lượng quan sát trùng lặp là:", duplicated_rows))
## [1] "Số lượng quan sát trùng lặp là: 0"
library(dplyr)
# Tạo biến phân nhóm mức độ phổ biến
spotify_data <- spotify_data %>%
mutate(popularity_level = case_when(
popularity <= 20 ~ "Thấp",
popularity <= 50 ~ "Trung bình",
popularity <= 80 ~ "Cao",
TRUE ~ "Rất cao"
))
# Phân tổ theo năm và mức độ phổ biến, đếm số bài hát
popularity_time_summary <- spotify_data %>%
group_by(year, popularity_level) %>%
summarise(So_bai_hat = n(), .groups = "drop") %>%
arrange(year, popularity_level)
print(popularity_time_summary)
## # A tibble: 304 × 3
## year popularity_level So_bai_hat
## <dbl> <chr> <int>
## 1 1921 Thấp 150
## 2 1922 Thấp 71
## 3 1923 Thấp 172
## 4 1923 Trung bình 13
## 5 1924 Thấp 236
## 6 1925 Thấp 269
## 7 1925 Trung bình 9
## 8 1926 Thấp 1367
## 9 1926 Trung bình 11
## 10 1927 Thấp 610
## # ℹ 294 more rows
Kết quả cho thấy trong các năm đầu thế kỷ 20, phần lớn bài hát thuộc nhóm thấp về mức độ phổ biến, với số lượng bài hát lớn hơn hẳn nhóm Trung bình. Số bài hát phổ biến ở các nhóm cao hơn gần như rất ít hoặc chưa xuất hiện, phản ánh xu hướng âm nhạc và khả năng lan tỏa hạn chế của những năm đó.
Điều này cũng phù hợp với thực tế phát triển công nghệ và ngành âm nhạc, khi mà sự phổ biến của bài hát chưa được mở rộng rộng rãi như ngày nay.
# Tạo biến phân nhóm năng lượng
spotify_data <- spotify_data %>%
mutate(energy_level = case_when(
energy <= 0.33 ~ "Thấp",
energy <= 0.66 ~ "Trung bình",
TRUE ~ "Cao"
))
# Phân tổ theo popularity_level và energy_level, đếm số bài hát
pop_energy_summary <- spotify_data %>%
group_by(popularity_level, energy_level) %>%
summarise(So_bai_hat = n(), .groups = "drop") %>%
arrange(popularity_level, energy_level)
print(pop_energy_summary)
## # A tibble: 12 × 3
## popularity_level energy_level So_bai_hat
## <chr> <chr> <int>
## 1 Cao Cao 17033
## 2 Cao Thấp 4384
## 3 Cao Trung bình 14320
## 4 Rất cao Cao 229
## 5 Rất cao Thấp 32
## 6 Rất cao Trung bình 288
## 7 Thấp Cao 3374
## 8 Thấp Thấp 35635
## 9 Thấp Trung bình 15395
## 10 Trung bình Cao 29801
## 11 Trung bình Thấp 18492
## 12 Trung bình Trung bình 31670
Kết quả cho thấy:
Các bài hát có mức độ phổ biến Cao và Trung bình tập trung nhiều ở nhóm năng lượng Cao và Trung bình, cho thấy bài hát phổ biến thường có năng lượng mạnh hoặc vừa phải.
Nhóm Thấp về độ phổ biến lại có số lượng lớn bài hát thuộc nhóm năng lượng Thấp, nghĩa là bài hát ít phổ biến thường có năng lượng thấp hơn.
Nhóm Rất cao về phổ biến có số lượng bài hát ít hơn, nhưng cũng chủ yếu tập trung ở nhóm năng lượng Cao và Trung bình.
=> Năng lượng bài hát có mối liên hệ rõ nét với mức độ phổ biến: bài hát năng lượng cao thường có xu hướng được yêu thích và phổ biến hơn.
# Phân tổ theo popularity_level và explicit, đếm số bài hát
pop_explicit_summary <- spotify_data %>%
group_by(popularity_level, explicit) %>%
summarise(So_bai_hat = n(), .groups = "drop") %>%
arrange(popularity_level, explicit)
print(pop_explicit_summary)
## # A tibble: 8 × 3
## popularity_level explicit So_bai_hat
## <chr> <dbl> <int>
## 1 Cao 0 28625
## 2 Cao 1 7112
## 3 Rất cao 0 353
## 4 Rất cao 1 196
## 5 Thấp 0 51829
## 6 Thấp 1 2575
## 7 Trung bình 0 75413
## 8 Trung bình 1 4550
Kết quả cho thấy phần lớn bài hát ở mọi mức độ phổ biến đều không có explicit (explicit = 0). Tuy nhiên, tỉ lệ bài hát có explicit (explicit = 1) tăng dần theo mức độ phổ biến: nhóm Cao và Rất cao có số bài hát explicit nhiều hơn so với nhóm Thấp và Trung bình. Điều này gợi ý rằng bài hát có lời tục tĩu có thể có xu hướng phổ biến hơn trong một số trường hợp.
# Tính tần suất mức độ phổ biến
Bảng_tần_suất <- spotify_data %>%
group_by(popularity_level) %>%
summarise(So_bai_hat = n(), .groups = "drop") %>%
mutate(Tỷ_lệ = round(So_bai_hat / sum(So_bai_hat) * 100, 2))
print(Bảng_tần_suất)
## # A tibble: 4 × 3
## popularity_level So_bai_hat Tỷ_lệ
## <chr> <int> <dbl>
## 1 Cao 35737 20.9
## 2 Rất cao 549 0.32
## 3 Thấp 54404 31.9
## 4 Trung bình 79963 46.9
Phần lớn bài hát có mức độ phổ biến từ trung bình đến thấp, chiếm gần 78% tổng số. Các bài hát phổ biến cao chiếm khoảng 21%, trong khi bài hát rất nổi tiếng chỉ chiếm dưới 1%, cho thấy nhóm này rất hiếm.
library(ggplot2)
ggplot(Bảng_tần_suất, aes(x = popularity_level, y = So_bai_hat, fill = popularity_level)) +
geom_col(show.legend = FALSE) +
geom_text(aes(label = paste0(round(Tỷ_lệ, 1), "%")), vjust = -0.5) +
labs(title = "Tần suất mức độ phổ biến bài hát",
x = "Mức độ phổ biến",
y = "Số lượng bài hát") +
theme_minimal()
# Đếm số bài hát theo năm
year_summary <- spotify_data %>%
group_by(year) %>%
summarise(So_bai_hat = n(), .groups = "drop") %>%
arrange(year)
print(year_summary)
## # A tibble: 100 × 2
## year So_bai_hat
## <dbl> <int>
## 1 1921 150
## 2 1922 71
## 3 1923 185
## 4 1924 236
## 5 1925 278
## 6 1926 1378
## 7 1927 615
## 8 1928 1261
## 9 1929 952
## 10 1930 1924
## # ℹ 90 more rows
Số lượng bài hát phát hành tăng dần qua các năm đầu thế kỷ 20, từ vài chục bài năm 1922 lên đến hàng nghìn bài vào cuối thập niên 1920 và đầu 1930. Điều này cho thấy sự phát triển mạnh mẽ của ngành công nghiệp âm nhạc trong giai đoạn này, với ngày càng nhiều bài hát được sản xuất và ghi lại.
# Vẽ biểu đồ số bài hát theo năm
ggplot(year_summary, aes(x = year, y = So_bai_hat)) +
geom_line(color = "blue") +
labs(title = "Số lượng bài hát theo năm phát hành",
x = "Năm phát hành",
y = "Số bài hát") +
theme_minimal()