2019-08-26用ggplot2畫“美圖”

A ggplot2 Tutorial for Beautiful Plotting in R

原文見https://cedricscherer.netlify.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r/

引言

從2016年開始,我不得不準備博士工作介紹的講演锈锤,因為非常討厭R的基礎(chǔ)繪圖包的語法和樣式驯鳖,從那時起開始用ggplot2 來可視化我的數(shù)據(jù)。因為時間不夠久免,我試了n次錯用于繪制這些圖形 浅辙,還用了大量的谷歌搜索的幫助。我經(jīng)逞掷眩回顧的資源是篇博客文章Beautiful plotting in R: A ggplot2 cheatsheet 记舆,作者是 Zev Ross, 2014年8月4日發(fā)布,最后更新于2016年1月呼巴。歸功于這個博客文章泽腮,我的演講中包含了很多非常優(yōu)美的圖形。我決定把這篇教程逐步予以介紹衣赶。我從中獲益良多诊赊,從直接修改代碼開始,與時俱進府瞄,增加了很多代碼段碧磅、圖表類型和資源。

由于Zev Ross 的博客很多年沒有更新了摘能,我在自己的Github上有跟新版(最后更新于2017年1月)。在此主頁是最合適的地方(另外敲街,我添加了多處更新团搞,如精彩絕倫的patchworkggforce包。還有餅圖多艇,因為人人都愛looooves餅圖B呖帧)

image.png

以下是我做的主要修改:

  • 遵循R的規(guī)范格式,如 Hadley Wickham, GoogleCoding Club 指導(dǎo)格式),
  • 改變了圖形的樣式和外觀(如不僅僅做了些許改變峻黍,我改變了所有繪圖的軸標題复隆、圖例和漂亮的顏色),
  • 更新的版本在 ggplot2 中記錄了這些變化,
  • 修改了輸入的數(shù)據(jù) (GitHub 資源),
  • 為實戰(zhàn)練習(xí)和研討會準備了可執(zhí)行的R腳本,
  • 加入了額外的小提示姆涩,如:
    • 另外的繪圖類型 (例如輪廓圖挽拂、地毯圖、屋脊圖)
    • 如何和為什么使用Viridis調(diào)色板
    • 使用 Tufte 打印樣式創(chuàng)建最小繪圖
    • 如何調(diào)整繪圖標題骨饿、副標題和標題
    • 如何為圖形加入不同的線型
    • 如何在圖例和圖例項名稱改變順序
    • 如何為數(shù)據(jù)添加標簽(如何做的更美觀)

目錄

點擊進入英文原文鏈接亏栈,哈哈哈??????Lㄐ取!绒北!

Preparation(準備)

  • 用著這個鏈接下載數(shù)據(jù) 這里.
  • 帶有可執(zhí)行代碼的 Rmarkdwon 腳本在下載 here.
  • 以下是需要安裝的包:
    • ggplot2
    • ggthemes
    • tidyverse
    • extrafont
    • patchwork
    • cowplot
    • grid
    • gridExtra
    • ggrepel
    • reshape2
    • ggforce
    • ggridges
    • shiny
install.packages(c("ggplot2", "ggthemes", "tidyverse", "extrafont", 
                   "cowplot", "grid", "gridExtra", "ggrepel", 
                   "reshape2", "ggforce", "ggridges", "shiny"))

devtools::install_github("thomasp85/patchwork")

(出于教學(xué)目的黎侈,在任何一個繪圖章節(jié)中,除了個ggplot2之外闷游,在相應(yīng)的代碼塊中都加載了必要的R包)

The Dataset(數(shù)據(jù)集)

我們采用的數(shù)據(jù)來源于 National Morbidity and Mortality Air Pollution Study (NMMAPS)峻汉。為了使圖形可控,我們把數(shù)據(jù)限定于芝加哥和1997-2000脐往。更多的數(shù)據(jù)細節(jié)休吠,參考Roger Peng的圖書 Statistical Methods in Environmental Epidemiology with R.

chic <- readr::read_csv("https://raw.githubusercontent.com/Z3tt/R-Tutorials/master/ggplot2/chicago-nmmaps.csv")
tibble::glimpse(chic)
## Observations: 1,461
## Variables: 10
## $ city     <chr> "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic"...
## $ date     <date> 1997-01-01, 1997-01-02, 1997-01-03, 1997-01-04, 1997-01-05, 1997-01-06, 1997-01-07, 1997-01-08, 1997-01-09, 1997-01-10, 1997-01-11, 1997-01-12, 1997-01-13, 1997-01-14, 1997-01-15, 1997-01-16, 1997-01-17, 1997-01-18, 1997-01-19, 1997-01-20, 1997-01-21, 1997-01-22, 1997-01-23, 1997-01-24, 1997-01-25, 1997-01-26, 1997-01-27, 1997-01-28, 1997-01-29, 1997-01-30, 1997-01-31, 1997-02-01, 1997-02-02, 1997-02-03, 1997-02-04, 1997-02-05, 1997-02-06, 1997-02-07, 1997-02-08, 1997-02-09, 1997-02-10, 1997-02-11, 1997-02-12, 1997-02-13, 1997-02-14, 1997-02-15, 1997-02-16, 1997-02-17, 1997-02-18, 1997-02-19, 1997-02-20, 1997-02-21, 1997-02-22, 1997-02-23, 1997-02-24, 1997-02-25, 1997-...
## $ death    <dbl> 137, 123, 127, 146, 102, 127, 116, 118, 148, 121, 110, 127, 129, 151, 128, 132, 116, 142, 124, 124, 127, 121, 134, 120, 109, 109, 115, 105, 114, 120, 117, 126, 97, 96, 119, 125, 116, 118, 121, 114, 111, 107, 127, 98, 104, 122, 124, 120, 106, 103, 139, 133, 109, 121, 111, 105, 107, 123, 124, 125, 108, 114, 104, 120, 134, 101, 102, 125, 119, 115, 121, 112, 127, 99, 125, 115, 113, 105, 113, 120, 105, 119, 147, 123, 108, 117, 110, 106, 96, 119, 119, 99, 120, 130, 97, 105, 102, 104, 137, 111, 108, 96, 100, 105, 128, 120, 98, 118, 94, 117, 121, 110, 110, 108, 121, 114, 116, 109, 123, 115, 101, 118, 100, 126, 126, 121, 114, 112, 111, 111, 107, 124, 104, 107, 109, 133, 108, 109...
## $ temp     <dbl> 36.0, 45.0, 40.0, 51.5, 27.0, 17.0, 16.0, 19.0, 26.0, 16.0, 1.5, 1.0, 3.0, 10.0, 19.0, 9.5, -3.0, 0.0, 14.0, 31.0, 35.0, 36.5, 26.0, 32.0, 14.5, 11.0, 17.0, 2.0, 8.0, 16.5, 31.5, 35.0, 36.5, 30.0, 34.5, 30.0, 26.0, 25.5, 25.5, 26.0, 27.0, 23.5, 21.0, 20.5, 25.5, 20.0, 18.5, 30.0, 48.5, 37.5, 35.5, 36.0, 26.0, 28.0, 21.5, 25.5, 36.5, 34.5, 37.5, 45.5, 35.0, 33.5, 38.0, 33.0, 26.5, 35.5, 39.0, 37.0, 44.0, 37.0, 33.5, 37.5, 26.5, 19.0, 24.5, 45.0, 33.5, 35.5, 46.0, 53.5, 37.5, 32.5, 33.0, 40.5, 44.0, 60.5, 55.5, 43.5, 37.5, 38.5, 44.5, 53.0, 59.5, 62.5, 60.5, 45.0, 34.0, 28.5, 30.0, 30.5, 33.5, 33.5, 38.5, 41.5, 49.0, 43.0, 40.5, 40.0, 45.5, 49.0, 45.0, 43.0, 48.5, 47.5, 4...
## $ dewpoint <dbl> 37.50000, 47.25000, 38.00000, 45.50000, 11.25000, 5.75000, 7.00000, 17.75000, 24.00000, 5.37500, -6.62500, -8.87500, 1.50000, 11.50000, 23.25000, -9.75000, -10.37500, -4.12500, 22.62500, 27.25000, 41.62500, 20.75000, 18.75000, 29.50000, -1.37500, 17.12500, 8.37500, -6.37500, 11.00000, 16.37500, 33.75000, 29.66667, 29.62500, 28.00000, 32.00000, 24.25000, 21.87500, 23.37500, 22.50000, 21.00000, 21.75000, 19.50000, 11.60000, 16.37500, 23.00000, 15.25000, 8.12500, 32.62500, 41.37500, 27.50000, 44.12500, 29.62500, 24.25000, 14.62500, 10.87500, 27.12500, 35.00000, 30.25000, 36.00000, 44.00000, 27.37500, 29.37500, 28.87500, 28.62500, 13.37500, 35.25000, 28.25000, 32.62500, 33....
## $ pm10     <dbl> 13.052268, 41.948600, 27.041751, 25.072573, 15.343121, 9.364655, 20.228428, 33.134819, 12.118381, 24.761534, 18.126151, 16.013770, 34.991079, 64.945403, 26.941955, 27.022906, 18.837025, 31.859740, 30.923168, 19.894566, 27.882017, 18.508762, 11.845698, 26.687346, 16.612825, 21.641455, 22.672498, 28.101180, 51.776607, 48.741462, 24.686329, 23.784943, 27.762150, 21.600928, 17.050900, 10.157749, 15.943086, 33.010704, 14.955909, 30.410449, 23.914813, 22.972347, 12.712336, 22.719836, 35.676001, 28.373076, 15.662430, 38.744847, 27.597166, 17.612211, 29.768805, 7.340321, 7.856717, 7.908915, 17.834350, 41.124012, 34.052583, 19.749350, 26.126759, 28.129506, 9.940940, 15.980970, 2...
## $ o3       <dbl> 5.659256, 5.525417, 6.288548, 7.537758, 20.760798, 14.940874, 11.920985, 8.678477, 13.355892, 10.448264, 15.866094, 15.115290, 9.381068, 8.029508, 7.066111, 20.113023, 15.363898, 12.713223, 9.616133, 16.840369, 12.758676, 21.024213, 18.665072, 7.131938, 17.167861, 9.960118, 9.167350, 13.613967, 7.945009, 7.660619, 11.882608, 16.676182, 12.032368, 21.849559, 10.887549, 14.894031, 15.957824, 14.391243, 19.749645, 12.397635, 14.193562, 20.492388, 23.091993, 20.171005, 15.453240, 19.526661, 20.019234, 17.297562, 27.013275, 19.055436, 6.890252, 16.313610, 23.015853, 24.990318, 18.939318, 12.526243, 7.962753, 13.194153, 15.178614, 13.860717, 30.992349, 29.260852, 15.413875, 1...
## $ time     <dbl> 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, ...
## $ season   <chr> "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter"...
## $ year     <dbl> 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, ...
head(chic, 10)
## # A tibble: 10 x 10
##    city  date       death  temp dewpoint  pm10    o3  time season  year
##    <chr> <date>     <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>  <dbl>
##  1 chic  1997-01-01   137  36      37.5  13.1   5.66  3654 Winter  1997
##  2 chic  1997-01-02   123  45      47.2  41.9   5.53  3655 Winter  1997
##  3 chic  1997-01-03   127  40      38    27.0   6.29  3656 Winter  1997
##  4 chic  1997-01-04   146  51.5    45.5  25.1   7.54  3657 Winter  1997
##  5 chic  1997-01-05   102  27      11.2  15.3  20.8   3658 Winter  1997
##  6 chic  1997-01-06   127  17       5.75  9.36 14.9   3659 Winter  1997
##  7 chic  1997-01-07   116  16       7    20.2  11.9   3660 Winter  1997
##  8 chic  1997-01-08   118  19      17.8  33.1   8.68  3661 Winter  1997
##  9 chic  1997-01-09   148  26      24    12.1  13.4   3662 Winter  1997
## 10 chic  1997-01-10   121  16       5.38 24.8  10.4   3663 Winter  1997

The ggplot2 Package(ggplot2包)

ggplot2 是個以聲明方式創(chuàng)建圖形的系統(tǒng),基于此書 The Grammar of Graphics钙勃。你需要提供數(shù)據(jù)蛛碌,告訴 ggplot2 如何把變量映射到美學(xué)外觀、使用何種圖形屬性辖源,細節(jié)問題由ggplot2處理蔚携。

隨后,一幅ggplot圖被從幾個基本原件所創(chuàng)建:

1.數(shù)據(jù):
用于繪圖的原始數(shù)據(jù)The raw data that you want to plot.
2.幾何形狀 geom_:
表示數(shù)據(jù)的幾何圖形克饶。
3.美學(xué)外觀 aes()_:
幾何和統(tǒng)計對象的美學(xué)外觀酝蜒,如顏色、大小矾湃、形狀霉咨、透明度和位置顽腾。
4.標度 scale_:
在數(shù)據(jù)和美學(xué)維度間進行映射锅风,如數(shù)據(jù)范圍到繪圖寬度或賦予顏色的因數(shù)。
5.統(tǒng)計變換 stat_:
數(shù)據(jù)的統(tǒng)計匯總工育,分位數(shù)、擬合曲線和總和坞生。
6.坐標系 coord_:
用于將數(shù)據(jù)坐標映射到數(shù)據(jù)矩形平面的轉(zhuǎn)換。
7分面 facet_:
把數(shù)據(jù)分列成圖形網(wǎng)格卒废。
8.視覺主題 theme():
圖形的總體視覺默認效果沛厨,如背景、網(wǎng)格升熊、坐標軸俄烁、默認字體、大小和顏色级野。

A Default ggplot(默認的ggplot)

首先页屠,我們加載 ggplot2包 (也能通過 tidyverse包加載):

library(ggplot2)
#library(tidyverse)

ggplot2 的語法體系有別于基本R繪圖包。如前所示蓖柔,我們經(jīng)常開始通過 ggplot(data = df, aes(x = 變量1, y = 變量2)) 定義繪圖原件辰企,它告訴ggplot2我們用此數(shù)據(jù)開始工作。因而况鸣,運行這個命令牢贸,只創(chuàng)建了一個繪圖板,因為ggplot2不知道我們想怎樣用這個數(shù)據(jù)進行繪圖镐捧。

(g <- ggplot(chic, aes(x = date, y = temp)))
image.png

提示: 在創(chuàng)建圖形時潜索,用括號創(chuàng)建一個對象,將即刻輸出對象(而不是寫作g <- ggplot(...) 懂酱,然后 g)竹习。

讓我們告訴 ggplot想用的樣式:

g + geom_point()
image.png

別擔(dān)心,我們將在后面學(xué)習(xí)幾個繪圖類型列牺。

Change Color of Points(改變點的顏色)

用這個命令整陌,可以改變美學(xué)外觀,如改變點的顏色:

g + geom_point(color = "firebrick")
image.png

把其用之于我們的繪圖原件,以下基于g的圖形就有了紅色點泌辫。

通過設(shè)置一個不同內(nèi)置的主題随夸,如theme_bw,我們就去除了默認的灰色系的外觀震放。

theme_set(theme_bw())

g + geom_point(color = "firebrick")

image.png

(能在 “Working with Themes”部分找到怎樣使用內(nèi)置主題和怎樣定制主題宾毒。)

Working with Axes(坐標軸)

加入坐標軸標簽

讓我們?yōu)樽鴺溯S加入寫好的標簽

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = expression(paste("Temperature (", degree ~ F, ")")))
image.png

Move Labels Away from the Plot & Change Color(從圖形中移動標簽和改變標簽顏色)

theme() 是一個必要的命令用于修改各種主題元素(文本和標題,框線殿遂、符號伍俘、背景等)。我們將大量使用它勉躺,參見可能的外觀here.

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(axis.title.x = element_text(color = "sienna", 
                                    size = 15, vjust = -0.35),
        axis.title.y = element_text(color = "orangered", 
                                    size = 15, vjust = 0.35))
image.png

Change Size & Angle of Tick Text(改變文本的大小和角度)

用angle和vjust調(diào)整文本的位置(0=左對齊癌瘾,0.5=中心對齊,1=右對齊):

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)") +
  theme(axis.text.x = element_text(angle = 50, size = 16, 
                                   vjust = 0.5))
image.png

Remove Axis Ticks & Tick Text(去除坐標軸刻度和刻度文本)

很少有理由去這么做-但是要這么做就需要這樣來:

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)") +
  theme(axis.ticks.y = element_blank(), 
        axis.text.y = element_blank())

image.png

如果你想去掉主體元素饵溅,參數(shù)的元素就是element_blank()妨退。

Limit Axis Range(限制坐標軸范圍)

有時候想要縮放你的數(shù)據(jù),可以這樣做蜕企,而不需要從數(shù)據(jù)取子集咬荷。

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)") +
  ylim(c(0, 50))
image.png

另外,可用g + scale_x_continuous(limits = c(0, 50))或者g + coord_cartesian(xlim = c(0, 50))轻掩。前者移除了范圍以外的所有的數(shù)據(jù)點幸乒,而第二個調(diào)整了可視的范圍。

Force Plot to Start at Origin(強制繪圖開始于原點)

與之相關(guān)唇牧,可以強制R繪圖開始于原點:

library(tidyverse)

chic %>% 
  dplyr::filter(temp > 25, o3 > 20) %>% 
  ggplot(aes(x = temp, y = o3)) + 
    geom_point() + 
    labs(x = expression(paste("Temperature higher than 25 ", degree ~ F, "")), 
         y = "Ozone higher than 20 ppb") + 
   expand_limits(x = 0, y = 0)

image.png

coord_cartesian(xlim = c(0, max(chic_red$temp)), ylim = c(0, max(chic_red$o3)))能得到相同的結(jié)果罕扎。
也能真正的強制繪圖開始于原點。

chic %>% 
  dplyr::filter(temp > 25, o3 > 20) %>% 
  ggplot(aes(x = temp, y = o3)) + 
    geom_point() + 
    labs(x = expression(paste("Temperature higher than 25 ", degree ~ F, "")), 
         y = "Ozone higher than 20 ppb") + 
    expand_limits(x = 0, y = 0) + 
    scale_x_continuous(expand = c(0, 0)) + 
    scale_y_continuous(expand = c(0, 0)) +
    coord_cartesian(clip = "off")
image.png

Axes with Same Scaling(帶有相同標度的坐標)

出于展示的目的丐重,我們用溫度和帶有隨機噪聲的溫度繪圖:

ggplot(chic, aes(x = temp, y = temp + rnorm(nrow(chic), sd = 20))) +
   geom_point() +
   labs(x = "Temperature (°F)") +
   xlim(c(0, 100)) + ylim(c(0, 150)) +
   coord_equal()
image.png

Use a Function to Alter Labels(用函數(shù)改變標簽)

有時要稍稍改變標簽腔召,或者加入單位或百分比符號,而不把他們加入你的數(shù)據(jù)扮惦。這種情況下臀蛛,可以用一個函數(shù)來實現(xiàn)。這是一個例子:

ggplot(chic, aes(x = date, y = temp)) +
   geom_point(color = "firebrick") +
   labs(x = "Year", y = "Temperature (°F)") +
   scale_y_continuous(label = function(x) {return(paste(x, "Degrees Fahrenheit"))})  
image.png

Working with Titles(標題)

Add a Title(加入標題)

能用ggtitle()函數(shù)加入標題:

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)") + 
  ggtitle("Temperatures in Chicago")
image.png

此外崖蜜,可以用g + labs(tite = "Temperatures in Chicago")浊仆。這里可以加入幾個參數(shù),如加入副標題和一個標題:

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)",
       title = "Temperatures in Chicago", 
       subtitle = "Seasonal pattern of daily temperatures from 1997 to 2001", 
       caption = "Data: NMMAPS")
image.png

Make Title Bold & Add a Space at the Baseline(將標題加粗和基線加入空格)

face參數(shù)能用于使字體加粗或斜體豫领。margin參數(shù)用 margin函數(shù)提供上下左右的邊界(默認單位是點)抡柿。

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)", 
       title = "Temperatures in Chicago") + 
  theme(plot.title = element_text(size = 15, face = "bold", 
                                  margin = margin(10, 0, 10, 0)))
image.png

(記住邊界參數(shù)的好方法是“trouble”的trbl字母與四個邊很像)宴卖。

Adjust Position of Titles(調(diào)整標題的位置)

hjust控制對齊(代表水平調(diào)整):

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +  
  labs(x = "Year", y = "Temperature (°F)", 
       title = "Temperatures in Chicago") + 
  theme(plot.title = element_text(size = 15, face = 4, hjust = 1))

image.png

當(dāng)然埃仪,用vjust可以調(diào)節(jié)垂直對齊。

Use a Non-Traditional Font in Your Title(在題目中用非傳統(tǒng)的字體)

值得注意的是可以用不同的字體亚再。為了用安裝到你機器上的字體(可能你在用office程序)鼠锈,我們從extrafont包獲取幫助闪檬。在加載包后,需要輸入和加載安裝到你機器上的:

library(extrafont)
extrafont::font_import()
## Importing fonts may take a few minutes, depending on the number of fonts and the speed of the system.
## Continue? [y/n]
## extrafont::loadfonts(device = "win")

可以先看一下你輸入的字體庫购笆,用fonts()fonttable().

現(xiàn)在粗悯,我們使用這些字體家族的一種:

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)", title = "Temperatures in Chicago") + 
  theme(plot.title = element_text(size = 18, family = "Merriweather"))
image.png

(你也可以為你的圖形設(shè)置一種非默認的字體,詳見“Working with Themes”部分同欠。我用Roboto Condensed作為圖形的新的默認字體)

theme_set(theme_bw(base_size = 12, base_family = "Roboto Condensed"))

Change Spacing in Multi-Line Text(在多行文本中改變間隔)

能用 lineheight 參數(shù)改變行的間隔样傍。在本例中,我把行壓縮了一點(行高小于1)铺遂。

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") + 
  labs(x = "Year", y = "Temperature (°F)") + 
  ggtitle("Temperatures in Chicago\nfrom 1997 to 2001") + 
  theme(plot.title = element_text(size = 16, face = "bold", 
                                  vjust = 1, lineheight = 0.75))
image.png

Working with Legends(圖例)

我們將按照季節(jié)為圖形著色衫哥。你會看到默認情況下,圖例的標題正是我們在顏色參數(shù)所定義的:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)")
image.png

Turn Off the Legend(關(guān)閉圖例)

常被問及的第一個問題是:“我怎樣才能去掉圖例襟锐?”撤逢。
很容易就能用legend.position = "none"實現(xiàn):

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.position = "none")
image

取決于特定的情況,也可以用guides(fill = F)或者用scale_fill_discrete(guide = F)粮坞。

Turn Off Legend Titles(關(guān)閉圖例標題)

正如我們所學(xué)蚊荣,用 element_blank() 來繪制無圖(nothing):

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.title = element_blank())
image

Change Legend Position(改變圖例位置)

如不想把圖例置于右側(cè),可在用themelegend.position 參數(shù) :

gplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.position = "bottom")
image

可能的位置包括:上莫杈,右互例,下,左筝闹。

Change Style of Legend Titles(改變圖例標題的樣式)

通過調(diào)節(jié)主題元素legend.title修改圖例題目的外觀:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.title = element_text(color = "chocolate", 
                                    size = 14, face = "bold"))
image

Change Legend Title(改變圖例標題)

改變圖例標題最簡便的方式是使用labs參數(shù):

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)", color = "Seasons\nindicated\nby colors:") + 
  theme(legend.title = element_text(color = "chocolate", 
                                    size = 14, face = "bold"))

image.png

取決于展示變量的類型媳叨,圖例的細節(jié)可通過scale_color_discretescale_color_continuous修改。

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.title = element_text(color = "chocolate", 
                                    size = 14, face = "bold")) +
  scale_color_discrete(name = "Seasons\nindicated\nby colors:")

Change Order of Legend Keys(改變圖例的排序)

通過改變season的水平達到目的 :

chic$season <- factor(chic$season, levels = c("Spring", "Summer", 
                                              "Autumn", "Winter"))

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)")

Change Legend Labels(改變圖例標簽)

我們實現(xiàn)以其涵蓋的月份替換季節(jié)標簽:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.title = element_text(color = "chocolate", 
                                    size = 14, face = 2)) +
  scale_color_discrete("Seasons:", labels = c("Mar - May", "Jun - Aug", 
                                              "Sep - Nov", "Dec - Feb"))
image.png

Change Background Boxes in the Legend(改變圖例的背景邊框)

要改變(填充)圖例項的背景色关顷,我們需要調(diào)整主題元素legend.key的設(shè)置:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.key = element_rect(fill = "darkgoldenrod1"),
        legend.title = element_text(color = "chocolate", 
                                    size = 14, face = 2)) +
  scale_color_discrete("Seasons:")
image

如果要全部去除背景肩杈,使用fill = NA

Change Size of Legend Symbols(改變圖例符號)

圖例中的點有點損失解寝,特別是沒有邊框時扩然。覆蓋默認的點,試試以下代碼:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(legend.key = element_rect(fill = NA),
        legend.title = element_text(color = "chocolate", 
                                    size = 14, face = 2)) +
  scale_color_discrete("Seasons:") +
  guides(color = guide_legend(override.aes = list(size = 6))
image

Leave a Layer Off the Legend(只在圖例中保留一個圖層)

假如你有一個點狀圖層聋伦,接著你又為同樣的數(shù)據(jù)添加了一個邊際圖夫偶。默認情況下,點圖和線圖使得圖例變成這樣:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  geom_rug() +
  theme(legend.title = element_text(color = "chocolate", 
                                    size = 14, face = 2)) +
  scale_color_discrete("Seasons:")

image.png

可用show.legend = F來關(guān)閉圖例的一個圖層:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  geom_rug(show.legend = F) +
  theme(legend.title = element_text(color = "chocolate", size = 14, face = 2)) +
  scale_color_discrete("Seasons:")
image.png

Manually Adding Legend Items(手動添加圖例項)

ggplot2 不能自動添加圖例觉增,除非你來把美學(xué)參數(shù)(顏色兵拢、大小等)映射到一個變量。我曾不止一次的想有一個圖例逾礁,使得所繪之圖更加清晰说铃。
這是默認圖形:

ggplot(chic, aes(x = date, y = o3)) +
  geom_line(color = "gray") +
  geom_point(color = "darkorange2") +
  labs(x = "Year", y = "Ozone")
image

我們可以強制映射一個圖例到一個變量访惜。用 aes() 映射線和點。在此我們的數(shù)據(jù)集中腻扇,不映射到一個變量债热,而是映射到一個代碼串(以便為每一個線或點繪制一種顏色)。

ggplot(chic, aes(x = date, y = o3)) +
  geom_line(aes(color = "line")) +
  geom_point(aes(color = "points")) +
  labs(x = "Year", y = "Ozone") +
  scale_color_discrete("Type:")
image

已經(jīng)接近幼苛,但是這不是我們想要的窒篱。我們想要灰色和紅色。要改變顏色舶沿,我們使用scale_color_manual()墙杯。另外,使用 guide()函數(shù)覆蓋圖例外觀括荡。

Voila! 現(xiàn)在高镐,我們繪出了灰色的線和紅色的點,還有帶有灰色線和紅色點的圖例符號:

ggplot(chic, aes(x = date, y = o3)) + 
  geom_line(aes(color = "line")) +  
  geom_point(aes(color = "points")) +
  labs(x = "Year", y = "Ozone") +
  scale_color_manual("", guide = "legend", 
                     values = c("points" = "darkorange2", 
                                "line" = "gray")) +
  guides(color = guide_legend(override.aes = list(linetype = c(1, 0), 
                                                  shape = c(NA, 16))))
image

Working with Backgrounds & Grid Lines(背景和網(wǎng)格線)

有很多種方法用一個函數(shù)(如下)改變繪圖的整體外觀畸冲,但是如果你只想改變部分元素的顏色避消,你可以這么做。

Change the Panel Color(改變面板顏色)

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(panel.background = element_rect(fill = "moccasin"))
image

Change Grid Lines(改變網(wǎng)格線)

有兩種網(wǎng)格線:主要網(wǎng)格線指示刻度和在主要網(wǎng)格線之間的次要網(wǎng)格線召夹。

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(panel.background = element_rect(fill = "grey90"),
        panel.grid.major = element_line(color = "gray10", size = 0.5),
        panel.grid.minor = element_line(color = "gray70", size = 0.25))
image

進一步岩喷,你可以在主要網(wǎng)格線和次要網(wǎng)格線間自定義間隔:

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") + 
  scale_y_continuous(breaks = seq(0, 100, 10),
                     minor_breaks = seq(0, 100, 2.5))
image.png

Change the Plot Background Color(改變圖形的背景色)

要改變(填充)圖形區(qū)域的背景色,需要調(diào)節(jié)主題元素的 plot.background:

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(plot.background = element_rect(fill = "gray60"))
image

Working with Margins(邊界)

有時候為繪圖邊界加入一點空隙是有用的监憎。同前面的例子相似纱意,我們用theme()函數(shù)的參數(shù)實現(xiàn)。在此使用參數(shù) plot.margin. 如前鲸阔,我們通過plot.background改變背景色偷霉,已經(jīng)展示了默認的邊際。

現(xiàn)在褐筛,讓我們?yōu)樽笥姨砑宇~外的空間类少。參數(shù)plot.margin可以處理多種不同的單位(厘米、英寸等)渔扎,但是需要使用 grid 包的函數(shù)單位來定義單位硫狞。在此我在左右使用用5厘米的邊際。

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") + 
  theme(plot.background = element_rect(fill = "gray60"),
        plot.margin = unit(c(1, 5, 1, 5), "cm"))
image

邊際的順序是上右下左晃痴。一個容易記憶的方法是 "trouble 分別代表四個邊的首字母残吩。

Working with Multi-Panel Plots(分面繪圖)

ggplot2 包有兩個很好的函數(shù)用于創(chuàng)建分面繪圖。他們相互有聯(lián)系倘核,但是有所不同泣侮,facet_wrap 本質(zhì)上基于一個變量創(chuàng)建了一個繪圖帶,而facet_grid 可以接受兩個變量紧唱。

Create a Single Row of Plots Based on One Variable(基于一個變量創(chuàng)建一列圖形)

facet_wrap 創(chuàng)建一個變量的分面圖活尊,前面用一個破折號: facet_wrap(~ variable)隶校。子圖的外觀用 ncolnrow參數(shù)進行控制:

g <- ggplot(chic, aes(x = date, y = temp)) +
       geom_point(color = "chartreuse4") +
       labs(x = "Year", y = "Temperature (°F)")

g + facet_wrap(~ year, nrow = 1) +
    theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))
image

Create a Matrix of Plots Based on One Variable(基于一個變量創(chuàng)建繪圖矩陣)

g + facet_wrap(~ year, nrow = 2)
image.png

Allow Scales to Roam Free(自由展示標度)

ggplot2分面圖的默認效果是為各自分面圖使用相同的標度。但有時你想讓自己的數(shù)據(jù)的每個分面有自己的標度蛹锰。這不是個好主意深胳,因為這會給用戶對數(shù)據(jù)以錯誤的印象。你可以設(shè)置scales = "free" 來實現(xiàn):

g + facet_wrap(~ year, nrow = 2, scales = "free")
image

注意x和y軸的范圍是不同的宁仔。

Create a Grid of Plots Based on Two Variables(基于兩個變量創(chuàng)建一個繪圖矩陣)

在兩個變量的情況下,facet_grid 可以完成此任務(wù)峦睡。在此翎苫,變量的順序決定了行數(shù)和列數(shù):

ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "orangered") +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  labs(x = "Year", y = "Temperature (°F)") +
  facet_grid(year ~ season)
image

要交換行對列的排布,可以改變 facet_grid(year ~ season)facet_grid(season ~ year)榨了。

Put Two (Different) Plots Side by Side(把兩張圖肩靠肩排列)

有好幾種方法來組合繪圖煎谍。以我愚見,最簡便的方法是 patchwork 龙屉,
Thomas Lin Pedersen寫的:

p1 <- ggplot(chic, aes(x = date, y = temp, 
                       color = factor(season))) + 
        geom_point() + 
        geom_rug() +
        labs(x = "Year", y = "Temperature (°F)")

p2 <- ggplot(chic, aes(x = date, y = o3)) + 
        geom_line(color = "gray") + 
        geom_point(color = "darkorange2") + 
        labs(x = "Year", y = "Ozone")

library(patchwork)
p1 + p2
image

通過兩圖相除呐粘,可以改變圖的順序(注意此排列方式,一個有圖例而另一個沒有圖例):

p1 / p2
image.png

而且嵌套作圖也是可以滴转捕!

(g + p2) / p1
image.png

(注意圖的排布作岖,甚至只有一行包含圖例)
另外,Claus Wilke寫的 cowplot 提供了同樣的功能(以及其它許多好的應(yīng)用):

library(cowplot)
plot_grid(p1, p2)

gridExtra包也可以:

library(gridExtra)
grid.arrange(p1, p2, ncol = 2)

Working with Themes(主題)

Change the Overall Plotting Style(改變整體的繪圖格式)

通過應(yīng)用主題可以改變整體外觀五芝。例如痘儡,Jeffrey Arnold把 ggthemes 庫和幾個用戶定義的主題放到一起。清單參見 ggthemes 網(wǎng)站. 不用任何代碼枢步,你就可以調(diào)節(jié)數(shù)種樣式沉删,其中一些樣式和美學(xué)外觀為大眾所熟知。

這里是一個例子復(fù)制了《經(jīng)濟學(xué)人》雜志的繪圖樣式

library(ggthemes)

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") + 
  ggtitle("Ups and Downs of Chicago's Daily Temperatures") +
  theme_economist() + 
  scale_color_economist(name = "Seasons:") +
  theme(legend.title = element_text(size = 12, face = "bold"))

image.png

另外一個例子是Tufte的繪圖樣式醉途,這是一個基于 Edward Tufte的書 The Visual Display of Quantitative Information的最少筆墨主題矾瑰。 此書以Minard’s chart depicting Napoleon’s march on Russia 作為有史以來人類所創(chuàng)建的最好的統(tǒng)計學(xué)繪圖得以廣為人知。Tuftes 圖變的知名是由于純粹的樣式隘擎。請看你自己的圖:

set.seed(2019)
chic.red <- chic[sample(nrow(chic), 50), ]

ggplot(chic.red, aes(x = temp, y = o3)) +
  geom_point() +
  labs(x = "Temperature (°F)", y = "Ozone") + 
  ggtitle("Temperature and Ozone Levels in Chicago") +
  theme_tufte() +
  stat_smooth(method = "lm", col = "black", size = 0.7, 
              fill = "gray60", alpha = 0.2)
image.png

由于Tufte’s樣式是極簡主義殴穴,我們首先減少用于展示的數(shù)據(jù)點的數(shù)目以貼合這條規(guī)則。(不關(guān)心`stat_smooth() '命令货葬,稍后我會解釋)推正。只是添加它以使繪圖更具趣味。

ggplot(chic.red, aes(x = temp, y = o3)) +
  geom_point() +
  labs(x = "Temperature (°F)", y = "Ozone") + 
  ggtitle("Temperature and Ozone Levels in Chicago") +
  theme_tufte() +
  stat_smooth(method = "lm", col = "black", size = 0.7, 
              fill = "gray60", alpha = 0.2) + 
  geom_rangeframe()

image.png

如果你想如此繪圖宝惰,請參見此博客植榕,用R重繪幾個Tufte 圖。

Change the Size of All Plot Text Elements(改變所有繪圖文本元素的大心岫帷)

很容易就一次性改變所有的文本元素的大小尊残。如果你仔細研究默認的主題(見如下“Create and Use Your Custom Theme”章節(jié))炒瘸,就會注意到所有的元素的大小都相對于基本的大小。所以寝衫,你可以簡單改變基本大小顷扩,如果你想增加繪圖的可讀性:

theme_set(theme_gray(base_size = 30, base_family = "Roboto Condensed"))

ggplot(chic, aes(x = date, y = temp, color = factor(season))) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") + 
  guides(color = F) 
image.png

Create and Use Your Custom Theme(用戶自定義的主題的創(chuàng)建和使用)

如果想要改變整體主題,可以用 theme_set,例如theme_set(theme_bw())慰毅。默認的主題是theme_gray隘截。如果要創(chuàng)建自定義的主題,可以從灰度主題提取代碼并修改汹胃。注意 rel()函數(shù)改變了base_size的大小婶芭。

theme_gray
ize = 11, base_family = "", base_line_size = base_size/22, 
##     base_rect_size = base_size/22) 
## {
##     half_line <- base_size/2
##     theme(line = element_line(colour = "black", size = base_line_size, 
##         linetype = 1, lineend = "butt"), rect = element_rect(fill = "white", 
##         colour = "black", size = base_rect_size, linetype = 1), 
##         text = element_text(family = base_family, face = "plain", 
##             colour = "black", size = base_size, lineheight = 0.9, 
##             hjust = 0.5, vjust = 0.5, angle = 0, margin = margin(), 
##             debug = FALSE), axis.line = element_blank(), axis.line.x = NULL, 
##         axis.line.y = NULL, axis.text = element_text(size = rel(0.8), 
##             colour = "grey30"), axis.text.x = element_text(margin = margin(t = 0.8 * 
##             half_line/2), vjust = 1), axis.text.x.top = element_text(margin = margin(b = 0.8 * 
##             half_line/2), vjust = 0), axis.text.y = element_text(margin = margin(r = 0.8 * 
##             half_line/2), hjust = 1), axis.text.y.right = element_text(margin = margin(l = 0.8 * 
##             half_line/2), hjust = 0), axis.ticks = element_line(colour = "grey20"), 
##         axis.ticks.length = unit(half_line/2, "pt"), axis.ticks.length.x = NULL, 
##         axis.ticks.length.x.top = NULL, axis.ticks.length.x.bottom = NULL, 
##         axis.ticks.length.y = NULL, axis.ticks.length.y.left = NULL, 
##         axis.ticks.length.y.right = NULL, axis.title.x = element_text(margin = margin(t = half_line/2), 
##             vjust = 1), axis.title.x.top = element_text(margin = margin(b = half_line/2), 
##             vjust = 0), axis.title.y = element_text(angle = 90, 
##             margin = margin(r = half_line/2), vjust = 1), axis.title.y.right = element_text(angle = -90, 
##             margin = margin(l = half_line/2), vjust = 0), legend.background = element_rect(colour = NA), 
##         legend.spacing = unit(2 * half_line, "pt"), legend.spacing.x = NULL, 
##         legend.spacing.y = NULL, legend.margin = margin(half_line, 
##             half_line, half_line, half_line), legend.key = element_rect(fill = "grey95", 
##             colour = "white"), legend.key.size = unit(1.2, "lines"), 
##         legend.key.height = NULL, legend.key.width = NULL, legend.text = element_text(size = rel(0.8)), 
##         legend.text.align = NULL, legend.title = element_text(hjust = 0), 
##         legend.title.align = NULL, legend.position = "right", 
##         legend.direction = NULL, legend.justification = "center", 
##         legend.box = NULL, legend.box.margin = margin(0, 0, 0, 
##             0, "cm"), legend.box.background = element_blank(), 
##         legend.box.spacing = unit(2 * half_line, "pt"), panel.background = element_rect(fill = "grey92", 
##             colour = NA), panel.border = element_blank(), panel.grid = element_line(colour = "white"), 
##         panel.grid.minor = element_line(size = rel(0.5)), panel.spacing = unit(half_line, 
##             "pt"), panel.spacing.x = NULL, panel.spacing.y = NULL, 
##         panel.ontop = FALSE, strip.background = element_rect(fill = "grey85", 
##             colour = NA), strip.text = element_text(colour = "grey10", 
##             size = rel(0.8), margin = margin(0.8 * half_line, 
##                 0.8 * half_line, 0.8 * half_line, 0.8 * half_line)), 
##         strip.text.x = NULL, strip.text.y = element_text(angle = -90), 
##         strip.placement = "inside", strip.placement.x = NULL, 
##         strip.placement.y = NULL, strip.switch.pad.grid = unit(half_line/2, 
##             "pt"), strip.switch.pad.wrap = unit(half_line/2, 
##             "pt"), plot.background = element_rect(colour = "white"), 
##         plot.title = element_text(size = rel(1.2), hjust = 0, 
##             vjust = 1, margin = margin(b = half_line)), plot.subtitle = element_text(hjust = 0, 
##             vjust = 1, margin = margin(b = half_line)), plot.caption = element_text(size = rel(0.8), 
##             hjust = 1, vjust = 1, margin = margin(t = half_line)), 
##         plot.tag = element_text(size = rel(1.2), hjust = 0.5, 
##             vjust = 0.5), plot.tag.position = "topleft", plot.margin = margin(half_line, 
##             half_line, half_line, half_line), complete = TRUE)
## }
## <bytecode: 0x0000000006c89660>
## <environment: namespace:ggplot2>

現(xiàn)在,讓我們修改默認主題函數(shù)着饥,并看看效果圖:

theme_custom <- function (base_size = 12, base_family = "Roboto Condensed") {
  half_line <- base_size/2
  theme(line = element_line(color = "black", size = 0.5, linetype = 1, lineend = "butt"), 
        rect = element_rect(fill = "white", color = "black", size = 0.5, linetype = 1), 
        text = element_text(family = base_family, face = "plain", color = "black", 
                            size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5, 
                            angle = 0, margin = margin(), debug = F), 
        axis.line = element_blank(), 
        axis.line.x = NULL, 
        axis.line.y = NULL, 
        axis.text = element_text(size = base_size * 1.1, color = "gray30"), 
        axis.text.x = element_text(margin = margin(t = 0.8 * half_line/2), vjust = 1), 
        axis.text.x.top = element_text(margin = margin(b = 0.8 * half_line/2), vjust = 0), 
        axis.text.y = element_text(margin = margin(r = 0.8 * half_line/2), hjust = 1), 
        axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line/2), hjust = 0), 
        axis.ticks = element_line(color = "gray30", size = 0.7), 
        axis.ticks.length = unit(half_line / 1.5, "pt"), 
        axis.title.x = element_text(margin = margin(t = half_line), vjust = 1, 
                                    size = base_size * 1.3, face = "bold"), 
        axis.title.x.top = element_text(margin = margin(b = half_line), vjust = 0), 
        axis.title.y = element_text(angle = 90, margin = margin(r = half_line), 
                                    vjust = 1, size = base_size * 1.3, face = "bold"), 
        axis.title.y.right = element_text(angle = -90, vjust = 0, 
                                          margin = margin(l = half_line)), 
        legend.background = element_rect(color = NA), 
        legend.spacing = unit(0.4, "cm"), 
        legend.spacing.x = NULL, 
        legend.spacing.y = NULL, 
        legend.margin = margin(0.2, 0.2, 0.2, 0.2, "cm"), 
        legend.key = element_rect(fill = "gray95", color = "white"), 
        legend.key.size = unit(1.2, "lines"), 
        legend.key.height = NULL, 
        legend.key.width = NULL, 
        legend.text = element_text(size = rel(0.8)), 
        legend.text.align = NULL, 
        legend.title = element_text(hjust = 0), 
        legend.title.align = NULL, 
        legend.position = "right", 
        legend.direction = NULL, 
        legend.justification = "center", 
        legend.box = NULL, 
        legend.box.margin = margin(0, 0, 0, 0, "cm"), 
        legend.box.background = element_blank(), 
        legend.box.spacing = unit(0.4, "cm"), 
        panel.background = element_rect(fill = "white", color = NA),
        panel.border = element_rect(color = "gray30", 
                                    fill = NA, size = 0.7),
        panel.grid.major = element_line(color = "gray90", size = 1),
        panel.grid.minor = element_line(color = "gray90", size = 0.5, 
                                        linetype = "dashed"),
        panel.spacing = unit(base_size, "pt"), 
        panel.spacing.x = NULL, 
        panel.spacing.y = NULL, 
        panel.ontop = F, 
        strip.background = element_rect(fill = "white", color = "gray30"), 
        strip.text = element_text(color = "black", size = base_size), 
        strip.text.x = element_text(margin = margin(t = half_line, 
                                                    b = half_line)), 
        strip.text.y = element_text(angle = -90, margin = margin(l = half_line, 
                                                                 r = half_line)), 
        strip.placement = "inside", 
        strip.placement.x = NULL, 
        strip.placement.y = NULL, 
        strip.switch.pad.grid = unit(0.1, "cm"), 
        strip.switch.pad.wrap = unit(0.1, "cm"), 
        plot.background = element_rect(color = NA), 
        plot.title = element_text(size = base_size * 1.8, hjust = 0.5, 
                                  vjust = 1, face = "bold", 
                                  margin = margin(b = half_line * 1.2)), 
        plot.subtitle = element_text(size = base_size * 1.3, hjust = 0.5, vjust = 1, 
                                     margin = margin(b = half_line * 0.9)), 
        plot.caption = element_text(size = rel(0.9), hjust = 1, vjust = 1, 
                                    margin = margin(t = half_line * 0.9)),
        plot.tag = element_text(size = rel(1.2), hjust = 0.5, vjust = 0.5), 
        plot.tag.position = "topleft", 
        plot.margin = margin(base_size, base_size, base_size, base_size), complete = T)
}

瀏覽一下修改的外觀犀农,新的面板和網(wǎng)格線,還有坐標軸標度宰掉、文本和標題:

theme_set(theme_custom())

ggplot(chic, aes(x = date, y = temp, color = factor(season))) + 
  geom_point() + labs(x = "Year", y = "Temperature (°F)") + guides(color = F)
image.png

這種改變繪圖設(shè)計的方式值得大力推薦呵哨。因為它讓你能快速一次性改變繪圖的任何元素。 在數(shù)秒內(nèi)讓你的結(jié)果符合恰當(dāng)?shù)臉邮讲M足其它任何需求(例如有更大字體大小用于演示或期刊需要)轨奄。

也可以通過theme_update()快速進行設(shè)置:

theme_custom <- theme_update(panel.background = element_rect(fill = "gray60"))

ggplot(chic, aes(x = date, y = temp, color = factor(season))) + 
  geom_point() + labs(x = "Year", y = "Temperature (°F)") + guides(color = F)
image.png

出于聯(lián)系目的孟害,我們用自己的主題,使用白色填充和不帶有白色的小網(wǎng)格線:

theme_custom <- theme_update(panel.background = element_rect(fill = "white"),
                             panel.grid.major = element_line(size = 0.5),
                             panel.grid.minor = element_blank())

Working with Colors(顏色)

對于簡單應(yīng)用顏色在ggplot2中是直接的挪拟,但是當(dāng)你有更高級的需求時纹坐,可能會遇到挑戰(zhàn)。對更高級的處理顏色的主題可以翻閱Hadley’s book 舞丛,這本書涵蓋了很好的內(nèi)容耘子。也有幾個其它的好資源包括 R Cookbookggplot2 online docs。哥倫比亞的 Tian Zheng 創(chuàng)建了實用性的 PDF of R colors.

為了用你的數(shù)據(jù)使用顏色球切,對重要的是需要指導(dǎo)你是否正在處理分類或連續(xù)性的變量谷誓。

Categorical Variables: Manually Select Colors(分類變量:手動選擇顏色)

(g <- ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
        geom_point() + 
        labs(x = "Year", y = "Temperature (°F)") +
        theme(legend.title = element_blank()) +
        scale_color_manual(values = c("dodgerblue4", "darkolivegreen4", 
                                      "darkorchid3", "goldenrod1")))
image.png

Categorical Variables: Use Built-In Palettes(分類變量:使用內(nèi)置的調(diào)色板)

可以用ColorBrewer palettes ,通過 scale_*_brewer吨凑,這是ggplot2包內(nèi)置的函數(shù):

g + scale_color_brewer(palette = "Set1")
image.png

可以忽略程序前臺的信息捍歪,替換已有的標度為我們想要的。

Categorical Variables: Use Tableau colors(分類變量鸵钝,使用Tableau顏色)

Tableau是著名的可視化軟件糙臼,帶有為人熟知的調(diào)色板。對R的用戶恩商,可以通過 ggthemes的命令 scale_color_tableau()獲得:

library(ggthemes)
g + scale_color_tableau()
image.png

Continuous Variables: Default Color Schemes(連續(xù)性變量:默認的顏色方案)

本例中变逃,我們要改變變量,把顏色賦予ozone怠堪,它是一個連續(xù)性的變量揽乱,同溫度強相關(guān)(higher temperature = higher ozone)名眉。函數(shù)scale_color_gradient()是一個連續(xù)性的梯度,而scale_color_gradient2()是另一個分支凰棉。

這是默認的ggplot2連續(xù)顏色方案 (sequential color scheme):

ggplot(chic, aes(x = date, y = temp, color = o3)) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") +
  scale_color_continuous("Ozone:")
image.png

此代碼繪同樣的圖:

ggplot(chic, aes(x = date, y = temp, color = o3)) +  
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") +
  scale_color_gradient()

這里是另一個默認的顏色方案:

ggplot(chic, aes(x = date, y = temp, color = o3)) +  
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") +
  scale_color_gradient2()
image.png

Continuous Variables: Manually Set a Sequential Color Scheme(連續(xù)性變量:手動設(shè)置連續(xù)顏色方案)

梯度改變的顏色板被用于連續(xù)性變量损拢,可以通過手動設(shè)置scale_*_gradient:

ggplot(chic, aes(x = date, y = temp, color = o3)) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") +
  scale_color_gradient(low = "darkkhaki", high = "darkgreen", "Ozone:")
image.png

溫度數(shù)據(jù)是正態(tài)分布的,因此使用對比性大的顏色方案會怎樣呢(不是連續(xù)性的顏色)撒犀。使用
scale_color_gradient2函數(shù)用于diverging顏色:

mid <- max(chic$o3) / 2  # or mid <- mean(chic$o3)

ggplot(chic, aes(x = date, y = temp, color = o3)) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") + 
  scale_color_gradient2(midpoint = mid, low = "blue4", 
                        mid = "white", high = "red4", "Ozone:")
image.png

Continuous Variables: The Beautiful Viridis Color Palette(連續(xù)性變量:美麗的翡翠調(diào)色板)

viridis color palettes 不僅是你的圖形更漂亮和易于理解福压,還可以使色盲者易于閱讀和以灰色的進行打印。你可以用 dichromate測試在色盲適用的各種形式下你繪圖是怎樣的外觀或舞。
如下多面板的圖形展示了4個翡翠調(diào)色板中的兩個:

g <- ggplot(chic, aes(x = date, y = temp, color = o3)) + 
       geom_point() + 
       labs(x = "Year", y = "Temperature (°F)")

library(viridis)
p1 <- g + scale_color_viridis("Ozone:") + ggtitle("'viridis' (default)")
p2 <- g + scale_color_viridis(option = "inferno", "Ozone:") + ggtitle("'inferno'")
p3 <- g + scale_color_viridis(option = "cividis", "Ozone:") + ggtitle("'cividis'")

library(patchwork)
(p1 + p2 + p3) * theme(legend.position = "bottom")
image.png

將翡翠調(diào)色板用于非連續(xù)的變量也是可能的荆姆。

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.title = element_blank()) +
  scale_color_viridis(discrete = T, end = 1)
image.png

Working with Lines(線條)

Add Horizonal or Vertical Lines to a Plot(為圖形添加水平或垂直的線)

你可能想強調(diào)給定的范圍或閾值,使用geom_hline()(對于水平線) 或者 geom_vline()(用于垂直線)嚷那,在給定的坐標位置繪制一條線 :

ggplot(chic, aes(x = date, y = temp, color = o3)) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") + 
  geom_hline(yintercept = c(0, 73))
image.png

如果你想非0或1位置添加一條斜線胞枕,需用用到'geom_abline()`杆煞。這里是一個例子魏宽,用于添加回歸線。

reg <- lm(o3 ~ temp, data = chic)
ggplot(chic, aes(x = temp, y = o3)) +
  geom_point(alpha = 0.5) +
  labs(caption = paste0("y = ", round(coefficients(reg)[2], 2), 
                        " * x + ", round(coefficients(reg)[1], 2)), 
       x = "Temperature (°F)", y = "Ozone") + 
  geom_abline(intercept = coefficients(reg)[1], slope = coefficients(reg)[2], 
              color = "darkorange2", size = 1.5)
image.png

隨后决乎,我們將學(xué)習(xí)怎樣用命令添加線性擬合線队询,用`stat_smooth(method = "lm")。但是构诚,可能有其它原因讓我們添加一條給定斜率的的線蚌斩。

Working with Text(文本)

Add Labels to Your Data(為你的數(shù)據(jù)添加標簽)

有時,我們想為我們的數(shù)據(jù)點添加標簽范嘱。為避免文本標簽重疊或擁擠送膳,使用1%原始數(shù)據(jù)抽樣,均等代表四個季節(jié)丑蛤。

set.seed(1)

library(tidyverse)
sample <- chic %>% 
  dplyr::group_by(season) %>% 
  dplyr::sample_frac(0.01)

## code without pipes: 
## sample <- sample_frac(group_by(chic, season), 0.01)

chic %>% 
  group_by(season) %>% 
  sample_frac(0.01) %>% 
  ggplot(aes(x = date, y = temp, label = season)) +
    geom_point() + 
    geom_text(aes(color = factor(temp)), hjust = 0.5, vjust = -0.5) +
    labs(x = "Year", y = "Temperature (°F)") +
    xlim(as.Date(c('1997-01-01', '2000-12-31'))) + 
    ylim(c(0, 90)) +
    theme(legend.position = "none")
image.png

好吧叠聋,避免標簽擁擠看起來不work。別擔(dān)心受裹,我們馬上就解決碌补。
可以用'geom_label '框圖:

ggplot(sample, aes(x = date, y = temp, label = season)) +
  geom_point() + 
  geom_label(aes(fill = factor(temp)), color = "white", 
             fontface = "bold", hjust = 0.5, vjust = -0.25) +
  labs(x = "Year", y = "Temperature (°F)") +
  xlim(as.Date(c('1997-01-01', '2000-12-31'))) +
  ylim(c(0, 90)) +
  theme(legend.position = "none")

image.png

很酷的一個包是ggrepel,它 為ggplot2提供了geoms以強制以上例子中重疊的標簽分離棉饶。這里厦章,我們展示了兩者,原始的數(shù)據(jù)和我們帶標簽的抽樣數(shù)據(jù):

library(ggrepel)
ggplot(chic, aes(x = date, y = temp, label = season)) +
  geom_point(alpha = 0.5) +
  geom_point(data = sample, aes(color = factor(temp)), size = 2.5) +
  geom_label_repel(data = sample, aes(fill = factor(temp)), 
                   color = "white", fontface = "bold") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.position = "none")
image.png

對于純文本標簽照藻,使用 geom_text_repel同樣奏效袜啃。看一下所有的例子 usage examples.

Add Text Annotation in the Top-Right, Top-Left etc.(在上右邊幸缕,上左等加入文本注釋)

ggplot2 可以為 Inf 設(shè)置注釋坐標囊骤,但是用處有限晃择。這里是一個例子 (基于代碼this Google group) 用grid 基于坐標標度來指定位置。0是最低也物,1是最高的位置宫屠。

grobTree函數(shù)來自于 grid 包,可以創(chuàng)建網(wǎng)格圖形對象滑蚯,textGrob 創(chuàng)建文本圖形對象。 annotation_custom() 函數(shù)來自于 ggplot2 滑绒,設(shè)計用grob作為輸入管钳。

library(grid)
my_grob <- grobTree(textGrob("This text stays in place!", 
                             x = 0.1, y = 0.9, hjust = 0, 
                             gp = gpar(col = "black", 
                                       fontsize = 15, 
                                       fontface = "bold")))

ggplot(chic, aes(x = temp, y = o3)) +
  geom_point(color = "tan", alpha = 0.5) + 
  labs(x = "Temperature (°F)", y ="Ozone") +
  annotation_custom(my_grob)
image.png

在你有很多圖有不同的標度時焰手,這個函數(shù)的作用尤其冥想。如下你看到的圖中史侣,坐標軸的范圍有很大變化,上面同樣的代碼能用于在每個分圖上同樣的位置添加注釋。

ggplot(chic, aes(x = temp, y = o3)) +
  geom_point(color = "tan") + 
  labs(x = "Temperature (°F)", y ="Ozone") +
  facet_wrap(~ season, scales = "free") +
  annotation_custom(my_grob)
image.png

Working with Coordinates(標度)

Flip a Plot(翻轉(zhuǎn)圖像)

以圖形的邊翻轉(zhuǎn)圖像非常容易實現(xiàn)钝吮。在此我們引入coord_flip(),需要它來翻轉(zhuǎn)圖像(順便轴踱,我們用 geom_boxpot()來繪制新的圖形嘁傀。

ggplot(chic, aes(x = season, y = o3)) +
  geom_boxplot(fill = "indianred") + 
  labs(x = "Season", y = "Ozone") +
  coord_flip()
image.png

Reverse an Axis(翻轉(zhuǎn)坐標軸)

分別使用scale_x_reverse()scale_y_reverse()很容易實現(xiàn)坐標軸翻轉(zhuǎn):

ggplot(chic, aes(x = date, y = temp, color = o3)) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") + 
  scale_y_reverse()
image.png

Transform an Axis(坐標軸轉(zhuǎn)換)

… 使用scale_y_log10()scale_y_sqrt()轉(zhuǎn)換默認的線性繪圖瓤狐。例如如贷,在此用 log10-轉(zhuǎn)換坐標軸(注意婿屹,會引入NA):

ggplot(chic, aes(x = date, y = temp, color = o3)) + 
  geom_point() + 
  labs(x = "Year", y = "Temperature (°F)") + 
  scale_y_log10(lim = c(0.1, 100))
image.png

Circularize a Plot(環(huán)形繪圖)

通過 coord_polar讓坐標系統(tǒng)成環(huán)形是可以滴(極性圖)溢十。

library(tidyverse)

chic %>% 
  dplyr::group_by(season) %>% 
  dplyr::summarize(o3 = median(o3)) %>% 
  ggplot(aes(x = season, y = o3)) +
    geom_col(aes(fill = factor(season))) + 
    labs(x = "", y = "Median Ozone Level") +
    coord_polar() +
    guides(fill = F)
image.png

此坐標系統(tǒng)可以畫餅圖:

chic %>% 
  dplyr::mutate(o3_avg = median(o3)) %>% 
  dplyr::filter(o3 > o3_avg) %>% 
  dplyr::mutate(n_all = n()) %>% 
  dplyr::group_by(season) %>% 
  dplyr::summarize(rel = n() / unique(n_all)) %>% 
  ggplot(aes(x = "", y = rel)) +
    geom_col(aes(fill = factor(season)), width = 1) + 
    labs(x = "", 
         y = "Proportion of Days Exceeding\nthe Median Ozone Level") +
    coord_polar("y") +
    scale_fill_brewer(palette = "Set1", name = "Season:") +
    theme(axis.ticks = element_blank())
image.png

Working with Chart Types(圖形)

Alternatives to a Box Plot(方框圖的替代圖)

方框圖是很好的,但是可能特讓人厭煩羡铲。有好幾種替代的圖形磕昼,但首先讓我們畫一個普通的方框圖:

image

有效性? Yes.
趣味性? No.

1. Alternative: Plot of Points(替代圖形:繪制點圖)

讓我們用原始數(shù)據(jù)繪制每個數(shù)據(jù)點:

g + geom_point(color = "firebrick")
image

不僅讓人煩鸟廓,而且沒有提供有用的信息。為了改進圖形贮预,可以增加透明度來處理重疊點:

g + geom_point(color = "firebrick", alpha = 0.1)
image.png

然而贝室,這里設(shè)了透明度也不行,因為重疊依然嚴重仿吞,高值或極值仍然不可見滑频。糟糕了,來試試其它方法唤冈。

2. Alternative: Jitter the Points(替代圖形:點的抖動)

試著為數(shù)據(jù)添加一些抖動峡迷。我超愛這個內(nèi)部的可視化,但需要注意你虹,人為添加的抖動增加了數(shù)據(jù)的噪音绘搞,可能導(dǎo)致數(shù)據(jù)的誤導(dǎo)。

g + geom_jitter(aes(color = season), alpha = 0.25, 
                position = position_jitter(width = 0.3)) +
    theme(legend.position = "none")
image.png

3. Alternative: Violin Plots(替代圖形:小提琴圖)

小提琴圖通過方框圖類似傅物,其突出優(yōu)勢是用核密度來展示最多的數(shù)據(jù)夯辖,這是一種有益的可視化圖形。

g + geom_violin(color = "sienna", fill = "red", alpha = 0.4)
image.png

4. Alternative: Combining Violin Plots with Jitter(替代圖形:小提琴圖和抖動合體)

當(dāng)然可以組合使用兩者董饰,同時估計密度和有原始數(shù)據(jù)點:

g + geom_violin(aes(color = season), fill = "gray80", alpha = 0.5) +
    geom_jitter(aes(color = season), alpha = 0.25, 
                position = position_jitter(width = 0.3)) +
    theme(legend.position = "none") +
    coord_flip()

image.png

ggforce 提供了所謂的sina 函數(shù)蒿褂,抖動的寬度可以通過數(shù)據(jù)的密度來控制圆米,可是讓抖動圖更具視覺吸引力:

library(ggforce)

g + geom_violin(aes(color = season), fill = "gray80", alpha = 0.5) +
    geom_sina(aes(color = season), alpha = 0.25) +
    theme(legend.position = "none") +
    coord_flip()
image.png

5. Alternative: Combining Violin Plots with Box Plots(替代圖形:小提琴圖和框型圖合體)

為了易于估計分位數(shù),可以為小提琴圖內(nèi)部添加框型圖啄栓,用于指示25%分位數(shù)榨咐、中位數(shù)和75%分位數(shù):

g + geom_violin(aes(fill = season), color = "transparent", alpha = 0.5) +
    geom_boxplot(outlier.alpha = 0, coef = 0, 
                 color = "gray40", width = 0.1) +
    theme(legend.position = "none") +
    coord_flip()
image.png

Create a Rug Representation to a Plot(為圖形添加地毯圖形)

地毯表示單一定量變量的數(shù)據(jù),表現(xiàn)形式是沿著坐標軸的標記谴供。多數(shù)情況下块茁,用于散點圖或熱圖來展示一個或兩個變量的整體分布:

ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  geom_rug() +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.position = "none")
image.png
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
  geom_point() +
  geom_rug(sides = "r", alpha = 0.3) +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.position = "none")
image.png

Create a Tiled Correlation Plot(繪制瓦片相關(guān)圖)

第一步是建立相關(guān)矩陣。我們用Pearson相關(guān)性桂肌,因為所有的變量都是相當(dāng)?shù)恼龖B(tài)分布(但是可以用Spearman系數(shù)数焊,如果變量遵循不同的分布模式) 。注意因為相關(guān)矩陣有冗余的信息崎场,我們設(shè)置它的一半為 NA佩耳。

corm <- round(cor(chic[ , sort(c("death", "temp", "dewpoint", "pm10", "o3"))], 
                  method = "pearson", use = "pairwise.complete.obs"), 2)
corm[lower.tri(corm)] <- NA
corm
##          death dewpoint    o3 pm10  temp
## death        1    -0.47 -0.24 0.00 -0.49
## dewpoint    NA     1.00  0.45 0.33  0.96
## o3          NA       NA  1.00 0.21  0.53
## pm10        NA       NA    NA 1.00  0.37
## temp        NA       NA    NA   NA  1.00

現(xiàn)在我們用 reshape2包的melt函數(shù),把矩陣變?yōu)?long 形式谭跨,丟掉 NA 值的記錄:

library(reshape2)
corm <- melt(corm)
corm$Var1 <- as.character(corm$Var1)
corm$Var2 <- as.character(corm$Var2)
corm <- na.omit(corm)
head(corm, 10)
##        Var1     Var2 value
## 1     death    death  1.00
## 6     death dewpoint -0.47
## 7  dewpoint dewpoint  1.00
## 11    death       o3 -0.24
## 12 dewpoint       o3  0.45
## 13       o3       o3  1.00
## 16    death     pm10  0.00
## 17 dewpoint     pm10  0.33
## 18       o3     pm10  0.21
## 19     pm10     pm10  1.00

畫圖我們用 geom_tile干厚,但是如你有很多數(shù)據(jù),可以考慮用geom_raster螃宙,它會更快蛮瞄。

ggplot(corm, aes(x = Var2, y = Var1)) +
   geom_tile(data = corm, aes(fill = value), color = "white") +
   labs(x = "Variable 2", y = "Variable 1") +
   scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
                        midpoint = 0, limit = c(-1, 1), 
                        name = "Correlation\n(Pearson)") +
   theme(axis.text.x = element_text(angle = 45, size = 11, 
                                    vjust = 1, hjust = 1)) +
   coord_equal()
image

Create a Contour Plot(畫登高線圖)

等高線圖是展示三維數(shù)據(jù)的好方法,可以指明數(shù)值的末端閾值谆扎。在此挂捅,我們用露點數(shù)據(jù)畫圖(也就是 空氣中的水蒸氣凝結(jié)成液態(tài)錄水的溫度), 與溫度和臭氧的濃度有關(guān):

## interpolate data
library(akima)
fld <- with(chic, interp(x = temp, y = o3, z = dewpoint))

## prepare data in long format
library(reshape2)
df <- melt(fld$z, na.rm = T)
names(df) <- c("x", "y", "Dewpoint")
df$Temperature <- fld$x[df$x]
df$Ozone <- fld$y[df$y]

g <- ggplot(data = df, aes(x = Temperature, y = Ozone, z = Dewpoint)) +
         theme(panel.background = element_rect(fill = "white"),
               panel.border = element_rect(color = "black", fill = NA),
               legend.title = element_text(size = 15),
               axis.text = element_text(size = 12),
               axis.title.x = element_text(size = 15, vjust = -0.5),
               axis.title.y = element_text(size = 15, vjust = 0.2),
               legend.text = element_text(size = 12))
         
g + stat_contour(aes(color = ..level.., fill = Dewpoint))
image.png

震驚了! 如其定義堂湖,露點多數(shù)情況下等于測量溫度闲先。

這些線表示的是不同的露點水平,但這不是一個靚圖无蜂,由于缺少邊界也難以閱讀伺糠。讓我們試著畫一個瓦片圖,用 viridis調(diào)色板編碼露點的臭氧水平和溫度組合:

g + geom_tile(aes(fill = Dewpoint)) +
    scale_fill_viridis(option = "inferno")
image.png

讓等高線圖和瓦片圖合體斥季,在登高線下填充這些區(qū)域會怎樣呢训桶?

g + geom_tile(aes(fill = Dewpoint)) + 
    stat_contour(color = "white", size = 0.7, bins = 5) + 
    scale_fill_viridis()
image.png

Create a Joyplot aka Ridge Plot(一種波濤洶涌,哦不對,是山峰疊巒的可視化方式)

山峰疊巒Joyplots (亦稱之為 屋脊(線)圖)是一種新型的圖形,此刻很流行泻肯。 (有趣的事實: 名字參考Joy Division’s “Unknown Pleasures” LP.封面)

你可以用 基本 ggplot 命令 繪圖渊迁,此圖的流行的后果就是有人寫了一個包,更加容易繪制此類圖形: ggridges. 這里我們用一下這個包灶挟。

library(ggridges)
ggplot(chic, aes(x = temp, y = factor(year))) + 
   geom_density_ridges(fill = "gray90") +
   labs(x = "Temperature (°F)", y = "Year")

image.png

使用參數(shù) rel_min_heightscale`分別易于區(qū)分重疊和拖尾。這個包帶有自己的主題(但是我更愿意自己造個輪子毒租,見“Create and Use Your Custom Theme”)稚铣。另外箱叁,我們基于年度來變更顏色,使圖形更具吸引力惕医。

ggplot(chic, aes(x = temp, y = factor(year), fill = year)) + 
  geom_density_ridges(alpha = 0.8, color = "white", 
                      scale = 2.5, rel_min_height = 0.01) + 
  labs(x = "Temperature (°F)", y = "Year") + 
  guides(fill = F) + 
  theme_ridges()
image.png

也能用scaling參數(shù)值小于1耕漱,來去除重疊(但是這個有悖于山峰疊巒的本意)。這是一個例子抬伺,用viridis調(diào)色板:

ggplot(chic, aes(x = temp, y = season, fill = ..x..)) + 
  geom_density_ridges_gradient(scale = 0.9, gradient_lwd = 0.5, 
                               color = "black") + 
  scale_fill_viridis(option = "plasma", name = "") + 
  labs(x = "Temperature (°F)", y = "Season:") +
  theme_ridges(font_family = "Roboto Condensed", grid = F)
image.png

也可以比較每個山峰疊巒線的幾個組螟够,根據(jù)他們的組別來上色。這個剽竊了 Marc Belzunces的思路峡钓。

library(tidyverse)

## only plot extreme season using dplyr from the tidyverse
ggplot(data = filter(chic, season %in% c("Summer", "Winter")), 
         aes(x = temp, y = year, fill = paste(year, season))) +
  geom_density_ridges(alpha = 0.7, rel_min_height = 0.01, 
                      color = "white", from = -5, to = 95) +
  scale_fill_cyclical(breaks = c("1997 Summer", "1997 Winter"),
                      labels = c(`1997 Summer` = "Summer", 
                                 `1997 Winter` = "Winter"),
                      values = c("tomato", "dodgerblue"),
                      name = "Season:", guide = "legend") +
  theme_ridges(font_family = "Roboto Condensed") + 
  labs(x = "Temperature (°F)", y = "Year")

image.png

ggridges包 在geom_density_ridges命令中用 stat = "binline" 創(chuàng)建直方圖是有用的:

ggplot(chic, aes(x = temp, y = factor(year), fill = year)) + 
  geom_density_ridges(stat = "binline", bins = 25, scale = 0.9, 
                      draw_baseline = F, show.legend = F) + 
  theme_ridges(font_family = "Roboto Condensed") +
  labs(x = "Temperature (°F)", y = "Season")
image.png

Working with Ribbons (AUC, CI, etc.)(絲帶圖)

展示絲帶圖的數(shù)據(jù)不是非常理想妓笙,但是絲帶圖非常有用。此例中能岩,我們將用filter()函數(shù)繪制一個30天的動態(tài)平均寞宫,以便讓我們的絲帶的噪音不會太多。

chic$o3run <- as.numeric(stats::filter(chic$o3, rep(1/30, 30), sides = 2))

ggplot(chic, aes(x = date, y = o3run)) +
   geom_line(color = "chocolate", lwd = 0.8) +
   labs(x = "Year", y = "Temperature (°F)")
image

如果我們用geom_ribbon()函數(shù)為曲線下的區(qū)域添充拉鹃,看起來會如何呢辈赋?

ggplot(chic, aes(x = date, y = o3run)) +
   geom_ribbon(aes(ymin = 0, ymax = o3run), fill = "orange", 
               color = "orange", alpha = 0.4) +
   geom_line(color = "chocolate", lwd = 0.8) +
   labs(x = "Year", y = "Temperature (°F)")
image.png

很好表明了曲線下面積 area under the curve (AUC),但是這不是 geom_ribbon()的經(jīng)典實用方式膏燕。替代方法是钥屈,我們繪制一條絲帶,在我們數(shù)據(jù)的上下添加標準差:

chic$mino3 <- chic$o3run - sd(chic$o3run, na.rm = T)
chic$maxo3 <- chic$o3run + sd(chic$o3run, na.rm = T)

ggplot(chic, aes(x = date, y = o3run)) +
   geom_ribbon(aes(ymin = mino3, ymax = maxo3), alpha = 0.5, 
               fill = "darkseagreen3", color = "transparent") +
   geom_line(color = "aquamarine4", lwd = 0.7) +
   labs(x = "Year", y = "Temperature (°F)")
image.png

Working with Smoothings(平滑線)

實用ggplot2為數(shù)據(jù)添加平滑線易如反掌坝辫。

Default: Adding a LOESS or GAM Smoothing(默認方式:添加LOESS或GAM平滑線)

簡單實用stat_smooth() – 甚至都不用公式焕蹄。如果數(shù)據(jù)少于1000個點,這個添加了LOESS 線(局部權(quán)重的散點平滑線阀溶,method = "loess") 或者 GAM線 (廣義加法模型, method = "gam") 腻脏。由于我們點多于1000個,平滑線基于GAM银锻。

ggplot(chic, aes(x = date, y = temp)) + 
  geom_point(color = "gray40", alpha = 0.5)+
  labs(x = "Year", y = "Temperature (°F)") +
  stat_smooth()
image.png

Specifying the Formula for Smoothing(為平滑線定義公式)

ggplot2 讓你可以想用的方式定義模型永品。比如增加GAM的維度(為平滑線加入一些其他額外的起伏):

ggplot(chic, aes(x = date, y = temp)) + 
   geom_point(color = "gray40", alpha = 0.3) +
   labs(x = "Year", y = "Temperature (°F)") +
   stat_smooth(method = "gam", formula = y ~ s(x, k = 1000), 
               se = F, size = 1.3, aes(col = "1000")) +
   stat_smooth(method = "gam", formula = y ~ s(x, k = 100), 
               se = F, size = 1, aes(col = "100")) +
   stat_smooth(method = "gam", formula = y ~ s(x, k = 10), 
               se = F, size = 0.8, aes(col = "10")) +
   scale_color_manual(name = "k", values = c("darkorange2", 
                                             "firebrick", 
                                             "dodgerblue3"))
image.png

Adding a Linear Fit(加入線性擬合)

雖然默認的是 LOESS或GAM平滑線,添加標準的線性擬合也相當(dāng)容易 :

ggplot(chic, aes(x = temp, y = death)) +
   geom_point(color = "gray40", alpha = 0.5) +
   labs(x = "Temperature (°F)", y = "Deaths") +
   stat_smooth(method = "lm", col = "firebrick", se = F, size = 1.3)
image

Working with Interactive Plots(交互繪圖)

Shiny

Shiny是RStudio的一個包击纬,使得用R創(chuàng)建交互網(wǎng)絡(luò)應(yīng)用非常便捷鼎姐,介紹和實例,見 Shiny homepage.

瀏覽一下潛在用途更振,可以看Hello Shiny例子炕桨。這是第一個:

Plot.ly

Plot.ly 可以用你的ggplot2很容易創(chuàng)建在線的交互圖形。過程相當(dāng)容易肯腕,用R就可以實現(xiàn)献宫。

Remarks, Tipps & Tricks(備注、提示和技巧)

Using ggplot2 in Loops and Functions(在循環(huán)和函數(shù)中用ggplot2)

基于網(wǎng)格的圖形函數(shù)lattice和ggplot2中創(chuàng)建圖形對象实撒。 當(dāng)你在命令行交互使用這些函數(shù)時姊途,結(jié)果就會自動打印涉瘾,但是在 source()或你自己的函數(shù)中,需要明確聲明print(), i.e. 在我們的例子中的print(g) 捷兰。也見 Q&A page of R.

其它資源

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末立叛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贡茅,更是在濱河造成了極大的恐慌秘蛇,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顶考,死亡現(xiàn)場離奇詭異赁还,居然都是意外死亡,警方通過查閱死者的電腦和手機村怪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門秽浇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人甚负,你說我怎么就攤上這事柬焕。” “怎么了梭域?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵斑举,是天一觀的道長。 經(jīng)常有香客問我病涨,道長富玷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任既穆,我火速辦了婚禮赎懦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘幻工。我一直安慰自己励两,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布囊颅。 她就那樣靜靜地躺著当悔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪踢代。 梳的紋絲不亂的頭發(fā)上盲憎,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音胳挎,去河邊找鬼饼疙。 笑死,一個胖子當(dāng)著我的面吹牛串远,可吹牛的內(nèi)容都是我干的宏多。 我是一名探鬼主播儿惫,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼澡罚,長吁一口氣:“原來是場噩夢啊……” “哼伸但!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起留搔,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤更胖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后隔显,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體却妨,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年括眠,在試婚紗的時候發(fā)現(xiàn)自己被綠了彪标。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掷豺,死狀恐怖捞烟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情当船,我是刑警寧澤题画,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站德频,受9級特大地震影響苍息,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壹置,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一竞思、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钞护,春花似錦盖喷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至步藕,卻和暖如春惦界,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咙冗。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工沾歪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雾消。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓灾搏,卻偏偏與公主長得像挫望,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子狂窑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

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