r - 如何将分组箱线图打印到 pdf 文档上并标记异常值
问题描述
我有一个类似于使用此代码创建的数据框:
Location <- rep(c("FL", "GA", "SC", "NC"), each = 5)
ID <- data.frame(ID=(c(12,122,242,329,595,130,145,245,654,878,863,425,24,92,75,3,200,300,40,500)))
set.seed(1)
Copper <- sample(1:100,20,replace=T)
Iron <- sample(1:100,20,replace=T)
Carbon <- sample(1:100,20,replace=T)
Lead <- sample(1:100,20,replace=T)
Mg <- sample(1:100,20,replace=T)
CaCO <- sample(1:100,20,replace=T)
Zinc <- sample(1:100,20,replace=T)
data <- cbind(Location,State,ID,Copper,Iron,Carbon,Lead,Mg,CaCO,Zinc)
注意:我不知道如何创建一个包含一些极端异常值的模拟数据集,这对这个问题很有用,如果有人想在答案中包含它,那就太棒了。
我可以为每个变量(Copper
: Zinc
)创建箱线图,Location
如下所示:
#example shown for Copper
library(tidyverse)
ggplot(data, aes(x=Location, y=Copper, color = Location))+
geom_boxplot() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.3, hjust = 1)) +
theme(legend.position = "none",
axis.title.y = element_blank()) +
ggtitle("Copper") + theme(plot.title = element_text(hjust = 0.5))
我一直在为每个变量(:)做同样的Copper
过程Zinc
。我想知道一种更快的方法来实现这一点 - 无需复制和粘贴这么多 - 并将绘图打印到 pdf 文档上。我必须先使用 pivot_longer() 吗?我还想知道如何使用 ggplot2 仅标记每个图中的异常值?
解决方案
用于在单个facet_wrap
图上获取多个面板
无需为每个元素复制代码,您可以使用facet_wrap
函数 inggplot2
将所有箱线图放在一个页面上(之后您可以按照自己喜欢的方式保存)。(https://ggplot2.tidyverse.org/reference/facet_wrap.html)
为此,您首先需要重塑数据,以便将所有元素放在单个列中,并将所有值放在第二列中,您可以使用以下pivot_longer
函数来实现tidyr
:
library(tidyr)
data %>% pivot_longer(.,-c(State,ID), names_to = "Element", values_to = "Value")
# A tibble: 140 x 4
State ID Element Value
<fct> <dbl> <chr> <int>
1 FL 12 Copper 68
2 FL 12 Iron 89
3 FL 12 Carbon 44
4 FL 12 Lead 81
5 FL 12 Mg 73
6 FL 12 CaCO 24
7 FL 12 Zinc 28
8 FL 122 Copper 39
9 FL 122 Iron 37
10 FL 122 Carbon 25
# … with 130 more rows
现在,您可以像以前一样获取绘图,除了,您指示使用以下ggplot2
命令为每个元素创建一个面板facet_wrap(~Element)
:
data %>% pivot_longer(.,-c(State,ID), names_to = "Element", values_to = "Value") %>%
ggplot(aes(x = State, y = Value, color = State))+
geom_boxplot() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.3, hjust = 1)) +
theme(legend.position = "none",
axis.title.y = element_blank(),
axis.title.x = element_blank()) +
facet_wrap(.~Element)
用 ID 标记异常值
要使用 ID 标记异常值,您可以首先创建一个新列来识别它们。在这里,我dplyr
用来创建一个新列(在旋转数据框之后)以确定每个点是否是异常值:
DATA <- data %>% pivot_longer(.,-c(State,ID), names_to = "Element", values_to = "Value") %>%
group_by(State, Element) %>%
mutate(Outlier = ifelse(Value > quantile(Value,0.75)+1.5*IQR(Value) | Value < quantile(Value,0.25)-1.5*IQR(Value), "Out","in"))
# A tibble: 140 x 5
# Groups: State, Element [28]
State ID Element Value Outlier
<fct> <dbl> <chr> <dbl> <chr>
1 FL 12 Copper 68 in
2 FL 12 Iron 37 in
3 FL 12 Carbon 70 in
4 FL 12 Lead 87 in
5 FL 12 Mg 45 in
6 FL 12 CaCO 59 in
7 FL 12 Zinc 43 in
8 FL 122 Copper 39 in
9 FL 122 Iron 89 in
10 FL 122 Carbon 40 in
# … with 130 more rows
现在,我们可以使用geom_text
(或geom_text_repel
从ggrepel
包中)通过子集数据框来标记此异常值,以仅保留标记为异常值的点并label = ID
用作参数,aes
以显示每个异常值的 ID:
library(ggplot2)
library(ggrepel)
ggplot(DATA, aes(x = State, y = Value, color = State))+
geom_boxplot() +
geom_text_repel(data = subset(DATA, Outlier == "Out"), aes(label = ID))+
theme(axis.text.x = element_text(angle = 90, vjust = 0.3, hjust = 1)) +
theme(legend.position = "none",
axis.title.y = element_blank(),
axis.title.x = element_blank()) +
facet_wrap(.~Element, scales = "free")
循环绘图以每页仅获取一个绘图
如果您希望每页仅绘制一个元素并遍历所有元素,从DATA
(识别出异常值)开始,您可以通过创建for
循环来遍历“元素”的每个值:
element <- unique(DATA$Element)
for(i in 1:length(element))
{
g <- ggplot(subset(DATA, Element == element[i]), aes(x = State, y = Value, color = State))+
geom_boxplot() +
geom_text_repel(data = subset(DATA, Element == element[i] & Outlier == "Out"), aes(label = ID))+
theme(axis.text.x = element_text(angle = 90, vjust = 0.3, hjust = 1)) +
theme(legend.position = "none",
axis.title.y = element_blank(),
axis.title.x = element_blank()) +
ggtitle(element[i]) + theme(plot.title = element_text(hjust = 0.5))
ggsave(g,filename = paste("test",element[i],".png"), width = 5, height =5, units = "in" )
}
在这里,我将其保存为png
,但您可以对 pdf 或任何其他格式执行相同的操作。
推荐阅读
- python - 递归与迭代时间复杂度
- javascript - 为什么 Function 的实例化没有存储在 Function.prototype 中的所有属性?
- python - 烧瓶的烧瓶邮件扩展在应用程序工厂结构中不起作用
- c - RPI 零 - 裸机 - PWM
- javascript - Javascript连接多个字符串变量并在span中显示
- vb.net - Dropbox API Upload 等待异步函数
- django - “方法不允许(发布):/”在家里使用联系我们表格时出错
- mongodb - 无法在 MongoDB 4.0 事务中运行 2 个 findAndUpdate 查询
- reactjs - 是否有我可以在接口中使用的接口类型?
- python - 如何隐藏列表中的项目?