iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
自我挑戰組

資料視覺化的探索之旅:從 ggplot2 技術到視覺化設計系列 第 28

Extension 系列:知道如何在圖形上貼標籤嗎?

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250928/20177964eLb92fJVtx.png
在ggplot2 中, aes 的option 本身有label 這個option 可以選擇. 但是, 可能會因為標籤之間的距離太接近的關係, 而有重疊不美觀的狀況, 今天將介紹ggrepel()這個套件, 並改善標籤在圖上重疊的問題. 今天範例的目標是: 在一張散點圖上,同時看見三位熱門藝術家的「前 10 首熱門歌」在 受歡迎程度 (popularity) 與 可舞性 (danceability) 的分布,並且讓標籤清楚可讀。


為什麼要這樣切資料?

  • 先抓整體 popularity 的 第 1 四分位數 (Q1)第 3 四分位數 (Q3) 的「中段」歌曲。

    這樣做可以避開極端熱門或極不熱門曲目,讓不同類型或藝術家的差異不會被兩端的極端值蓋過。

  • 在中段範圍中,挑出出現數量最多的前三位藝術家,作為代表樣本。

  • 對每位代表藝術家,再依 popularity 各取前 10 首歌,作為我們要標示在圖上的焦點曲目。

這個流程的核心,是先「控制資料的複雜度與極端值」,再把注意力放在「同一比較尺標下的代表人物」。在展示或討論時,這種分層過濾能讓讀者更快抓到重點。


資料處理流程

q <- quantile(spotify$popularity, probs = c(0.25, 0.75), na.rm = TRUE)

top_artist_name <- spotify %>%
  filter(popularity >= q[1], popularity <= q[2]) %>%
  count(artist_name, sort = TRUE) %>%
  slice_head(n = 3) %>%
  pull(artist_name)

spotify_4 <- spotify %>%
  filter(artist_name %in% top_artist_name)

top10_tracks <- spotify_4 %>%
  drop_na(popularity) %>%
  group_by(artist_name) %>%
  slice_max(order_by = popularity, n = 10, with_ties = FALSE) %>%
  arrange(artist_name, desc(popularity), .by_group = TRUE) %>%
  ungroup()

小提醒

  • with_ties = FALSE 可保證每位藝術家最多10 首;若希望同分也全納入,可改 TRUE(但每組會超過 10)。

  • 若資料中同一首歌有多版本,想去重可在 group_by() 後加上:

    top10_tracks <- top10_tracks %>% distinct(artist_name, track_name, .keep_all = TRUE)


第一張:直接貼上曲名標籤 - ggplot ()內建功能, 標籤容易重疊

ggplot(data = top10_tracks,
       aes(x = popularity,
           y = danceability,
           label = track_name)) +
  geom_point() +
  geom_text()

  • 優點:做法最直覺,易學習。
  • 缺點:標籤會重疊,尤其當熱門歌擠在相近區域時,幾乎不可讀。

https://ithelp.ithome.com.tw/upload/images/20250928/201779641CDlaGrthU.png

第二張:用 geom_text_repel() 自動閃避

ggplot(data = top10_tracks,
       aes(x = popularity,
           y = danceability,
           label = artist_name)) +
  geom_point() +
  geom_text_repel(box.padding = 0.5)

  • geom_text_repel() 會在不改變資料點位置的前提下,自動幫文字找不重疊的位置。
  • 這裡先用 藝術家名字當標籤,快速看出聚落,但若三位藝術家各 10 首歌,標籤會重複顯示 10 次,資訊密度不足

https://ithelp.ithome.com.tw/upload/images/20250928/20177964kVyAYeozq2.png

第三張:geom_label_repel() 加底框,閱讀更穩

ggplot(data = top10_tracks,
       aes(x = popularity,
           y = danceability,
           label = artist_name)) +
  geom_point() +
  geom_label_repel()

  • 與上張差異在「標籤有底框」,對於底圖顏色複雜或需要強調時更清楚。

https://ithelp.ithome.com.tw/upload/images/20250928/201779646t0pM8yOf3.png

首張:聚焦 + 可讀性調校的完成版

  1. 標籤的顏色用 artist_name 區分;
  2. 標籤改回 track_name(歌曲);
  3. 適度限制標籤尺寸與 padding,避免佔滿畫面。
ggplot(data = top10_tracks,
       aes(x = popularity,
           y = danceability,
           fill = artist_name,
           label = track_name)) +
  geom_point() +
  geom_label_repel(max.overlaps = Inf,
                   size = 4,
                   box.padding = 0.1) +
  labs(x = "Popularity",
       y = "Danceability",
       fill = "Artist",
       title = "Top 10 Popular Tracks per Artist (Middle-Popularity Segment)")

小技巧:

  • 如果仍覺得太擠,可以只標 每位藝術家前 3 首,其餘只保留點:

    top3_labeled <- top10_tracks %>% group_by(artist_name) %>% slice_head(n = 3)

    然後 geom_point(data = top10_tracks) + geom_label_repel(data = top3_labeled, ...)

  • 或使用 ggrepel::min.segment.length = 0 讓連線更短、更靈活。


如何讀這張圖

  • 同一藝術家的 10 首熱門歌,是否都適合跳舞?

    例如 Hans Zimmer 的配樂多半 danceability 偏低,但也可能有個別曲目(如較節奏感強的動作場景配樂)拉高。

  • Popularity觀察,前 10 首是否都集中在 80+?若是,代表該藝術家熱門曲目尾端也很強

  • 斜率意象:若某藝術家點雲呈現「越熱門越可舞」的趨勢,可能指向市場偏好與音樂設計的互動關係。


什麼時候用 geom_text_repel()、什麼時候用 geom_label_repel()

  • 背景簡單、想要標籤輕量geom_text_repel()
  • 背景雜或需要強化對比geom_label_repel() 有底色框較醒目
  • 場景很擠時,與其硬塞標籤,不如改成挑重點標註 + 完整點集的做法(上面的 top3_labeled 技巧)

小結

  1. 以 Q1–Q3 的中段熱門度作為母群,能有效避免極端值左右觀察;
  2. 在該母群中挑出代表性最強的三位藝術家,再各取前 10 首熱門歌,讓比較聚焦;
  3. ggrepel 能大幅提升標籤可讀性,但請留意資訊節制(別把整張圖變成「文字海」);
  4. 場景複雜時,透過「只標重點 + 顏色分組 + 適度調參」的組合,會比全面標註更有效。

🔎 English Abstract

This article demonstrates how to use the ggrepel package to solve overlapping label issues in scatter plots. Using Spotify data, the analysis focuses on tracks within the middle quartile of popularity, selecting the top three artists with the most songs and extracting their ten most popular tracks. Different labeling methods are compared: the default geom_text() often results in clutter, while geom_text_repel() automatically adjusts positions to prevent overlap, and geom_label_repel() adds background boxes for better readability. The refined version highlights track names with artist-based coloring and adjusted parameters. Overall, ggrepel enhances clarity and allows effective visualization without overwhelming the audience.


上一篇
Day27 Extension 系列: 透過ggstatsplot 套件挖掘數據下的真相?
下一篇
Extension 系列: 圖形合併與摘要
系列文
資料視覺化的探索之旅:從 ggplot2 技術到視覺化設計30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言