在BBC数据团队开发了一个R包,以ggplot2内部风格创建可发布出版物的图形,并且使新手更容易到R创建图形。 例如:
加载所有所需的R语言包
通常在R中创建图表需要安装和加载某些软件包。 为了不必一一安装和加载它们,可以使用pacman软件包中的``p_load''函数通过以下代码一次加载它们。
代码语言:javascript复制#This line of code installs the pacman page if you do not have it installed - if you do, it simply loads the package
if(!require(pacman))install.packages("pacman")
pacman::p_load('dplyr', 'tidyr', 'gapminder',
'ggplot2', 'ggalt',
'forcats', 'R.utils', 'png',
'grid', 'ggpubr', 'scales',
'bbplot')
创建 bbplot 包
bbplot
没有在CRAN上, 所以你必须通过 devtools
来安装
# install.packages('devtools')
devtools::install_github('bbc/bbplot')
bbplot包介绍
共计两个函数bbc_style()
and finalise_plot()
。
bbc_style()
没有参数,并且在创建绘图后将其添加到ggplot“链”中。 它所做的通常是将文本大小,字体和颜色,轴线,轴线文本,边距和许多其他标准图表组件转换为BBC样式,这是根据设计团队的建议和反馈制定的。请注意,对于折线图而言,折线的颜色或对于条形图而言是条形的颜色,并不是从bbc_style()函数中直接获得的,而是需要在其他标准ggplot图表函数中明确设置 。以下代码显示了在标准图表制作工作流程中应如何使用bbc_style()
。 这是一个非常简单的折线图的示例,使用了来自gapminder
包的数据。
#Data for chart from gapminder package
line_df <- gapminder %>%
filter(country == "Malawi")
#Make plot
line <- ggplot(line_df, aes(x = year, y = lifeExp))
geom_line(colour = "#1380A1", size = 1)
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
labs(title="Living longer",
subtitle = "Life expectancy in Malawi 1952-2007")
image.png
这就是bbc_style()
函数实际上是在做什么。 它本质上修改了ggplot2的主题功能中的某些参数。例如,第一个参数是设置绘图标题元素的字体,大小,字体和颜色。
## function ()
## {
## font <- "Helvetica"
## ggplot2::theme(plot.title = ggplot2::element_text(family = font,
## size = 28, face = "bold", color = "#222222"), plot.subtitle = ggplot2::element_text(family = font,
## size = 22, margin = ggplot2::margin(9, 0, 9, 0)), plot.caption = ggplot2::element_blank(),
## legend.position = "top", legend.text.align = 0, legend.background = ggplot2::element_blank(),
## legend.title = ggplot2::element_blank(), legend.key = ggplot2::element_blank(),
## legend.text = ggplot2::element_text(family = font, size = 18,
## color = "#222222"), axis.title = ggplot2::element_blank(),
## axis.text = ggplot2::element_text(family = font, size = 18,
## color = "#222222"), axis.text.x = ggplot2::element_text(margin = ggplot2::margin(5,
## b = 10)), axis.ticks = ggplot2::element_blank(),
## axis.line = ggplot2::element_blank(), panel.grid.minor = ggplot2::element_blank(),
## panel.grid.major.y = ggplot2::element_line(color = "#cbcbcb"),
## panel.grid.major.x = ggplot2::element_blank(), panel.background = ggplot2::element_blank(),
## strip.background = ggplot2::element_rect(fill = "white"),
## strip.text = ggplot2::element_text(size = 22, hjust = 0))
## }
## <environment: namespace:bbplot>
可以使用所需的参数调用主题功能来修改图表的这些设置或添加其他主题参数。但请注意,要使其正常工作,必须是在bbc_style()
后, 否则bbc_style()
将覆盖它。
theme(panel.grid.major.x = element_line(color="#cbcbcb"),
panel.grid.major.y=element_blank())
保存完成的图表
bbplot软件包的第二个功能finalise_plot()
将使标题和副标题左对齐,并在图的右下角添加带有源和图像的页脚。它还会将其保存到指定的位置。该函数有五个参数:
finalise_plot(plot_name, source, save_filepath, width_pixels = 640, height_pixels = 450)
plot_name
:绘图的变量名称,例如上面的图表示例,plot_name
将为“ line”。
source
:要显示在绘图左下角的源文本。
save_filepath
:图形保存到的精确文件路径,包括末尾的.png
扩展名。这确实取决于工作目录以及您是否在特定的R项目中。示例文件路径为:``Desktop / R_projects / charts / line_chart.png''。
width_pixels
:默认情况下设置为640px,因此仅当希望图表具有不同的宽度并指定其宽度时才调用此参数。
height_pixels
:默认设置为450px,因此仅当希望图表具有不同的高度并指定其高度时才调用此参数。
logo_image_path
:此参数指定图右下角的图像/徽标路径。默认值为占位符PNG文件,其背景与绘图的背景颜色匹配。
finalise_plot(plot_name = my_line_plot,
source = "Source: Gapminder",
save_filepath = "filename_that_my_plot_should_be_saved_to.png",
width_pixels = 640,
height_pixels = 450,
logo_image_path = "placeholder.png")
因此,一旦创建了绘图并对其比较满意,就可以使用finalise_plot()
函数进行最终调整并保存图表,以便可以在RStudio之外查看它。因为文本和其他元素的位置在RStudio的“plot”面板中无法准确呈现(这取决于显示绘图的大小和纵横比), 因此将其保存并打开文件可以准确地表示图形的外观。
finalise_plot(plot_name = line,
source = "Source: Gapminder",
save_filepath = "images/line_plot_finalised_test.png",
width_pixels = 640,
height_pixels = 550)
绘制线图
代码语言:javascript复制#Prepare data
line_df <- gapminder %>%
filter(country == "China")
#Make plot
line <- ggplot(line_df, aes(x = year, y = lifeExp))
geom_line(colour = "#1380A1", size = 1)
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
labs(title="Living longer",
subtitle = "Life expectancy in China 1952-2007")
绘制多个线图
代码语言:javascript复制#Prepare data
multiple_line_df <- gapminder %>%
filter(country == "China" | country == "United States")
#Make plot
multiple_line <- ggplot(multiple_line_df, aes(x = year, y = lifeExp, colour = country))
geom_line(size = 1)
geom_hline(yintercept = 0, size = 1, colour="#333333")
scale_colour_manual(values = c("#FAAB18", "#1380A1"))
bbc_style()
labs(title="Living longer",
subtitle = "Life expectancy in China and the US")
绘制柱状图
代码语言:javascript复制#Prepare data
bar_df <- gapminder %>%
filter(year == 2007 & continent == "Africa") %>%
arrange(desc(lifeExp)) %>%
head(5)
#Make plot
bars <- ggplot(bar_df, aes(x = country, y = lifeExp))
geom_bar(stat="identity",
position="identity",
fill="#1380A1")
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
labs(title="Reunion is highest",
subtitle = "Highest African life expectancy, 2007")
绘制堆叠柱状图
代码语言:javascript复制#prepare data
stacked_df <- gapminder %>%
filter(year == 2007) %>%
mutate(lifeExpGrouped = cut(lifeExp,
breaks = c(0, 50, 65, 80, 90),
labels = c("Under 50", "50-65", "65-80", "80 "))) %>%
group_by(continent, lifeExpGrouped) %>%
summarise(continentPop = sum(as.numeric(pop)))
#set order of stacks by changing factor levels
stacked_df$lifeExpGrouped = factor(stacked_df$lifeExpGrouped, levels = rev(levels(stacked_df$lifeExpGrouped)))
#create plot
stacked_bars <- ggplot(data = stacked_df,
aes(x = continent,
y = continentPop,
fill = lifeExpGrouped))
geom_bar(stat = "identity",
position = "fill")
bbc_style()
scale_y_continuous(labels = scales::percent)
scale_fill_viridis_d(direction = -1)
geom_hline(yintercept = 0, size = 1, colour = "#333333")
labs(title = "How life expectancy varies",
subtitle = "% of population by life expectancy band, 2007")
theme(legend.position = "top",
legend.justification = "left")
guides(fill = guide_legend(reverse = TRUE))
制作分组的条形图
代码语言:javascript复制#Prepare data
grouped_bar_df <- gapminder %>%
filter(year == 1967 | year == 2007) %>%
select(country, year, lifeExp) %>%
spread(year, lifeExp) %>%
mutate(gap = `2007` - `1967`) %>%
arrange(desc(gap)) %>%
head(5) %>%
gather(key = year,
value = lifeExp,
-country,
-gap)
#Make plot
grouped_bars <- ggplot(grouped_bar_df,
aes(x = country,
y = lifeExp,
fill = as.factor(year)))
geom_bar(stat="identity", position="dodge")
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
scale_fill_manual(values = c("#1380A1", "#FAAB18"))
labs(title="We're living longer",
subtitle = "Biggest life expectancy rise, 1967-2007")
制作哑铃图
表示差异的另一种方式是哑铃图:
代码语言:javascript复制library("ggalt")
library("tidyr")
#Prepare data
dumbbell_df <- gapminder %>%
filter(year == 1967 | year == 2007) %>%
select(country, year, lifeExp) %>%
spread(year, lifeExp) %>%
mutate(gap = `2007` - `1967`) %>%
arrange(desc(gap)) %>%
head(10)
#Make plot
ggplot(dumbbell_df, aes(x = `1967`, xend = `2007`, y = reorder(country, gap), group = country))
geom_dumbbell(colour = "#dddddd",
size = 3,
colour_x = "#FAAB18",
colour_xend = "#1380A1")
bbc_style()
labs(title="We're living longer",
subtitle="Biggest life expectancy rise, 1967-2007")
制作直方图
代码语言:javascript复制hist_df <- gapminder %>%
filter(year == 2007)
ggplot(hist_df, aes(lifeExp))
geom_histogram(binwidth = 5, colour = "white", fill = "#1380A1")
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
scale_x_continuous(limits = c(35, 95),
breaks = seq(40, 90, by = 10),
labels = c("40", "50", "60", "70", "80", "90 years"))
labs(title = "How life expectancy varies",
subtitle = "Distribution of life expectancy in 2007")
修改图例legend
移除legend
仅仅移除特定legend
代码语言:javascript复制multiple_line guides(colour=FALSE)
移除所有legend
代码语言:javascript复制multiple_line theme(legend.position = "none")
image.png
改变legend位置
代码语言:javascript复制multiple_line theme(legend.position = "right")
为了确切地说明我们希望图例的位置,我们可以给它指定特定的坐标,例如legend.position = c(0.98,0.1)
将图例移到右下角。 作为参考,c(0,0)在左下方,c(1,0)在右下方,c(0,1)在左上方,依此类推。 找到最佳的位置可能会涉及一些反复试验。要检查图例在最终绘图中出现的确切位置,必须查看保存的文件。
multiple_line theme(legend.position = c(0.115,1.05),
legend.direction = "horizontal")
labs(title="Living longer",
subtitle = "Life expectancy in China and the USn")
为了使图例与图表的左侧齐平,使用legend.margin
为图例设置负的左边距会更容易。 语法是margin(top, right, bottom, left)。
theme(legend.margin = margin(0, 0, 0, -200))
移除legend标题
代码语言:javascript复制 theme(legend.title = element_blank())
翻转legend顺序
代码语言:javascript复制 guides(fill = guide_legend(reverse = TRUE))
重新排列图例的布局
可以指定您的图例作为guide的参数的行数。 例如,下面的代码片段将创建具有4行的图例:
代码语言:javascript复制 guides(fill = guide_legend(nrow = 4, byrow = T))
更改图例符号的外观
可以通过将参数override.aes添加到guide中来更改图例符号的默认外观,例如下面将增加图例符号的大小:
代码语言:javascript复制 guides(fill = guide_legend(override.aes = list(size = 4))))
在图例标签之间添加空格
默认的ggplot图例在各个图例项目之间几乎没有空格。 可以通过手动更改比例标签来添加空间。
代码语言:javascript复制 scale_colour_manual(labels = function(x) paste0(" ", x, " "))
如果图例显示的内容有所不同,则需要相应地更改代码。 例如scale_fill_manual()
。
更改轴
翻转图的坐标
添加coord_flip()
使垂直分布变为水平:
bars <- bars coord_flip()
添加/删除网格线
默认主题的y轴具有网格线。 用panel.grid.major.x = element_line添加x条网格线。(类似地,通过panel.grid.major.y = element_blank()
删除y轴上的网格线)
bars <- bars coord_flip()
theme(panel.grid.major.x = element_line(color="#cbcbcb"),
panel.grid.major.y=element_blank())
代码语言:javascript复制## Coordinate system already present. Adding new coordinate system, which will replace the existing one.
手动更改轴文本
可以使用scale_y_continuous或scale_x_continuous
自由更改轴文本标签:
bars <- bars scale_y_continuous(limits=c(0,85),
breaks = seq(0, 80, by = 20),
labels = c("0","20", "40", "60", "80 years"))
bars
在轴标签中添加千位分隔符
可以指定轴文本具有千位分隔符,并带有scale_y_continuous
的参数。有两种方法可以执行此操作,一种在基数R中有点儿麻烦:
scale_y_continuous(labels = function(x) format(x, big.mark = ",",
scientific = FALSE))
第二种方法依赖于scales包,但是更加简洁:
代码语言:javascript复制 scale_y_continuous(labels = scales::comma)
将百分比符号添加到轴标签
这也很容易通过在scale_y_continuous中添加参数来实现:
代码语言:javascript复制 scale_y_continuous(labels = function(x) paste0(x, "%"))
更改限制
代码语言:javascript复制bars ylim(c(0,500))
代码语言:javascript复制## Scale for 'y' is already present. Adding another scale for 'y', which
## will replace the existing scale.
添加轴标题
默认主题没有轴标题,但是可以通过修改theme()
来完成。请注意,必须在bbc_style()
后之后执行此操作,否则更改将被覆盖:
theme(axis.title = element_text(size = 18))
修改轴标题
如果添加轴标题,则默认情况下,它们将是数据集中的列名。 您可以在调用labs()时将其更改为所需的任何内容。例如,如果您希望x轴标题为“ I'm a axis”,而y轴标签为空白,则格式为:
代码语言:javascript复制 labs(x = "I'm an axis",
y = "")
添加轴刻度
可以通过在主题中添加axis.ticks.x或axis.ticks.y来添加轴刻度线:
代码语言:javascript复制multiple_line theme(
axis.ticks.x = element_line(colour = "#333333"),
axis.ticks.length = unit(0.26, "cm"))
添加注释
向绘图添加文本注释的最简单方法是使用geom_label
:
multiple_line geom_label(aes(x = 1980, y = 45, label = "I'm an annotation!"),
hjust = 0,
vjust = 0.5,
colour = "#555555",
fill = "white",
label.size = NA,
family="Helvetica",
size = 6)
使用 n在标签中的必要位置添加换行,并使用lineheight
设置行高。
multiple_line <- multiple_line
geom_label(aes(x = 1980, y = 45, label = "I'm quite a longnannotation overnthree rows"),
hjust = 0,
vjust = 0.5,
lineheight = 0.8,
colour = "#555555",
fill = "white",
label.size = NA,
family="Helvetica",
size = 6)
multiple_line <- multiple_line
theme(legend.position = "none")
xlim(c(1950, 2011))
geom_label(aes(x = 2007, y = 79, label = "US"),
hjust = 0,
vjust = 0.5,
colour = "#1380A1",
fill = "white",
label.size = NA,
family="Helvetica",
size = 6)
geom_label(aes(x = 2007, y = 72, label = "China"),
hjust = 0,
vjust = 0.5,
colour = "#FAAB18",
fill = "white",
label.size = NA,
family="Helvetica",
size = 6)
左对齐/右对齐文本
参数'hjust'和'vjust'指示水平和垂直文本对齐方式。 它们的值可以在0到1之间,其中0左对齐,而1右对齐(或垂直对齐的底部和顶部对齐)。
根据数据添加标签
上面的向图表添加注释的方法使您可以精确地指定x和y坐标。 如果我们想在特定位置添加文本注释,这将非常有用,但是重复起来将非常繁琐。幸运的是,如果要向所有数据点添加标签,则可以简单地根据数据设置位置。假设我们要在条形图中添加数据标签:
代码语言:javascript复制labelled.bars <- bars
geom_label(aes(x = country, y = lifeExp, label = round(lifeExp, 0)),
hjust = 1,
vjust = 0.5,
colour = "white",
fill = NA,
label.size = NA,
family="Helvetica",
size = 6)
labelled.bars
上面的代码会自动为每个大洲添加一个文本标签,而无需我们分别添加“ geom_label”。
(如果您对为什么将x设置为大陆,将y设置为预期寿命感到困惑,那么当图表似乎正以相反的方式绘制它们时,这是因为我们已经翻转了 使用coord_flip()
进行绘图。
将左对齐标签添加到条形图
如果您想为条形图添加左对齐标签,只需根据数据设置x
参数,而是直接使用数字值指定y
参数。y的确切值将取决于数据范围。
labelled.bars.v2 <- bars
geom_label(aes(x = country,
y = 4,
label = round(lifeExp, 0)),
hjust = 0,
vjust = 0.5,
colour = "white",
fill = NA,
label.size = NA,
family="Helvetica",
size = 6)
labelled.bars.v2
增加一条线
通过geom_segment函数
代码语言:javascript复制multiple_line geom_segment(aes(x = 1979, y = 45, xend = 1965, yend = 43),
colour = "#555555",
size=0.5)
size
函数设置了线条的宽度。
增加一条弯曲的线
geom_curve
函数
multiple_line geom_curve(aes(x = 1979, y = 45, xend = 1965, yend = 43),
colour = "#555555",
curvature = -0.2,
size=0.5)
``曲率''参数设置曲线的数量:0为直线,负值给出左手曲线,正值给出右手曲线。
增加一个箭头
仅仅需要增加一个arrow
参数。
multiple_line geom_curve(aes(x = 1979, y = 45, xend = 1965, yend = 43),
colour = "#555555",
size=0.5,
curvature = -0.2,
arrow = arrow(length = unit(0.03, "npc")))
image.png
增加一条贯穿整个图片的线条
在整个图上添加一条线的最简单方法是使用geom_vline()
表示垂直线,或者geom_hline()
表示水平线。可选的其他参数可以指定线条的大小,颜色和类型(默认选项为实线)。
multiple_line geom_hline(yintercept = 10, size = 1, colour = "red", linetype = "dashed")
在此示例对想突出显示某些内容(例如, 阈值水平或平均值)特别有用。
代码语言:javascript复制 geom_hline(yintercept = 0, size = 1, colour = "#333333")
构图
如果想将可视化的数据按某个变量进行拆分,则需要使用facet_wrap或facet_grid。将要除以的变量添加到以下代码行:facet_wrap(〜变量),分面换行的另一个参数ncol
指定列数:
#Prepare data
facet <- gapminder %>%
filter(continent != "Americas") %>%
group_by(continent, year) %>%
summarise(pop = sum(as.numeric(pop)))
#Make plot
facet_plot <- ggplot()
geom_area(data = facet, aes(x = year, y = pop, fill = continent))
scale_fill_manual(values = c("#FAAB18", "#1380A1","#990000", "#588300"))
facet_wrap( ~ continent, ncol = 5)
scale_y_continuous(breaks = c(0, 2000000000, 4000000000),
labels = c(0, "2bn", "4bn"))
bbc_style()
geom_hline(yintercept = 0, size = 1, colour = "#333333")
theme(legend.position = "none",
axis.text.x = element_blank())
labs(title = "Asia's rapid growth",
subtitle = "Population growth by continent, 1952-2007")
Free scales
可能已经在上表中注意到,人口相对较少的大洋洲已经完全消失。默认情况下,构面在较小的倍数上使用固定的轴比例。 最好始终在较小的倍数上使用相同的y轴比例,以避免产生误导,但有时您可能需要为每个倍数分别设置这些值,我们可以通过添加参数scales =“ free”来实现。如果只想释放一个轴的刻度,则将参数设置为free_x
或free_y
。
#Make plot
facet_plot_free <- ggplot()
geom_area(data = facet, aes(x = year, y = pop, fill = continent))
facet_wrap(~ continent, scales = "free")
bbc_style()
scale_fill_manual(values = c("#FAAB18", "#1380A1","#990000", "#588300"))
geom_hline(yintercept = 0, size = 1, colour = "#333333")
theme(legend.position = "none",
axis.text.x = element_blank(),
axis.text.y = element_blank())
labs(title = "It's all relative",
subtitle = "Relative population growth by continent,1952-2007")
image.png
增加或减少边距
您可以更改情节几乎所有元素(标题,字幕,图例)或情节本身周围的边距。
通常,您不需要更改主题的默认边距,但是如果这样做,则语法为theme(ELEMENT = element_text(margin = margin(0,5,10,0)))
。
这些数字分别指定顶部,右侧,底部和左侧的边距-但您也可以直接指定要更改的边距。 例如,让我们尝试为字幕提供一个较大的底边距:
代码语言:javascript复制bars theme(plot.subtitle=element_text(margin=margin(b=75)))
Exporting your plot and x-axis margins
当您制作的绘图超出bbplot中的默认高度450px时,您确实需要考虑x轴边距的大小。 例如,如果要创建带有很多条形图的条形图,并要确保每个条形图和标签之间有一定的呼吸空间,则可能是这种情况。 如果您确实保留了较大高度图的边距,那么轴和标签之间的间隙可能会更大。
这是我们在处理条形图的边距和高度时应用的指南(已应用coord_flip)
size | t | b |
---|---|---|
550px | 5 | 10 |
650px | 7 | 10 |
750px | 10 | 10 |
850px | 14 | 10 |
因此,您需要做的就是将此代码添加到图表中,例如,如果您希望绘图的高度为650px而不是450px。
代码语言:javascript复制bar_chart_tall <- bars theme(axis.text.x = element_text(margin=margin(t = 7, b = 10)))
bar_chart_tall
image.png
尽管可能性要小得多,但是如果您确实想对折线图进行等效处理并以大于默认高度的高度导出它,则需要执行相同的操作,但是要根据上表将t的值更改为负值 。
按大小重新排序栏
默认情况下,R将按字母顺序显示数据,但按大小排列则很简单:只需将reorder()
包装在要重新排列的x
或y
变量周围,然后指定要变量 重新排序。
例如。 x =重新排序(国家/地区,流行)。 升序是默认设置,但是您可以通过将desc()
包裹在要排序的变量周围来将其更改为降序:
bars <- ggplot(bar_df, aes(x = reorder(country, lifeExp), y = lifeExp))
geom_bar(stat="identity", position="identity", fill="#1380A1")
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
coord_flip()
labs(title="Reunion is highest",
subtitle = "Highest African life expectancy, 2007")
theme(panel.grid.major.x = element_line(color="#cbcbcb"),
panel.grid.major.y=element_blank())
image.png
修改柱状图柱子顺序
有时,您需要以不按字母顺序或按大小重新排序的方式对数据进行排序。为了正确排序这些参数,需要在绘制图表之前设置数据的因子水平,在levels
参数中指定要绘制类别的顺序:
dataset$column <- factor(dataset$column, levels = c("18-24","25-64","65 "))
有条件的显示条状图颜色
可以通过 ifelse()
设置图片的 fill, alpha, size。
fill=ifelse(logical_condition, fill_if_true, fill_if_false)
ggplot(bar_df,
aes(x = reorder(country, lifeExp), y = lifeExp))
geom_bar(stat="identity", position="identity", fill=ifelse(bar_df$country == "Mauritius", "#1380A1", "#dddddd"))
geom_hline(yintercept = 0, size = 1, colour="#333333")
bbc_style()
coord_flip()
labs(title="Reunion is highest",
subtitle = "Highest African life expectancy, 2007")
theme(panel.grid.major.x = element_line(color="#cbcbcb"),
panel.grid.major.y=element_blank())