更好閱讀移步至:https://www.yuque.com/docs/share/01fe5958-5f6b-4364-aa39-cb7d3fd602ed?#
參考鏈接:
- twitter:https://twitter.com/geokaramanis/status/1247586395876741120
- 代碼 github 鏈接:https://github.com/gkaramanis/tidytuesday/tree/master/2020-week15

<br />
<a name="zcTxe"></a>
須知:
rle 函數(shù):計(jì)算向量中連續(xù)相同字符的個(gè)數(shù)
> rle(c(1,1,1,2,3,3,3,1,1))
Run Length Encoding
lengths: int [1:4] 3 1 3 2
values : num [1:4] 1 2 3 1
> rle(c(1, 2, 3, 3, 1, 1, 2, 3, 2))
Run Length Encoding
lengths: int [1:7] 1 1 2 2 1 1 1
values : num [1:7] 1 2 3 1 2 3 2
<br />**glue 函數(shù):用大括號(hào) {} **括起來的表達(dá)式將被計(jì)算為 R 代碼。長(zhǎng)字符串由行分隔并連接在一起。從第一行和最后一行開始的空白行和空白行被自動(dòng)裁剪烧栋。
> name <- "Fred"
> age <- 50
> anniversary <- as.Date("1991-10-12")
> glue('My name is {name},',
'my age next year is {age + 1},',
'my anniversary is {format(anniversary, "%A, %B %d, %Y")}.')
My name is Fred,my age next year is 51,my anniversary is 星期六, 十月 12, 1991.
> glue("My name is {name}, not {{name}}.")
My name is Fred, not {name}.
> year <- 1940
> glue("**year**")
**year**
> glue("**{year}**")
**1940**
<br />**countrycode **函數(shù):對(duì)我不重要
> cowcodes <- c("ALG", "ALB", "UKG", "CAN", "USA")
> countrycode(cowcodes, origin = "cowc", destination = "iso3c")
[1] "DZA" "ALB" "GBR" "CAN" "USA"
<br />**ggtext **包 的 **geom_richtext **函數(shù):加文本標(biāo)簽注釋
<br />
<br />annotate:添加注釋和以及幾何圖形特別方便吞瞪,為所欲為
- https://ggplot2.tidyverse.org/reference/annotate.html
- annotate 添加空白
annotate("rect",
xmin = -2000, ymin = c(13, 38),
xmax = 26000, ymax = c(16, 41),
fill = "#F3F2EE", colour = "black", size = 0.3)
<br />coord_cartesian:放大鏡效果不改變圖形形狀
- https://ggplot2.tidyverse.org/reference/coord_cartesian.html
- 繪圖應(yīng)該裁剪到畫板的范圍嗎 ? 設(shè)置為"on" (默認(rèn)值)表示“是”骡楼,設(shè)置為"off" 表示“不是”淡喜。在大多數(shù)情況下陨帆,不應(yīng)該更改默認(rèn)的 "on"骚亿,因?yàn)樵O(shè)置 clip ="off" 可能會(huì)導(dǎo)致意外的結(jié)果已亥。它允許在繪圖圖的任何地方繪制數(shù)據(jù)點(diǎn),包括在繪圖頁(yè)邊距中来屠。如果通過 xlim 和 ylim 設(shè)置了限制虑椎,并且一些數(shù)據(jù)點(diǎn)超出了這些限制,那么這些數(shù)據(jù)點(diǎn)可能出現(xiàn)在軸俱笛、圖例捆姜、畫板標(biāo)題或畫板邊距等位置。
p <- ggplot(mtcars, aes(disp, wt)) +
geom_point() +
geom_smooth()
p + scale_x_continuous(limits = c(325, 500))
p + coord_cartesian(xlim = c(325, 500))
<br />
coord_cartesian(clip = 'off'):取消畫板限制
<br />**scale_x_continuous **函數(shù)通過 **limits **和 **expand **函數(shù)控制貼 y 軸距離
scale_y_reverse 函數(shù)翻轉(zhuǎn) y 軸左邊起始順序迎膜,上下顛倒泥技,并通過 expand = expansion(add = 0) 控制 y 軸頂端和低端間隙為 0<br /><br />theme_void:去除畫板,包括軸以及背景**<br />
- ggplot2 Complete themes:https://ggplot2.tidyverse.org/reference/ggtheme.html
- image.png
plot.margin:控制上下左右圖片邊距<br />**<br />
<br />
<a name="alM8p"></a>
前期數(shù)據(jù)獲得:
library(tidyverse)
library(lubridate)
library(countrycode)
library(ggtext)
library(glue)
library(here)
#library(skimr)
tdf_winners <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-04-07/tdf_winners.csv')
tdf_table <- tdf_winners %>%
mutate(
# rle: 計(jì)算相同值的數(shù)目
wins_consecutive = with(rle(winner_name), rep(lengths, times = lengths)),
year = year(start_date), # 提取年數(shù)據(jù)
# glue() 函數(shù)大括號(hào) {} 括起來表示 R 代碼 year <- 1940; glue("**{year}**"); > **1940** <
year_labels = ifelse(year %% 10 == 0, glue("**{year}**"), year),
year_group = case_when(
year < 1915 ~ 1,
year > 1915 & year < 1940 ~ 2,
TRUE ~ 3),
avg_speed = distance / time_overall,
country_code = countrycode(nationality, origin = "country.name", destination = "iso3c"),
winner_annot = ifelse(wins_consecutive > 2, glue("**{winner_name} ({country_code})**"), glue("{winner_name} ({country_code})"))
) %>%
# 分組很妙星虹,添加行號(hào)
group_by(year_group) %>%
mutate(
n_annot = row_number(),
annot = ifelse((n_annot - 2) %% 3 == 0, TRUE, FALSE)
) %>%
ungroup() %>%
add_row(year = c(1915, 1916, 1917, 1918, 1940, 1941, 1942, 1943)) %>%
arrange(year) %>%
mutate(n = row_number())
<a name="LL9Yf"></a>
分步驟重現(xiàn)圖:
<a name="hLyBf"></a>
step1: geom_segment() 標(biāo)虛線
- 使用 geom_segment() 函數(shù)添加虛線, 數(shù)據(jù)中的 NA 很妙用零抬,如果是 NA 值就不需要加虛線,就是為了圖中看到的 1915-1918 添加用宽涌。
- 真的妙平夜,利用有多少行非 NA 數(shù)值,來保證點(diǎn)添加多少
ggplot(tdf_table) +
# dotted gridlines ---------------------------------------------------
# 使用 geom_segment() 函數(shù)添加虛線, 數(shù)據(jù)中的 NA 很妙用卸亮,如果是 NA 值就不需要加虛線忽妒,就是為了圖中看到的 1915-1918 添加用。
# 真的妙,利用有多少行非 NA 數(shù)值段直,來保證點(diǎn)添加多少
geom_segment(data = subset(tdf_table, !is.na(year_labels)),
aes(x = 0, xend = 24000, y = n, yend = n),
linetype = "dotted", size = 0.2)

<br />
<a name="RQ23D"></a>
step2:加上左右兩側(cè)的年份
- 這里的 x = -1000 y = n 以及 x = 25000 用的很妙啊吃溅。特別是 -1000,加在坐標(biāo)軸左側(cè)
geom_richtext(aes(x = -1000, y = n, label = year_labels),
fill = "red", label.color = NA,
label.padding = unit(0.1, "lines"),
family = "JetBrains Mono", size = 2.5) +
geom_richtext(aes(x = 25000, y = n, label = year_labels),
fill = "blue", label.color = NA,
label.padding = unit(0.1, "lines"),
family = "JetBrains Mono", size = 2.5)

<br />
<a name="kUiQk"></a>
step3:geom_area() 加上填充面積
geom_area(aes(x = distance * 0.625, y = n, group = year_group),
fill = "#7DDDB6", alpha = 0.6,
orientation = "y", position = "identity")

<br />
<a name="50aa2"></a>
step4:選擇性加上每一個(gè)上面對(duì)應(yīng)的點(diǎn)
geom_point(data = subset(tdf_table, annot),
aes(x = distance * 0.625, y = n), size = 0.5)

<br />
<a name="K2rHJ"></a>
step5:給 step4 中的點(diǎn)加上數(shù)值
geom_label(data = subset(tdf_table, annot),
aes(x = distance * 0.625 + 100, y = n, label = distance),
fill = "#F3F2EE", label.size = 0,
label.padding = unit(0.1, "lines"),
hjust = 0, family = "JetBrains Mono", size = 2.5)
<br />
<br />
<a name="dfy6e"></a>
step6:給每一行加上注釋鸯檬,對(duì)應(yīng) WINNER
geom_richtext(aes(x = 5300, y = n, label = winner_annot, .na = NULL),
fill = "#F3F2EE", label.size = 0,
label.padding = unit(0.1, "lines"),
hjust = 0, family = "JetBrains Mono", size = 2.5)
<br />
<br />
<br />step7:
geom_label(aes(x = 10300, y = n, label = glue("{winner_team}", .na = NULL)),
fill = "#F3F2EE", label.size = 0, label.padding = unit(0.1, "lines"),
hjust = 0, family = "JetBrains Mono", size = 2.5)

<br />
<a name="Usq1r"></a>
step7:geom_segment 函數(shù)添加 AVERAGE SPEED 數(shù)據(jù)
geom_segment(aes(x = 16000, xend = 16000 + avg_speed * 66.67, y = n, yend = n),
size = 2, colour = "#7DDDB6", alpha = 0.6)

<br />
<a name="BJmwo"></a>
step8:選擇性添加 AVERAGE SPEED 對(duì)應(yīng)的數(shù)值
geom_label(data = subset(tdf_table, annot),
aes(x = 16000 + avg_speed * 66.67 + 100, y = n,
label = round(avg_speed, 1)), fill = "#F3F2EE",
label.size = 0, label.padding = unit(0.1, "lines"),
hjust = 0, family = "JetBrains Mono", size = 2.5)

<br />
<a name="t2Caa"></a>
step9:添加 TOTAL TIME 時(shí)間填充(geom_ribbon)决侈、點(diǎn)、標(biāo)簽
geom_ribbon(aes(xmin = 20000, xmax = 20000 + time_overall * 10, y = n, group = year_group),
fill = "#FCDF33", alpha = 0.6, orientation = "y", position = "identity") +
geom_point(data = subset(tdf_table, annot),
aes(x = 20000 + time_overall * 10, y = n), size = 0.5) +
geom_label(data = subset(tdf_table, annot),
aes(x = 20000 + time_overall * 10 + 100, y = n,
label = round(time_overall, 1)),
fill = "#F3F2EE", label.size = 0,
label.padding = unit(0.1, "lines"),
hjust = 0, family = "JetBrains Mono", size = 2.5)

<br />
<a name="psBfU"></a>
step10:annotate 函數(shù)添加豎直線
annotate("segment",
x = c(-2000, 0, 5000, 10000, 16000, 20000, 24000, 26000),
xend = c(-2000, 0, 5000, 10000, 16000, 20000, 24000, 26000),
y = -4, yend = 115, size = 0.3)

<br />
<a name="IEOLm"></a>
step11:annotate 函數(shù)添加三條橫線
annotate("segment",
x = -2000, xend = 26000,
y = c(-4, -1, 115), yend = c(-4, -1, 115), size = 0.3)

<br />
<a name="tIULc"></a>
step12:annotate 添加表頭
annotate("text",
x = c(-1000, 2500, 7500, 13000, 18000, 22000, 25000),
y = -2.5,
label = toupper(c("year", "distance", "winner", "team", "average speed", "total time", "year")),
hjust = 0.5, family = "IBM Plex Sans Bold", size = 3.5)

<br />
<a name="qoRiI"></a>
step13:annotate 函數(shù)加上空白
annotate("rect",
xmin = -2000, ymin = c(13, 38),
xmax = 26000, ymax = c(16, 41),
fill = "#F3F2EE", colour = "black", size = 0.3)

<br />
<a name="Gfu1v"></a>
step14:annotate 函數(shù)參數(shù) richtext 添加中間小表頭
annotate("richtext", x = 13000, y = c(14.5, 39.5),
label = c("**1915-1918** Tour suspended because of Word War I",
"**1940-1946** Tour suspended because of Word War II"),
label.color = NA, fill = "#F3F2EE", hjust = 0.5,
family = "IBM Plex Sans", size = 3.5)

<br />
<a name="E0c7U"></a>
step15:annotate 函數(shù)參數(shù) text 給 DISTANCE 欄加上單位刻度
annotate("text", x = c(100, 4900), y = 0,
label = c("0", "8000 km"), hjust = c(0, 1),
family = "IBM Plex Mono Light", size = 3)

<br />
<a name="TyUrp"></a>
step16:annotate 函數(shù)參數(shù) text 給其他的添加刻度尺和注釋
annotate("text", x = c(16100, 19900), y = 0,
label = c("0", "60 km/h"), hjust = c(0, 1),
family = "IBM Plex Mono Light", size = 3) +
annotate("text", x = c(20100, 23900), y = 0,
label = c("0", "300 h"), hjust = c(0, 1),
family = "IBM Plex Mono Light", size = 3) +
annotate("text", x = 26000, y = -6,
label = "Source: alastairrushworth/tdf & kaggle.com/jaminliu | Graphic: Georgios Karamanis",
hjust = 1, family = "IBM Plex Mono Light", size = 3)

<br />
<a name="9CuG9"></a>
step17:coord_cartesian 函數(shù)取消畫板限制范圍
- 圖形相對(duì)于 step16 沒啥變化
coord_cartesian(clip = 'off')

<a name="HBo0W"></a>
step18:scale_x_continuous 函數(shù)通過 limits 和 expand 函數(shù)控制貼 y 軸距離
scale_x_continuous(limits = c(-2300, 26300), expand = expansion(add = 1))

<br />
<a name="A31Sj"></a>
step19:scale_y_reverse 函數(shù)翻轉(zhuǎn) y 軸左邊起始順序喧务,上下顛倒赖歌,并通過 expand = expansion(add = 0) 控制 y 軸頂端和低端間隙為 0
scale_y_reverse(expand = expansion(add = 0))

<br />
<a name="nszRU"></a>
step20:labs 加標(biāo)題以及 theme_void 去除主題線條背景以及坐標(biāo)軸
labs(
title = "Tour de France Winners"
) +
theme_void(base_family = "JetBrains Mono")

<br />
<a name="SAvaF"></a>
step21:設(shè)置灰色背景,畫板大小功茴,以及標(biāo)題大小
-
F3F2EE 色條為灰白色:https://www.color-hex.com/color/f3f2ee
- image.png
- plot.margin:控制上下左右邊距(上庐冯,左,下坎穿,右)
theme(
plot.background = element_rect(fill = "#F3F2EE", colour = NA),
plot.margin = margin(20, 20, 20, 20),
plot.title = element_text(hjust = 0.01, size = 28,
family = "IBM Plex Sans Bold", margin = margin(0, 0, -8, 0))
)

<br />
<a name="ofV8b"></a>
step22:here 函數(shù)加時(shí)間函數(shù)命名文件名
ggsave(here::here("2020-week15", "plots", "temp",
paste0("tour-de-france", format(Sys.time(), "%Y%m%d_%H%M%S"), ".png")),
dpi = 320, width = 11, height = 15)
<br />step23:附加 AI 操作視頻<br />