Я новичок в R и пытаюсь создать точечные диаграммы с двумя переменными, при этом значения каждой переменной сгруппированы в 4 класса.
В частности, я пытаюсь добиться следующего:
Ниже вы можете найти воспроизводимую версию (вам просто нужно определить вывод для файла png) кода, который работает, но показывает точки данных и эллипсы достоверности для всех данных:
library(ggplot2)
out_path = YOUR OUTPUT DIRECTORY
#data frame
gr1 <- (rep(paste('B-12-B-002'), 10))
gr2 <- (rep(paste('B-12-M-03'), 10))
gr3 <- (rep(paste('b-b-d-3'), 10))
gr4 <- (rep(paste('h-12-b-01'), 10))
Run_type <- c(gr1,gr2,gr3,gr4)
axial_ratio <- runif (40,0,1)
Solidity <- runif (40,0,1)
Convexity <- runif (40,0,1)
sel_data_all <- data.frame(Run_type,axial_ratio,Solidity,Convexity)
fill_colors <- c('red','blue','green','orange');
#Plot
one_plot = ggplot(sel_data_all,aes(x = axial_ratio,y = Solidity))+
geom_point(aes(x = axial_ratio,y = Solidity, fill = Run_type, shape = Run_type), color = "black", stroke = 1,
size = 5, alpha = 0.4)+
stat_ellipse(data = sel_data_all, aes(x = axial_ratio, y = Solidity, fill = Run_type,colour=Run_type),geom = "polygon",alpha = 0.4,type = "norm",level = 0.6,
show.legend = FALSE) + #, group=Run_type , data = subset(sel_data_all, Run_type %in% leg_keys_man[1:7]),
scale_shape_manual(values=c(21,21,23,23))+
scale_fill_manual(values = fill_colors)+
scale_color_manual(values = fill_colors)+
coord_fixed(ratio = 1)+
theme(legend.position = "top", # write 'none' to hide the legend
legend.key = element_rect(fill = "white"), # Set background of the points in the legend
legend.title = element_blank(), # Remove legend title
panel.background=element_rect(fill = "white", colour = "black"),
panel.grid.major=element_line(colour = "lightgrey"),
panel.grid.minor=element_line(colour = "lightgrey"),
axis.title.x = element_text(margin = margin(t = 10), size = 12,face = "bold"), # margin = margin(t = 10) vjust = 0
axis.title.y = element_text(margin = margin(r = 10), size = 12,face = "bold"), # margin = margin(r = 10) vjust = 2
axis.text = element_text(color = "black", size = 10), # To hide the text from a specific axis do: axis.text.y = element_blank()
axis.ticks.length=unit(-0.15, "cm"), # To hide the ticks from a specific axis do: axis.ticks.y = element_blank()
#plot.margin = margin(t = 0, r = 1, b = 0.5, l = 0.5, unit = "cm"), # define margine of the plot frame t = top, r = right, b = bottom, l = left
)
#expand_limits(x = 0, y = 0)+ #Force the origin of the plot to 0
#xlim(c(0,1))+
#ylim(c(0,1)) # or xlim, limit the axis to the values defined
show(one_plot)
# Save plots
ggsave(
filename=paste("Axial_ratio","_vs_","Solidity",".png",sep = ""),
plot = one_plot,
device = "png",
path = out_path,
scale = 1,
width = 8, # Refers to the plot frame, not the area
height = 6, # Refers to the plot frame, not the area
units = "cm",
dpi = 300,
limitsize = FALSE,
bg = "white")
К сожалению, после нескольких дней попыток и чтения документации R и форумов я не могу этого добиться.
Для первой задачи я попытался разделить данные, изменив функции geom_point и stat_ellipse,
geom_point(data = subset(sel_data_all, Run_type %in% c('B-12-B-002','B-12-M-03')),aes(x = axial_ratio,y = Solidity, fill = Run_type, shape = Run_type), color = "black", stroke = 1,
size = 5, alpha = 0.4)+ #
stat_ellipse(data = subset(sel_data_all, Run_type %in% c('b-b-d-3','h-12-b-01')), aes(x = axial_ratio, y = Solidity, fill = Run_type,colour=Run_type),geom = "polygon",alpha = 0.4,type = "norm",level = 0.6,
show.legend = FALSE) + #
но я получаю дубликат легенды (в сером цвете).
Для моего второго вопроса, с рабочей версией скрипта в верхней части сообщения,
Вот сюжет, который отображается в окне "Plots" в RStudio:
Но это то, что сохраняется в каталоге вывода.
Последнее замечание о второй проблеме: представленный здесь скрипт фактически вставлен в цикл for, который генерирует несколько точечных диаграмм, созданных уникальными парами двух переменных, а представленный здесь фрейм данных является лишь частичным, чтобы вам было легче помочь. . К сожалению, это то, что генерирует ggsave:
отношение осей против выпуклости
ves_pct против осевого соотношения
Кто-нибудь может помочь?
Заранее спасибо всем!
Обновлено:
Итак, благодаря MarBlo (которому большое спасибо) мне удалось получить почти то, что я хочу, но есть еще кое-что, чего я пока не могу понять.
Это последняя версия кода с некоторой адаптацией, чтобы лучше соответствовать рассуждениям:
library(tidyverse)
set.seed(123)
gr1 <- (rep(paste("B-12-B-002"), 10))
gr2 <- (rep(paste("B-12-M-03"), 10))
gr3 <- (rep(paste("b-b-d-3"), 10))
gr4 <- (rep(paste("h-12-b-01"), 10))
Sample_ID <- c(gr1, gr2, gr3, gr4)
axial_ratio <- runif (40, 0, 1)
Solidity <- runif (40, 0, 1)
Convexity <- runif (40, 0, 1)
sel_data_all <- data.frame(Sample_ID, axial_ratio, Solidity, Convexity)
fill_colors <- c("#5bd9ca",
"#1e99d6","#1e49d6","#f2581b80","#e8811280","#e3311280","#fc000080")
sel_data_all <- sel_data_all |> add_column(Run_type = c(
rep("MAG", 10), rep("PMAG", 10),
rep("MAG", 10), rep("PMAG", 10)), .before = "Sample_ID")
one_plot = ggplot(
data = sel_data_all |> dplyr::filter(Run_type == "PMAG"),
aes(x = axial_ratio, y = Solidity)
) +
# CONFIDENCE ELLIPSE
stat_ellipse(
data = sel_data_all |> dplyr::filter(Run_type == "MAG"),
aes(x = axial_ratio, y = Solidity,
fill = Sample_ID),
geom = "polygon", type = "norm",
level = 0.6,
colour = 'white', # ellipse border
) +
# DATA POINTS
geom_point(aes(colour = Sample_ID,
shape = Sample_ID),
stroke = 0.5,
size = 3,
) +
scale_color_manual(values = fill_colors[1:3]) + # of Data points
scale_shape_manual(values = c(21, 21, 23, 23,21,23,22)) + # of data points
scale_fill_manual(values = fill_colors[4:7]) + # of ellipses
coord_cartesian(xlim=c(0,1))+
#scale_x_continuous(expand = expansion(mult = c(0.001, 0.05)))+
coord_cartesian(ylim=c(0,1))+
#scale_y_continuous(expand = expansion(mult = c(0.001, 0.05)))+
# Theme
theme(
legend.position = "top",
legend.key.size = unit(5, 'mm'), #change legend key size
# legend.key.height = unit(1, 'cm'), #change legend key height
# legend.key.width = unit(1, 'cm'), #change legend key width
legend.text = element_text(size=8),
legend.key = element_rect(fill = "white", colour = 'white'),
legend.background = element_rect(fill = "transparent"),
legend.title = element_blank(),
panel.background = element_rect(fill = "white", colour = "black"),
panel.grid.major = element_line(colour = "lightgrey"),
panel.grid.minor = element_line(colour = "lightgrey"),
axis.title.x = element_text(vjust = -1, size = 12, face = "bold"),
axis.title.y = element_text(vjust = 4, size = 12, face = "bold"),
axis.text = element_text(color = "black", size = 10),
axis.ticks.length = unit(-0.15, "cm"),
plot.margin = margin(t = 2, # Top margin
r = 4, # Right margin
b = 4, # Bottom margin
l = 4, # Left margin
unit = "mm"),
)+
guides(colour = guide_legend(nrow=2, byrow=TRUE)+
coord_fixed(ratio = 1))
ggsave(
filename=paste("snap",".png",sep = ""),
plot = one_plot,
device = "png",
path = here::here(),
width = 8, # Refers to the plot frame, not the area
height = 8, # Refers to the plot frame, not the area
units = "cm",
#dpi = 300,
#limitsize = FALSE,
bg = "white")
Что мне нужно, так это точки данных, заполненные цветом, используемым в настоящее время для их границы, и граница всех точек данных черного цвета.
Я попытался обойти эстетику, но в итоге получил дубликат легенды и еще большую путаницу.
Заранее еще раз спасибо за вашу помощь.
Я взял ваши данные и добавил переменную под названием group
, которая упрощает фильтрацию ggplot
.
Если вы определяете x
и y
в ggplot(..,aes())
, вам не нужно определять их снова в geom_point
.
В geom_point
вы уже задаете цвет Run_type
переменной, из которой должна быть составлена легенда. Поскольку вы используете в geom_ellipse
другое подмножество DF, легенда будет обновлена и снова сделает 4 записи легенды вместо 2 только для переменных. color = Run_type
поэтому можно пропустить.
Я добавил set.seed()
, что гарантирует сопоставимость результатов, хотя для составления DF генерируются случайные числа.
library(tidyverse)
set.seed(123)
gr1 <- (rep(paste("B-12-B-002"), 10))
gr2 <- (rep(paste("B-12-M-03"), 10))
gr3 <- (rep(paste("b-b-d-3"), 10))
gr4 <- (rep(paste("h-12-b-01"), 10))
Run_type <- c(gr1, gr2, gr3, gr4)
axial_ratio <- runif (40, 0, 1)
Solidity <- runif (40, 0, 1)
Convexity <- runif (40, 0, 1)
sel_data_all <- data.frame(Run_type, axial_ratio, Solidity, Convexity)
fill_colors <- c("red", "blue", "green", "orange")
df <- sel_data_all |> mutate(group = c(
rep("Data", 10), rep("Conf", 10),
rep("Data", 10), rep("Conf", 10)
))
ggplot(
data = df |> dplyr::filter(group == "Data"),
aes(x = axial_ratio, y = Solidity)
) +
geom_point(aes(color = Run_type, shape = Run_type),
stroke = 1,
size = 5, alpha = 0.4
) +
stat_ellipse(
data = df |> dplyr::filter(group != "Data"),
aes(
x = axial_ratio, y = Solidity,
fill = Run_type
),
geom = "polygon", alpha = 0.4, type = "norm", level = 0.6,
show.legend = FALSE
) +
scale_shape_manual(values = c(21, 21, 23, 23)) +
scale_fill_manual(values = fill_colors) +
scale_color_manual(values = fill_colors) +
coord_fixed(ratio = 1) +
theme(
legend.position = "top",
legend.key = element_rect(fill = "white"),
legend.title = element_blank(),
panel.background = element_rect(fill = "white", colour = "black"),
panel.grid.major = element_line(colour = "lightgrey"),
panel.grid.minor = element_line(colour = "lightgrey"),
axis.title.x = element_text(margin = margin(t = 10), size = 12, face = "bold"),
axis.title.y = element_text(margin = margin(r = 10), size = 12, face = "bold"),
axis.text = element_text(color = "black", size = 10),
axis.ticks.length = unit(-0.15, "cm"),
)
Затем график был сохранен с одинаковой шириной и высотой.
ggsave(
filename=paste("Axial_ratio","_vs_","Solidity",".png",sep = ""),
plot = last_plot(),
device = "png",
path = here::here(),
width = 8, # Refers to the plot frame, not the area
height = 8, # Refers to the plot frame, not the area
units = "cm",
#dpi = 300,
#limitsize = FALSE,
bg = "white")
сохраненный png выглядит так.
НОВОЕ ИЗМЕНЕНИЕ
Теперь я понимаю, что вам нужны два цвета для geom_points
и 2 разных цвета для stat_ellipse
.
Итак, ниже будет показана новая попытка. Если это правильный ответ, я удалю большую часть сверху, чтобы сделать этот пост более читаемым.
Вопрос с ggsave
считаю решенным.
Я определил два разных набора цветов; один для geom_point
и один для stat_ellipse
. (Определены 3 и 4 цвета, хотя позже в scale_color_manual
и scale_fill_manual
нужны только 2 цвета.)
Что касается как geom_point
, так и stat_ellipse
, используется другой DF, ggplot
вызывается без каких-либо data
или aes
. Оба будут определены индивидуально при вызове geom_point
и stat_ellipse
.
Для stat_ellipse
используется fill
, а для geom_point
color
используется как aes
.
Если вы хотите исключить ту или иную легенду, вы можете использовать
show.legend = F
в соответствующем geom
.
xlim
и ylim
определяют пределы осей.
guides()
и theme_bw()
убедитесь, что темный фон legend.key
стерт.
Я попытался сделать тему более краткой.
library(tidyverse)
set.seed(123)
gr1 <- (rep(paste("B-12-B-002"), 10))
gr2 <- (rep(paste("B-12-M-03"), 10))
gr3 <- (rep(paste("b-b-d-3"), 10))
gr4 <- (rep(paste("h-12-b-01"), 10))
Sample_ID <- c(gr1, gr2, gr3, gr4)
axial_ratio <- runif (40, 0, 1)
Solidity <- runif (40, 0, 1)
Convexity <- runif (40, 0, 1)
sel_data_all <- data.frame(Sample_ID, axial_ratio, Solidity, Convexity)
fill_colors_points <- c("#5bd9ca", "#1e99d6", "#1e49d6")
fill_colors_ellipse <- c("#f2581b80", "#e8811280", "#e3311280", "#fc000080")
sel_data_all <- sel_data_all |> mutate(Run_type = c(
rep("MAG", 10), rep("PMAG", 10),
rep("MAG", 10), rep("PMAG", 10)
))
ggplot() +
stat_ellipse(
data = sel_data_all |> dplyr::filter(Run_type == "MAG"),
aes(
x = axial_ratio, y = Solidity,
fill = Sample_ID
),
geom = "polygon", type = "norm",
level = 0.6, show.legend = T
) +
geom_point(
data = sel_data_all |> dplyr::filter(Run_type == "PMAG"),
aes(
x = axial_ratio, y = Solidity,
color = Sample_ID,
shape = Sample_ID
),
stroke = 0.5, size = 3,
) +
scale_color_manual(values = fill_colors_points[1:2]) + # of Data points
scale_fill_manual(values = fill_colors_ellipse[1:2]) + # of ellipses
xlim(0,1) + ylim(0,1) +
guides(color = guide_legend(override.aes = list(fill = NA))) +
theme_bw() +
theme(
legend.position = "top",
legend.key.size = unit(5, "mm"), # change legend key size
legend.text = element_text(size = 8),
legend.title = element_blank(),
panel.background = element_rect(fill = "white", colour = "black"),
panel.grid = element_line(colour = "lightgrey"),
axis.title.x = element_text(vjust = -1, size = 12, face = "bold"),
axis.title.y = element_text(vjust = 4, size = 12, face = "bold"),
axis.text = element_text(color = "black", size = 10),
axis.ticks.length = unit(-0.15, "cm"),
) +
coord_fixed(ratio = 1)
@Pier Volc
Добро пожаловать, рад, что смог помочь. Вы можете проголосовать за ответ. Если вы хотите добавить к эллипсу белую рамку, просто добавьте color = 'white'
к stat_ellipse
, но вне aes
. Добавление черной рамки к точкам возможно, но вы должны выбрать правильные формы. Те, между 21 и 25 имеют черные границы. Но затем вы должны определить fill
, и это может помешать fill
из эллипса. Вероятно, это сработает, но требует небольшой настройки - не уверен, что оно того стоит.
Большое спасибо еще раз. Я пытался проголосовать, но мне нужно как минимум 15 репутации :(
Большое спасибо! Это сработало как заклинание. Последний вопрос: если мне нужно будет добавить черную обводку вокруг точек и белую рамку вокруг эллипса, как мне это сделать? Спасибо большое, вы спаситель жизни!