第 5 章 数据可视化
- 作者
- Name
- 青玉白露
- Github
- @white0dew
- Modified on
- Reading time
- 11 分钟
阅读:.. 评论:..
数据可视化是数据分析过程中至关重要的一环。通过生动形象的图表,我们可以直观地展示数据背后的规律和趋势,让枯燥的数字"活"起来。本章将重点介绍 R 语言强大的可视化功能,带你从基础的绘图函数入手,逐步掌握 ggplot2 等高级可视化包的用法,并教你如何绘制动态交互式图表。
5.1 基本绘图函数
R 语言内置了一系列基本绘图函数,可以帮助我们快速绘制常见的图表类型,如散点图、柱状图、直方图、箱线图等。
5.1.1 plot 函数
plot()
是 R 语言最常用的通用绘图函数,根据输入数据的类型自动选择合适的图表样式。例如:
# 绘制散点图 x <- c(1, 2, 3, 4, 5) y <- c(2, 4, 6, 8, 10) plot(x, y)
5.1.2 barplot 函数
barplot()
用于绘制柱状图,可以方便地对比不同类别的数值大小。例如:
# 绘制柱状图 data <- c(10, 20, 30, 40, 50) barplot(data)
5.1.3 hist 函数
hist()
用于绘制直方图,展示数据的分布情况。例如:
# 绘制直方图 data <- rnorm(1000) # 生成1000个正态分布的随机数 hist(data)
5.1.4 boxplot 函数
boxplot()
用于绘制箱线图,直观地展示数据的分位数、异常值等信息。例如:
# 绘制箱线图 data <- list(group1 = rnorm(100), group2 = rnorm(100, mean = 1)) boxplot(data)
通过这些基本绘图函数,我们可以快速探索数据的特征。但是它们的定制性较差,难以满足更高的可视化需求。因此,我们需要使用更强大的可视化包,如 ggplot2。
5.2 ggplot2 包的使用
ggplot2 是 R 语言著名的可视化扩展包,提供了一套"图形语法",可以灵活地自定义图表的各个细节。下面让我们一起来学习 ggplot2 的用法。
5.2.1 ggplot2 的基本概念
ggplot2 的核心思想是将图表拆分为不同的组件,然后使用不同的函数进行组合,最终形成完整的图表。ggplot2 的基本组件包括:
- 数据(data):待可视化的数据框(data.frame)。
- 几何对象(geom):图表的基本图形元素,如点、线、条形等。
- 美学映射(aes):指定数据变量如何映射到几何对象的视觉属性上,如位置、颜色、大小等。
- 标度(scale):控制视觉属性的范围和显示方式,如坐标轴、图例等。
- 分面(facet):按照某些变量将图表划分为多个子图。
- 主题(theme):控制图表的整体外观,如背景、字体、边距等。
理解了这些概念后,我们就可以根据"图形语法"来创建图表了。
5.2.2 ggplot2 的基本语法
使用 ggplot2 绘图的基本语法结构为:
ggplot(data = <DATA>) + <GEOM_FUNCTION>(mapping = aes(<MAPPINGS>))
其中,<DATA>
为数据框,<GEOM_FUNCTION>
为几何对象函数,<MAPPINGS>
为美学映射。
例如,我们可以用以下代码绘制一个散点图:
library(ggplot2) # 创建数据框 df <- data.frame( x = c(1, 2, 3, 4, 5), y = c(2, 4, 6, 8, 10) ) # 绘制散点图 ggplot(data = df) + geom_point(mapping = aes(x = x, y = y))
可以看到,我们首先创建了一个数据框 df
,然后使用 ggplot()
函数指定数据源,再使用 geom_point()
函数添加散点图层,并在 aes()
函数中指定数据变量和视觉属性的映射关系。
ggplot2 支持多种几何对象函数,可以绘制不同类型的图表,例如:
geom_line()
:绘制折线图geom_bar()
:绘制柱状图geom_histogram()
:绘制直方图geom_boxplot()
:绘制箱线图- ...
5.2.3 常用图形的绘制
下面我们通过一些具体的例子,来学习如何使用 ggplot2 绘制常见的图表类型。
折线图
# 生成时间序列数据 df <- data.frame( date = seq(as.Date("2023-01-01"), as.Date("2023-12-31"), by = "month"), value = cumsum(rnorm(12)) ) # 绘制折线图 ggplot(data = df) + geom_line(mapping = aes(x = date, y = value))
柱状图
# 生成分类数据 df <- data.frame( category = c("A", "B", "C", "D", "E"), value = c(10, 20, 30, 40, 50) ) # 绘制柱状图 ggplot(data = df) + geom_bar(mapping = aes(x = category, y = value), stat = "identity")
注意,这里我们需要设置 stat = "identity"
,告诉 ggplot2 使用数据本身的 y 值,而不是默认的计数。
堆叠柱状图
# 生成分类数据 df <- data.frame( category = rep(c("A", "B", "C"), each = 2), group = rep(c("X", "Y"), times = 3), value = c(1, 3, 2, 4, 3, 5) ) # 绘制堆叠柱状图 ggplot(data = df) + geom_bar(mapping = aes(x = category, y = value, fill = group), stat = "identity")
通过设置 fill
参数,我们可以按照 group
变量对柱状图进行着色,形成堆叠柱状图。
直方图
# 生成随机数 data <- rnorm(1000) # 绘制直方图 ggplot(data = data.frame(x = data)) + geom_histogram(mapping = aes(x = x), bins = 30)
直方图可以展示数据的分布情况。通过设置 bins
参数,我们可以控制直方图的分箱数。
箱线图
# 生成分组数据 df <- data.frame( group = rep(c("A", "B", "C"), each = 100), value = c(rnorm(100), rnorm(100, mean = 1), rnorm(100, mean = 2)) ) # 绘制箱线图 ggplot(data = df) + geom_boxplot(mapping = aes(x = group, y = value))
箱线图可以比较不同组别数据的分布情况。这里我们按照 group
变量对数据进行分组。
以上只是 ggplot2 的冰山一角,它还有许多强大的功能等待你去探索,如分面、主题、标度等。建议大家多查阅 ggplot2 的官方文档和示例,学习更多的用法。
5.2.4 图形的美化与自定义
除了绘制基本的图形,我们还可以使用 ggplot2 提供的各种函数对图形进行美化和自定义,使其更加易读和专业。以下是一些常用的美化技巧:
添加标题和标签
ggplot(data = df) + geom_point(mapping = aes(x = x, y = y)) + labs(title = "Scatter Plot", x = "X variable", y = "Y variable")
使用 labs()
函数可以方便地添加图表标题和轴标签。
修改图例
ggplot(data = df) + geom_bar(mapping = aes(x = category, y = value, fill = group), stat = "identity") + scale_fill_manual(values = c("X" = "blue", "Y" = "red")) + guides(fill = guide_legend(title = "Group"))
使用 scale_fill_manual()
函数可以自定义图例的颜色,使用 guides()
函数可以修改图例的标题。
调整坐标轴
ggplot(data = df) + geom_line(mapping = aes(x = date, y = value)) + scale_x_date(date_labels = "%Y-%m", date_breaks = "2 months") + scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 20))
使用 scale_x_date()
和 scale_y_continuous()
函数可以分别控制 x 轴和 y 轴的刻度、标签和范围等。
应用主题
ggplot(data = df) + geom_point(mapping = aes(x = x, y = y)) + theme_minimal()
ggplot2 内置了多个主题函数,如 theme_minimal()
、theme_bw()
等,可以一键改变图表的整体外观。我们也可以使用 theme()
函数来自定义主题的各个细节。
5.3 高级图形和自定义
除了常见的图表类型,我们有时还需要绘制一些更复杂、更个性化的图形。ggplot2 提供了强大的扩展机制,允许我们灵活地组合不同的图层和几何对象。
5.3.1 多图层绘制
在 ggplot2 中,我们可以通过叠加多个图层来创建复合图形。例如,我们可以在散点图的基础上添加趋势线:
ggplot(data = df) + geom_point(mapping = aes(x = x, y = y)) + geom_smooth(mapping = aes(x = x, y = y), method = "lm")
这里我们使用 geom_smooth()
函数添加了一个趋势线图层,并指定了拟合方法为 "lm"
(线性回归)。
5.3.2 自定义几何对象
除了内置的几何对象,我们还可以自定义新的几何对象来满足特殊的可视化需求。例如,我们可以定义一个"半透明柱状图"的几何对象:
library(ggplot2) library(ggproto) # 定义半透明柱状图的几何对象 GeomTransparentBar <- ggproto("GeomTransparentBar", GeomBar, setup_data = function(data, params) { data$width <- data$width %||% params$width %||% resolution(data$x, FALSE) * 0.9 transform(data, ymin = pmin(y, 0), ymax = pmax(y, 0), xmin = x - width / 2, xmax = x + width / 2, width = NULL ) }, draw_panel = function(self, data, panel_params, coord) { # 设置透明度 data$alpha <- 0.5 ggplot2:::ggname("geom_transparent_bar", gTree(children = gList( GeomRect$draw_panel(data, panel_params, coord) ))) } ) geom_transparent_bar <- function(mapping = NULL, data = NULL, stat = "count", position = "stack", ..., width = NULL, binwidth = NULL, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) { layer( data = data, mapping = mapping, stat = stat, geom = GeomTransparentBar, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( width = width, na.rm = na.rm, ... ) ) } # 使用半透明柱状图 ggplot(data = df) + geom_transparent_bar(mapping = aes(x = category, y = value, fill = group))
通过定义 GeomTransparentBar
对象并重写其 draw_panel()
方法,我们实现了半透明效果。然后使用 geom_transparent_bar()
函数来调用这个自定义的几何对象。
5.3.3 主题与配色
ggplot2 提供了强大的主题定制功能,允许我们修改图表的各个细节,如字体、边距、背景等。除了使用内置的主题函数外,我们还可以使用 theme()
函数来自定义主题:
custom_theme <- theme( plot.title = element_text(size = 20, face = "bold"), axis.title = element_text(size = 16), axis.text = element_text(size = 12), panel.background = element_rect(fill = "white"), panel.grid.major = element_line(color = "gray90"), panel.grid.minor = element_blank() ) ggplot(data = df) + geom_point(mapping = aes(x = x, y = y)) + custom_theme
此外,ggplot2 还支持灵活的配色方案。除了使用内置的调色板外,我们还可以使用 scale_color_manual()
和 scale_fill_manual()
函数来自定义颜色:
ggplot(data = df) + geom_bar(mapping = aes(x = category, y = value, fill = group), stat = "identity") + scale_fill_manual(values = c("X" = "#1F77B4", "Y" = "#FF7F0E"))
5.3.4 动态图形
除了静态图形,ggplot2 还支持创建动态交互式图形。我们可以使用 gganimate
包来为 ggplot2 图形添加动画效果,使用 plotly
包来创建可交互的 web 图形。
下面是一个使用 gganimate
创建动画气泡图的示例:
library(ggplot2) library(gganimate) # 创建数据 df <- data.frame( x = runif(20), y = runif(20), size = runif(20), frame = rep(1:10, each = 2) ) # 绘制动画气泡图 ggplot(data = df) + geom_point(mapping = aes(x = x, y = y, size = size), color = "steelblue") + transition_manual(frame) + labs(title = "Frame: {current_frame}")
gganimate
提供了多种过渡效果函数,如 transition_manual()
、transition_time()
等,可以根据数据的不同属性来控制动画的帧。
下面是一个使用 plotly
创建交互式散点图的示例:
library(ggplot2) library(plotly) # 绘制散点图 p <- ggplot(data = df) + geom_point(mapping = aes(x = x, y = y, size = size, color = group)) + scale_color_manual(values = c("X" = "blue", "Y" = "red")) # 转换为交互式图形 ggplotly(p)
plotly
可以自动将 ggplot2 图形转换为交互式的 web 图形,支持缩放、悬停、选择等交互操作。
5.4 动态可视化
在数据分析和展示中,动态可视化越来越受到重视。相比静态图表,动态图表可以更生动地展示数据的变化趋势和互动关系。前面我们已经初步了解了 gganimate
和 plotly
的用法,下面我们再深入介绍一些动态可视化的高级技巧。
5.4.1 使用 plotly 进行动态绘图
plotly
是一个强大的交互式绘图库,支持多种图表类型和丰富的自定义选项。除了直接在 R 中使用 plotly
包外,我们还可以在 RStudio 的 Viewer 窗口中预览 plotly 图形,或将其嵌入到 R Markdown 文档中。
下面是一个使用 plotly
绘制三维散点图的示例:
library(plotly) # 创建数据 df <- data.frame( x = rnorm(100), y = rnorm(100), z = rnorm(100), group = rep(c("A", "B"), each = 50) ) # 绘制三维散点图 plot_ly(data = df, x = ~x, y = ~y, z = ~z, color = ~group, marker = list(size = 5), type = "scatter3d", mode = "markers")
plot_ly()
函数用于创建 plotly 图形,我们可以通过设置不同的参数来控制图形的各个细节,如数据映射、图表类型、标记样式等。
5.4.2 动态交互图形
plotly 支持丰富的交互操作,如缩放、平移、悬停、选择等。我们可以通过添加适当的参数来启用这些交互功能。例如:
library(plotly) # 绘制散点图矩阵 plot_ly(data = iris, type = "splom", dimensions = list( list(label = "Sepal Length", values = ~Sepal.Length), list(label = "Sepal Width", values = ~Sepal.Width), list(label = "Petal Length", values = ~Petal.Length), list(label = "Petal Width", values = ~Petal.Width) ), marker = list(size = 5, color = ~as.numeric(Species), colorscale = "Viridis"), text = ~paste("Species:", Species), hoverinfo = "text" )
这里我们绘制了鸢尾花数据集的散点图矩阵,并启用了悬停交互。当鼠标悬停在某个点上时,会显示该点所属的鸢尾花品种。
5.4.3 实时数据可视化
在某些场景下,我们需要实时地展示数据的变化情况,如股票价格、传感器读数等。plotly
提供了 plotlyProxy()
函数,可以在不重绘整个图形的情况下高效地更新数据。
下面是一个模拟实时数据并动态更新图表的示例:
library(plotly) # 初始化数据 x <- 0 y <- 0 # 创建plotly图形 p <- plot_ly(x = ~x, y = ~y, type = "scatter", mode = "lines") # 创建plotly代理 pp <- plotlyProxy(p, session = "session1") # 模拟实时数据更新 for (i in 1:100) { x <- c(x, i) y <- c(y, rnorm(1)) # 使用plotlyProxy更新数据 pp <- plotlyProxyInvoke(pp, list( list(method = "extendTraces", args = list(list(x = list(list(i)), y = list(list(tail(y, 1)))), list(0)), label = "extend"), list(method = "relayout", args = list(list(xaxis = list(range = c(max(0, i - 50), i))), label = "relayout")) )) Sys.sleep(0.1) }
在这个示例中,我们首先创建了一个空的折线图,然后使用 plotlyProxy()
创建了一个图形代理。接下来,我们在一个循环中模拟实时数据的生成,并使用 plotlyProxyInvoke()
函数来更新图形的数据和布局。通过设置 xaxis.range
,我们可以让图形自动滚动,始终显示最新的数据。
如果你在学习过程中遇到任何问题,欢迎在评论区留言讨论。