Использование facet_wrap
для получения нескольких панелей на одном графике
Без дублирования кода для каждого элемента вы можете использовать функцию facet_wrap
в ggplot2
чтобы все боксы на одной странице (которые вы можете сохранить после того, как вам нравится). (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, вы можете сначала создать новый столбец, чтобы идентифицировать их. здесь я использую 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
для отображения идентификатора каждого из этих выбросов:
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")
К l oop за сюжет, чтобы получить только один одиночный сюжет на страницу
Если вы глядя на график только одного элемента на странице и l oop по всем элементам, начиная с DATA
(с выявленными выбросами), вы можете l oop по каждому значению "Element", создав for
l oop:
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 или любого другого формата.