今天的推文是個 ggplot2 案例,不過也是一個動態圖表,在開始敲今天的代碼之前我們先了解一下什麼是「赫羅圖」?
赫羅圖(Hertzsprung-Russell diagram,簡寫為 H-R diagram 或 HRD)是丹麥天文學家赫茨普龍及由美國天文學家羅素分別於 1911 年和 1913 年各自獨立提出的。後來的研究發現,這張圖是研究恆星演化的重要工具,因此把這樣一張圖以當時兩位天文學家的名字來命名,稱為赫羅圖。赫羅圖是恆星的光譜類型與光度之關係圖,赫羅圖的縱軸是光度與絕對星等,而橫軸則是光譜類型及恆星的表面溫度,從左向右遞減。恆星的光譜型通常可大致分為 O.B.A.F.G.K.M 七種,要記住這七個類型有一個簡單的英文口訣 "Oh be A Fine Girl/Guy. Kiss Me!"
上面一段是我百度的。。。
這篇文章的核心代碼來源於 zonination/h-r-diagram 當然我不是直接 Ctrl + C / V 把代碼直接複製過了,我在作者的代碼基礎上進行了更正和改進。
附件(文末有下載連結)中有本文需要的兩個數據:
我們使用 readr 包把這兩個數據集讀入 R 中並使用 rbind 函數進行行連接:
library(tidyverse)
library(ggplot2)
# 讀入數據
# 發現這個數據使用 read_csv 讀取的時候有點問題,ci 和 x 變量錯位了,absmag 和 spect 也錯位了,所以這裡我們選擇 spect 和 x,然後把 x 重命名為 ci,spect 重命名為 absmag
catalog <- rbind(
read_csv("hygdata_v3-1.csv"),
read_csv("hygdata_v3-2.csv")
) %>%
select(spect, x) %>%
rename(ci = x,
absmag = spect)通過繪製一系列帶有不同透明度的靜態圖合成動圖就可以產生星星閃耀的效果。為此,我們先生成一列隨機數:
catalog$randomseed <- runif(nrow(catalog), min = 0, max = 2 * pi)這個隨機數服從
我們先繪製一幅靜態圖:
ggplot(catalog, aes(ci, absmag)) +
geom_point(
shape = 16,
size = 0.001,
aes(
alpha = (sin(randomseed + pi / 180)),
colour = ci
)
) +
scale_x_continuous(limits = c(-0.5, 2.5)) +
scale_y_reverse() +
guides(colour = F, alpha = F) +
scale_alpha_continuous(range = c(0, 1)) +
scale_color_gradientn(
colours = c("blue", "skyblue", "white", "orange", "red"),
limits = c(-0.5, 2.5)
) +
labs(
title = "圖:赫羅圖",
subtitle = "恆星的類別",
y = "絕對星等",
x = "光譜類型(B-V)"
) +
annotate("text",
x = 0, y = 15,
label = "白矮星", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
annotate("text",
x = 1.75, y = 12,
label = "主序帶", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
annotate("text",
x = 1.75, y = 0,
label = "巨星", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
annotate("text",
x = 1.75, y = -10,
label = "超巨星", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
theme_modern_rc(base_family = cnfont, grid = "") +
theme(panel.background = element_rect(fill = '#000000',
color = 'white',
size = 0.2),
plot.background = element_rect(fill = '#000000',
color = '#000000'))突然發現我們甚至可以把這幅圖製作成一幅藝術品,為此我們可以把文本、軸線等刪除了:
ggplot(catalog, aes(ci, absmag)) +
geom_point(
shape = 16,
size = 0.001,
aes(
alpha = (sin(randomseed + pi / 180)),
colour = ci
)
) +
scale_x_continuous(limits = c(-0.5, 2.5)) +
scale_y_reverse() +
guides(colour = F, alpha = F) +
scale_alpha_continuous(range = c(0, 1)) +
scale_color_gradientn(
colours = c("blue", "skyblue", "white", "orange", "red"),
limits = c(-0.5, 2.5)
) +
labs(
caption = "赫羅圖",
x = "", y = ""
) +
theme_modern_rc(caption_family = cnfont, grid = "") +
theme(panel.background = element_rect(fill = '#000000',
color = '#000000',
size = 0.2),
plot.background = element_rect(fill = '#000000',
color = '#000000'),
axis.text = element_blank(),
plot.caption = element_text(hjust = 0, size = 14))
ggsave("赫羅圖.png", height = 9, width = 6)最後使用 for 循環是生成 37 張透明度不同的圖片然後再合併為 GIF 圖:
for (n in seq(0, 360, 10)) {
ggplot(catalog, aes(ci, absmag)) +
geom_point(
shape = 16,
size = 0.001,
aes(
alpha = (sin(randomseed + n * pi / 180)),
colour = ci
)
) +
scale_x_continuous(limits = c(-0.5, 2.5)) +
scale_y_reverse() +
guides(colour = F, alpha = F) +
scale_alpha_continuous(range = c(0, 1)) +
scale_color_gradientn(
colours = c("blue", "skyblue", "white", "orange", "red"),
limits = c(-0.5, 2.5)
) +
labs(
title = "赫羅圖",
subtitle = "恆星的類別",
y = "絕對星等",
x = "光譜類型(B-V)"
) +
annotate("text",
x = 0, y = 15,
label = "白矮星", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
annotate("text",
x = 1.75, y = 12,
label = "主序帶", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
annotate("text",
x = 1.75, y = 0,
label = "巨星", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
annotate("text",
x = 1.75, y = -10,
label = "超巨星", size = 4,
hjust = 0, vjust = 0, color = "white", family = cnfont
) +
theme_modern_rc(base_family = cnfont, grid = "") +
theme(panel.background = element_rect(fill = '#000000',
color = 'white',
size = 0.5),
plot.background = element_rect(fill = '#000000',
color = '#000000'))
ggsave(paste("star_anim", formatC(n, width = 3, flag = "0"), ".png", sep = ""), height = 9, width = 6)
print(paste(n, "of", 360, "degrees completed."))
}
rm(n)
# 使用 convert 命令把靜態圖合成動圖
system("convert -delay 10 star_anim*.png twinkle.gif")
# 刪除剛剛繪製並保存的靜態圖
system("rm star_anim*.png")結果(很大,請耐心等待,這裡我給它轉為 MP4 文件插入,附件中有轉換的代碼):
把多個圖片合成 GIF 圖 可以使用終端命令 convert,如果你的電腦沒有這個工具,可以使用 magick 工具,下載和使用方法可以閱讀這裡:https://www.imagemagick.org/script/command-line-processing.php
附件連結:連結: https://pan.baidu.com/s/14DobGlItoDRN8zHWibQu9g 密碼: ql3u