繼續用 ggplot2 完成簡單任務:
事實上,類似的功能,已經有用其他語言來完成的了,例如:
https://docs.bokeh.org/en/latest/docs/gallery/periodic.html
以及:
https://plotnine.readthedocs.io/en/stable/generated/plotnine.geoms.geom_tile.html
前者為:Bokeh 的做法,後者為 Plotnine 的做法,而後者其實是 ggplot2 的圖形語法,但細節上還是不同於 R 語言上的 ggplot2.
在這裡,簡單地做了一下,用 ggplot2 完成了元素周期表的簡單繪製:
theme_set(theme_classic(base_family = 'sourcehan-normal'))新設置主題以及字體,字體選用思源黑體。
接著,構建數據:
ele <- c("H ", "He",
"Li","Be","B ", "C ", "N ","O ","F ","Ne",
"Na","Mg","Al", "Si", "P ", "S ","Cl", "Ar",
"K ","Ca","Sc", "Ti", "V ", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", 'Kr',
"Rb","Sr","Y ", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I ", "Xe",
"Cs","Ba", "Hf", "Ta", "W ", "Re", "Os", "Ir", "Pt", "Au", "Hg", "TI", "Pb", "Bi", "Po", "At", "Rn",
"Fr","Ra", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn", "Nh", "FI", "Mc", "Lv", "Ts", "Og"
)
num <- c(1:56,72:88,104:118)
f1 <- num
x <- c(1,18,
1:2, 13:18,
1:2,13:18,
rep(1:18,2),
rep(c(1:2,4:18),2)
)
y <- c(1,1,
rep(2,8),rep(3,8),
rep(4:5,each = 18),
rep(6:7, each = 17)
)
f <- c(1,2,3,4,5,rep(1,3),6,2,
3,4,7,5,1,1,6,2,
3,4,rep(8,10),7,5,5,1,6,2,
3,4,rep(8,10),7,7,5,5,6,2,
3,4,rep(8,9),7,7,7,5,6,2,
3,4,rep(8,9),7,7,7,7,6,2
) %>% factor(.,labels = c(
'nonmetal','noble gas', 'alkali metal',
'alkali earth metal', 'metalloid', 'halogen',
'metal', 'transition metal'
) )
d2 <- data.frame(
ele, num,x, y ,f
)x ,y 對應每一個元素的坐標位置, f 提供分類變量。
之後要生成羅馬數字:
roman_num <- c('\u2160','\u2161','\u2162','\u2163',
'\u2164','\u2165','\u2166')
d3 <- data.frame( x = c(rep(0.7,7),1:18+0.5),
y = c(1:7+0.5,rep(8.1,18)),
label = c(roman_num,1:18)
)
然後開始作圖:
ggplot(d2) +
geom_rect(aes(xmin = x,ymin = y,
xmax = x + 0.96,ymax = y + 0.96,
fill = f),
size = 0.1
) +
geom_text(aes(x +0.2,y+ 0.5,label = ele),
fontface = 'bold',
hjust = 0) +
geom_text(aes(x = x+0.05, y = y + 0.2,label = num),
vjust = 0.5 ,hjust = 0,
size = 3) +
geom_text(aes(x = x,y = y,label = label ),
d3, family = 'sourcehan-light',
hjust = 0.5,vjust = 0.5) +
scale_y_reverse() +
theme_void() +
scale_fill_discrete(NULL,
labels = function(x) str_pad(x,25,'right')
) + ggtitle(' Periodic table')需要說明的是: function(x) str_pad(x,25,'right') 在右側添加空白,避免圖例直接與右側邊界對齊。
圖像:
這樣顯示的,是 ggplo2t 的默認配色,感覺上非常不美觀。。。
因此,需要修改顏色:
ggplot(d2) +
geom_rect(aes(xmin = x,ymin = y,
xmax = x + 0.96,ymax = y + 0.96,
fill = f,colour = f), alpha = 0.45,
size = 0.1
) +
geom_text(aes(x +0.2,y+ 0.5,label = ele),
fontface = 'bold',
hjust = 0) +
geom_text(aes(x = x+0.05, y = y + 0.2,label = num),
vjust = 0.5 ,hjust = 0,
size = 3) +
geom_text(aes(x = x,y = y,label = label ),
d3, family = 'sourcehan-light',
hjust = 0.5,vjust = 0.5) +
annotate('text', y = 6:7+0.6,x = c(3,3)+0.5,
label = c('LA','AC'),
hjust = 0.5,vjust = 0.5) +
scale_y_reverse() +
theme_void() -> p1在 p1 中增加了 LA, AC 的位置,但沒有添加顏色。
接著修改配色部分:
p1 + scale_fill_discrete(NULL,
type = list (c('#F1D4AF',
'#EAEAEA','#A6CEE3','#1F78B4',
'#E08D49','#999D9A','#D93B43',
'#599D7A') )
) +
scale_colour_discrete(NULL,
type = list (c('#F1D4AF',
'#EAEAEA','#A6CEE3','#1F78B4',
'#E08D49','#999D9A','#D93B43',
'#599D7A') )
)新版 ggplot2 的配色修改,是通過 type 參數完成,傳入部分可以為 list 對象。
而顏色的深淺,則在 p1 中通過 alpha 參數進行調整
接著再修改圖例,以及標題部分:
p1 + scale_fill_discrete(NULL,
type = list (c('#F1D4AF',
'#EAEAEA','#A6CEE3','#1F78B4',
'#E08D49','#999D9A','#D93B43',
'#599D7A') )
) +
scale_colour_discrete(NULL,
type = list (c('#F1D4AF',
'#EAEAEA','#A6CEE3','#1F78B4',
'#E08D49','#999D9A','#D93B43',
'#599D7A') )
) +
ggtitle(' Periodic Table') +
guides(fill = guide_legend(
nrow = 1
)) +
theme(
legend.position = c(0.5,0.9),
plot.title = element_text(
hjust = 0.05, vjust = -0.3
)
)至此,已完成基本的繪圖。如果需要添加元素的全寫名稱,以及相對分子質量,可類似地操作,繼續添加 geom_text() 圖層即可。
此外,也可以繼續添加 LA, AC 系的元素。
這樣的繪圖相對比較簡單,難度不大。
---end---