28 ggplot的各种图形 您所在的位置:网站首页 图例包括什么图形组成 28 ggplot的各种图形

28 ggplot的各种图形

2024-05-09 04:36| 来源: 网络整理| 查看: 265

28 ggplot的各种图形 28.1 介绍

ggplot2包提供了许多种图形, 其作用可以大致地分为:

表现数量; 表现一维或者二维分布; 表现两个变量之间的数量关系,等等。

下面按照其作用分别进行介绍。

主要参考:

Claus O. Wilke(2019). Fundamentals of Data Visualization. O’Reilly Media. https://serialmentor.com/dataviz/ 28.2 表现数量 28.2.1 条形图

设有若干个类, 每个类有一个数量属性值。 经常用条形图表现数量。

28.2.1.1 简单的条形图

例如, 有25个共同基金, 分为三个类别, 各类别的频数为:

d_funds_type mutate(type = fct_relevel( type, "国内股本", "国际股本", "固定收益")) |> ggplot(aes( x = type, y = freq )) + geom_col() + labs(x = NULL)

可以用forcats包的fct_reorder()函数或者用stats包的reorder()函数, 将因子水平按照某种有意义的次序排列。 下例用fct_reorder()函数将各个水平按照频数大小排序:

p setNames(c("社区", "性别", "频数")) knitr::kable(d_comm) 社区 性别 频数 A社区 男 9 B社区 男 10 C社区 男 13 D社区 男 4 A社区 女 18 B社区 女 7 C社区 女 8 D社区 女 11

现在数据中有两个分类变量, 频数是交叉分类的结果, 这样的数据称为“列联表”。 这时, 将两个分类变量中一个作为大类, 映射到x维度, 另一个作为小类, 映射到fill维度, 频数映射到y维度。 使用geom_col()或者geom_bar(stat = "identity")。 如:

ggplot(d_comm, aes( x = `性别`, fill = `社区`, y = `频数`)) + geom_col()

结果为堆叠的条形图, 每个大类画一个分段的条形, 条形的程度等于各段长度之和。 这需要各段长度之和相当于每个大类的某种总计, 对于频数,这当然是合理的, 每段长度每个交叉小类的频数, 而一个条形的总长度是一个大类的频数。 当y轴映射到其它指标时堆叠条形图不一定合适, 比如, 如果y映射到每个交叉小类的某个指标的标准差, 因为标准差的和并不是标准差, 所以就不能用堆叠条形图表示。

下面将社区作为大类,性别作为小类:

ggplot(d_comm, aes( x = `社区`, y = `频数`, fill = `性别`)) + geom_col()

在geom_col()和geom_bar()中加选项position = "dodge"可以将小类并列放置:

ggplot(d_comm, aes( x = `性别`, fill = `社区`, y = `频数`)) + geom_col(position = "dodge")

这样得到并列的条形图。 并列条形图就不需要像堆叠条形图那样要求各个小类的y轴变量和有意义。 堆叠条形图相当于在geom_col()中加position = "stack"。

也可以将不同的大类放置到不同的切片, 用facet_wrap()或者facet_grid()函数:

ggplot(d_comm, aes( x = `社区`, y = `频数`)) + geom_col() + facet_wrap(~ `性别`) + labs(x = NULL)

注意各切片默认使用相同的坐标范围。

28.2.1.3 百分数的条形图

对于只有一个分类变量的条形图, 如果y轴代表频数, 为了转换成比例或者百分比, 修改输入数据增加相应的变量, 如:

d_funds_type |> mutate( ratio = freq / sum(freq), `百分数` = 100*ratio) |> ggplot(aes( x = fct_relevel( type, "国内股本", "国际股本", "固定收益"), y = `百分数` )) + geom_col() + labs(x=NULL)

对于有两个分类变量的列联表, 如果希望y轴表现总百分数, 只要修改输入数据集增加分母为总数的百分数,如:

d_comm |> mutate(`百分数` = `频数` / sum(`频数`) * 100) |> ggplot(aes( x = `社区`, y = `百分数`, fill=`性别`)) + geom_col()

如果y轴希望表现每个大类内的百分数, 首先增加大类内的百分数, 比如下面的程序将社区居民调查数据按社区分为大类, 每个社区内计算不同性别的百分数:

d_comm |> group_by(`社区`) |> mutate(`百分数` = `频数` / sum(`频数`) * 100) |> ungroup() -> d

这样,与对频数作图类似就可以做堆叠条形图, 每个社区为一个大类, 每个大类总计100%:

ggplot(d, aes( x = `社区`, fill = `性别`, y = `百分数`)) + geom_col()

在geom_col()中加position = "dodge"可以变成并列条形图, 每个社区为一个大类, 每个大类中总计100%:

ggplot(d, aes( x = `社区`, fill = `性别`, y = `百分数`)) + geom_col(position = "dodge")

与前一章27.5.1中类似问题相比, 对表格数据做比例或者百分数条形图, 比基于原始数据直接用geom_bar()做图要简单而且不易出错。

28.2.1.4 直接标记数字的条形图

比较简单的条形图, 可以不使用y坐标轴而是对每个条形或者堆叠的每个段标出数字。 用geom_text()函数标数字。 如:

d_funds_type |> mutate(type = fct_relevel( type, "国内股本", "国际股本", "固定收益")) |> ggplot(aes( x = type, y = freq )) + geom_col(fill = "lightblue") + geom_text(mapping = aes( y = freq / 2, label = paste(freq))) + scale_y_continuous(breaks = NULL) + labs(x = NULL, y = NULL) + coord_flip()

上述程序中, 用了scale_y_continuous()的breaks = NULL选项使得y轴(经过对换后画在了x轴)不画刻度和刻度值。

堆叠的条形图用数字而非坐标轴的例子如下:

d_comm |> arrange(`性别`, desc(`社区`)) |> group_by(`性别`) |> mutate(ylabel = cumsum(`频数`) - 0.5*`频数`) |> ggplot(aes( x = `性别`, fill = `社区`, y = `频数`)) + geom_col() + geom_text(mapping = aes( y = ylabel, label = paste(`频数`) )) + scale_y_continuous(breaks = NULL) + labs(y = NULL)

上述程序中预先计算了每段的纵坐标值, 保存在变量ylabel中。 注意计算过程中的排序与分组操作。

28.2.2 点图

条形图的y轴一般都代表数量, 最小值从0开始, 一般不画y轴最小值大于0的条形图。

对于不会取0的量, 可以取y轴的范围为某个区间而不必总是从0开始。 这时, 可以用散点位置表示y坐标。

考虑gapminder包的gapminder数据集中各国的平均期望寿命, 先求出每个大洲的期望寿命最大值:

library(gapminder) gapminder |> select(continent, country, lifeExp) |> group_by(continent) |> summarise( lifeExp = max(lifeExp, na.rm=TRUE), .groups = "drop") -> d_gap

用点图表现各大洲的最大期望寿命:

p select(continent, year, lifeExp) |> group_by(continent, year) |> summarise( lifeExp = median(lifeExp, na.rm=TRUE), .groups = "drop") -> d_gap2a d_gap2a |> filter(year == 2007) |> arrange(desc(lifeExp)) -> d_gap2b d_gap2a |> mutate( continent = factor( continent, levels = d_gap2b$continent)) -> d_gap2

上面的程序中将各大洲的次序调整为最后一年的中位期望寿命。 作热力图:

ggplot(d_gap2, aes( x = year, y = continent, fill = lifeExp)) + geom_tile() + scale_fill_viridis_c()

函数scale_fill_viridis_c()提供了连续变量到颜色的一种映射, 在黑白显示时仍适用,且使用色盲的读者。

热力图中不易读出每个交叉组的数量的具体数值, 但是比较容易进行组间比较以及展示发展趋势。

28.3 表现分布

对于离散变量, 可以用频数、比例、百分数的条形图表现单个离散变量分布, 可以用热力图表现两个离散变量的分布。

对于连续型变量, 可以用直方图、密度估计图表现单个变量分布, 可以对多个变量同时做密度估计图。 可以用正态QQ图、盒形图、经验分布函数图等表现一元分布。

ggdist包提供了多种显示一维分布与分布比较的函数。

28.3.1 单个一元分布的直方图与密度估计图

直方图是最常用的表现一元连续变量分布的方法。 geom_histogram()作直方图, 可以自动选取合适的分组个数, 也可以人为指定分组个数。 直方图的结果受分组个数与分组的开始位置的影响较大, 所以使用直方图时应该尝试选用不同的分组数, 选择较适当的分组个数。

ggplot2包中的midwest数据集包含了美国中西部的一些县的统计数据, 如面积(单位:平方英里)。 下面的程序对连续取值的数值型变量area作频数直方图, 自动确定分组个数:

p filter(state %in% c("IL", "IN")) |> ggplot(aes( x = area, fill = state)) + geom_histogram() ## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

可以看出, IN州的县面积偏小, IL州的县面积较大。 这样的条形分段的直方图的缺点是, 下面的段的直方图形状是清楚的, 但是上面一段(上图中为IL州)的直方图则看不出形状。

如果将数据中所有的5个州都包含并在直方图中分段, 图形就变得更难认读:

p mutate(size = factor( ifelse(carat >= 1.0, "big", "small"), levels=c("small", "big"))) |> ggplot() + geom_mosaic(mapping = aes( x = product(cut), fill = size)) + theme_mosaic() ## Warning: `unite_()` was deprecated in tidyr 1.2.0. ## ℹ Please use `unite()` instead. ## ℹ The deprecated feature was likely used in the ggmosaic package. ## Please report the issue at . ## This warning is displayed once every 8 hours. ## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was ## generated.

mosaic包还支持更多分类变量的频数统计图示。

与马赛克图类似的一种方法是在大类中再细分小类, 而且细分小类的办法不是单向划分的。 treemapify包的geom_treemap()函数可以做树状分类图。 如:

library(treemapify) ggplot(ddssize0, aes( subgroup = cut, fill = interaction(size, cut), area = n)) + geom_treemap( color="white", size=0.5*.pt, alpha=NA) + geom_treemap_subgroup_text( place = "center", alpha = 0.5, grow = TRUE) + geom_treemap_text(mapping = aes( label = size), color = "white", place = "center", grow = FALSE) + guides(fill = "none")

还可以用平行集(parallel sets)方法表现多个分类之间的关系, 以一个分类为主分类染色, 可以看出每个主分类与其他子类的关系。 ggforce包的geom_paralles_sets()函数作这种图。 参见https://serialmentor.com/dataviz/nested-proportions.html。

28.5 表现多个变量间的关系

当数据集中有多个变量中, 我们除了关心每一个变量的类型、取值集合、分布情况, 还关心变量之间的关系, 观测的分组情况等。

为表现两个变量之间的关系, 最常用的是散点图。 多个变量之间可以用散点图矩阵、相关图, 可以在散点图中用符号大小、符号颜色、符号形状表示更多维数。 对于高维数据, 经常需要利用降维方法, 如主成分分析(PCA)对数据降维, 对降维数据作图。

28.5.1 散点图

R软件自带的iris数据集中包含了三种鸢尾花的150个样品的测量数据, 每种各50个样品, 每个样品测量了花瓣、花萼的长、宽。 下面画50个setosa样品的花瓣长、宽的散点图, 可以看出, 两种有明显的线性相关关系:

p


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有