TidyTuesday 可視化學(xué)習(xí)之 ggplot2 一筆一畫繪制表格

更好閱讀移步至:https://www.yuque.com/docs/share/01fe5958-5f6b-4364-aa39-cb7d3fd602ed?#

參考鏈接:

image.png
image.png

<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:添加注釋和以及幾何圖形特別方便吞瞪,為所欲為

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 />
image.png
image.png

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 />

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)
image.png
image.png

<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) 
image.png
image.png

<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")
image.png
image.png

<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) 
image.png
image.png

<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 />
image.png
image.png

<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 />
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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) 
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<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)
image.png
image.png

<br />

<a name="9CuG9"></a>

step17:coord_cartesian 函數(shù)取消畫板限制范圍

  • 圖形相對(duì)于 step16 沒啥變化
coord_cartesian(clip = 'off') 
image.png
image.png

<a name="HBo0W"></a>

step18:scale_x_continuous 函數(shù)通過 limits 和 expand 函數(shù)控制貼 y 軸距離

scale_x_continuous(limits = c(-2300, 26300), expand = expansion(add = 1))
image.png
image.png

<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))
image.png
image.png

<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") 
image.png
image.png

<br />

<a name="SAvaF"></a>

step21:設(shè)置灰色背景,畫板大小功茴,以及標(biāo)題大小

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))
  )
image.png
image.png

<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 />

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末展父,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子玲昧,更是在濱河造成了極大的恐慌栖茉,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孵延,死亡現(xiàn)場(chǎng)離奇詭異衡载,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)隙袁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門痰娱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人菩收,你說我怎么就攤上這事梨睁。” “怎么了娜饵?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵坡贺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我箱舞,道長(zhǎng)遍坟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任晴股,我火速辦了婚禮愿伴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘电湘。我一直安慰自己隔节,他們只是感情好鹅经,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怎诫,像睡著了一般瘾晃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幻妓,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天蹦误,我揣著相機(jī)與錄音,去河邊找鬼肉津。 笑死胖缤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阀圾。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼狗唉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼初烘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起分俯,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肾筐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后缸剪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吗铐,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年杏节,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唬渗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奋渔,死狀恐怖镊逝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嫉鲸,我是刑警寧澤撑蒜,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站玄渗,受9級(jí)特大地震影響座菠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜藤树,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一浴滴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岁钓,春花似錦巡莹、人聲如沸司志。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骂远。三九已至,卻和暖如春腰根,著一層夾襖步出監(jiān)牢的瞬間激才,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工额嘿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘸恼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓册养,卻偏偏與公主長(zhǎng)得像东帅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子球拦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容