玩转数据可视化之R语言ggplot2
- 🌸个人主页:JoJo的数据分析历险记
- 📝个人介绍:小编大四统计在读,目前保研到统计学top3高校继续攻读统计研究生
本系列主要介绍R语言ggplot2的使用
参考资料:
ggplot2: Elegant Graphics for Data Analysis
文章目录
- 玩转数据可视化之R语言ggplot2
- 💘2.玩转数据可视化之R语言ggplot2:(二)实现分面画图(Faceting)
- 💕2.1 Facet wrap
- 💖2.2 Facet grid
- 💗2.3 坐标轴刻度控制
- 💙2.4 缺失数据分面
- 💚2.5 分组和分面
- 💜2.6 连续变量
💘2.玩转数据可视化之R语言ggplot2:(二)实现分面画图(Faceting)
# 加载库
library(ggplot2)
首先我们来看一个简单的分面案例,使用数据集mpg,按照class分面画displ和hwy的散点图,使用facet_wrap()函数进行分面,通过~来指定选择分面的变量
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(~class)
分面其实就是将数据集分为一部分子集,对每个子集进行绘图,并放在同一张图上。这在我们进行探索性数据分析时很有用,我们
可以分析不同图之间有什么相同点和不同点.faceting主要有以下三种方法
- facet_null()
- facet_wrap():对一个变量进行分面
- facet_gird():分别从行和列对两个变量进行分面
facet_wrap()和facet_grid()的区别如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z9mf84za-1649326423002)(attachment:image.png)]
为了使得方便描述,我们在这里使用mpg的子集,cyl取值三个水平4,6,8.drv取值两个水平4,f.class不等于2seater的
mpg2 <- subset(mpg, cyl != 5 & drv %in% c("4", "f") & class != "2seater")
head(mpg2)
A tibble: 6 × 11
manufacturer | model | displ | year | cyl | trans | drv | cty | hwy | fl | class |
<chr> | <chr> | <dbl> | <int> | <int> | <chr> | <chr> | <int> | <int> | <chr> | <chr> |
audi | a4 | 1.8 | 1999 | 4 | auto(l5) | f | 18 | 29 | p | compact |
audi | a4 | 1.8 | 1999 | 4 | manual(m5) | f | 21 | 29 | p | compact |
audi | a4 | 2.0 | 2008 | 4 | manual(m6) | f | 20 | 31 | p | compact |
audi | a4 | 2.0 | 2008 | 4 | auto(av) | f | 21 | 30 | p | compact |
audi | a4 | 2.8 | 1999 | 6 | auto(l5) | f | 16 | 26 | p | compact |
audi | a4 | 2.8 | 1999 | 6 | manual(m5) | f | 18 | 26 | p | compact |
💕2.1 Facet wrap
facet_wrap()绘制一系列图片在一张画布上。根据某一变量的不同取值进行绘制子图。
当某一单独的变量有不同水平时,我们研究不同水平下某些其他变量的关系,此时适合用face_wrap()
facet_warp主要有以下参数:
- ncol和nrow,控制绘制几列几行的图,设置其中一个变量即可
- as.table.是否像一个表一样显示图(最高值在右下角),false(最高值在右上角)
- dir.控制绘图的方向,水平(h)还是纵向(v)
p <- ggplot(mpg2, aes(displ, hwy)) +
geom_blank() + #绘制空图
xlab(NULL) +
ylab(NULL)
p + facet_wrap(~class, ncol = 3)
p + facet_wrap(~class, ncol = 3, as.table = FALSE)#默认是true
下面来看看dir参数
p + facet_wrap(~class, nrow = 3)
p + facet_wrap(~class, nrow = 3, dir = "v")
💖2.2 Facet grid
facet_grid()是画一个二维的分面图,有两个变量进行分面
- .~a是按列进行分面
- b~.是按行进行分面
- a~b按两个变量进行分面
在这里就不再需要指定row和col了
p + facet_grid(. ~ cyl)
p + facet_grid(drv ~ .)
p + facet_grid(drv ~ cyl)
💗2.3 坐标轴刻度控制
在facet_wrap()和facet_grid()中都可以设置是否共用坐标轴刻度,使用scales参数进行设置
- scales = ‘fixed’:x和y轴坐标轴刻度都固定
- scales = ‘free_x’:x坐标轴刻度根据数据可以变换
- scales = ‘free_y’:y坐标轴刻度根据数据变化
- scalse = ‘free’:x和y坐标轴都根据数据变化
facet_grid()有一个额外的限制:在同一列的图x轴必须相同,在同一行的图y轴必须相同
p <- ggplot(mpg2, aes(cty, hwy)) +
geom_abline()+
geom_jitter(width = 0.1, height = 0.1)
p + facet_wrap(~cyl)
p + facet_wrap(~cyl, scales = "free")
当我们想在时间序列显示多个不同尺度的变量时,使用scales也很有效
# 如果不适用scale
ggplot(economics_long, aes(date, value)) +
geom_line() +
facet_wrap(~variable, ncol=1)
从图中可以看出有些变量我们没办法得到具体随时间变化趋势
ggplot(economics_long, aes(date, value)) +
geom_line() +
facet_wrap(~variable, scales = "free_y",ncol=1)
facet_grid()还有一个额外的参数是space,如果space为free,则每一个图的大小会根据其范围自动按比例调整
例如,图a的范围是0-2,图b的范围是0-4,那么在画图的时候,我们会分配1/3的空间给a,2/3的空间给b
head(mpg2)
A tibble: 6 × 11
manufacturer | model | displ | year | cyl | trans | drv | cty | hwy | fl | class |
<fct> | <fct> | <dbl> | <int> | <int> | <chr> | <chr> | <int> | <int> | <chr> | <chr> |
audi | a4 | 1.8 | 1999 | 4 | auto(l5) | f | 18 | 29 | p | compact |
audi | a4 | 1.8 | 1999 | 4 | manual(m5) | f | 21 | 29 | p | compact |
audi | a4 | 2.0 | 2008 | 4 | manual(m6) | f | 20 | 31 | p | compact |
audi | a4 | 2.0 | 2008 | 4 | auto(av) | f | 21 | 30 | p | compact |
audi | a4 | 2.8 | 1999 | 6 | auto(l5) | f | 16 | 26 | p | compact |
audi | a4 | 2.8 | 1999 | 6 | manual(m5) | f | 18 | 26 | p | compact |
# 根据cty排序
mpg2$model <- reorder(mpg2$model, mpg2$cty)#升序
mpg2$manufacturer <- reorder(mpg2$manufacturer, -mpg2$cty) # 降序
ggplot(mpg2, aes(cty, model)) +
geom_point() +
facet_grid(manufacturer ~ ., scales = "free",space='free')+
theme(strip.text.y = element_text(angle = 0))
💙2.4 缺失数据分面
假设我们在分面的时候对多个数据集绘图,可能会出现某个数据集没有分面变量。这种情况发生时,ggplot默认将该数据集的数据在分面变量的每个值上都有。例如
df1 <- data.frame(x = 1:3, y = 1:3, gender = c("f", "f", "m"))
df2 <- data.frame(x = 2, y = 2)
ggplot(df1, aes(x, y)) +
geom_point(data = df2, colour = "red", size = 2) +
geom_point() +
facet_wrap(~gender)
由于df2没有gender变量,因此df的值在gender的两个取值上都有值
💚2.5 分组和分面
分面方法是使用不同美学特征(例如颜色、大小、形状等)来区分不同组的另一种选择。两种方法各有优劣/
通过颜色大小来区分时,容易出现一些绘图重叠的部分,而使用分面的话,由于分面的每一部分都是数据集的一小部分,
因此不会出现重叠的问题。下面举例说明这两种方法
使用颜色来区分不同组
df <- data.frame(
x = rnorm(120, c(0, 2, 4)),
y = rnorm(120, c(1, 2, 1)),
z = letters[1:3]
)
ggplot(df, aes(x, y)) +
geom_point(aes(colour = z))
ggplot(df, aes(x, y)) +
geom_point() +
facet_wrap(~z)
分面的一个优势是可以增加一些注释,例如我们可以在每个图中增加每一类的平均值,首先计算分组统计量
具体可以参考我的R语言数据分析专栏
# 计算分组统计量
library(dplyr)
df_sum <- df %>%
group_by(z) %>%
summarise(x = mean(x), y = mean(y)) %>%
rename(z2 = z)
ggplot(df, aes(x, y)) +
geom_point() +
geom_point(data = df_sum, aes(colour = z2), size = 4) +
facet_wrap(~z)
另外一个有用的技巧是将所有数据都放到图中的背景
# 首先定义一个新数据集,删除z
df2 <- select(df, -z)
ggplot(df, aes(x, y)) +
geom_point(data = df2, colour = "grey70") +
geom_point(aes(colour = z)) +
facet_wrap(~z,ncol=1)
💜2.6 连续变量
如果要对连续变量进行分面,首先要做到是将其离散化。ggplot2提供了以下三种方法:
- 将数据分为n个长度相同的桶:cut_interval(x,n)
- 将数据分为若干桶,桶的宽度用
width
参数:cut_width(x,width) - 将数据分为n桶,每一桶包含的数据量相同:cut_number(x,n=i)
# 设置桶宽为1
mpg2$disp_w <- cut_width(mpg2$displ, 1)
# 分为六桶
mpg2$disp_i <- cut_interval(mpg2$displ, 6)
# 设置每个桶6个数据
mpg2$disp_n <- cut_number(mpg2$displ, 6)
plot <- ggplot(mpg2, aes(cty, hwy)) +
geom_point() +
labs(x = NULL, y = NULL)
plot + facet_wrap(~disp_w, nrow = 1)
plot + facet_wrap(~disp_i, nrow = 1)
plot + facet_wrap(~disp_n, nrow = 1)