#r #ggplot2
Вопрос:
Я хотел бы, чтобы ggplot взял цвет и эстетику этикетки из строящегося фрейма данных. Я понимаю, что вы можете использовать scale_colour_identity()
для получения цвета из data.frame ( col
столбец ниже), но я не уверен, как заставить его также читать пользовательские метки ( lab
столбец ниже).
Примечание: Я ценю, что вы можете сделать это, жестко закодировав метки и цвета сценария (набор manual
команд в ggplot). Тем не менее, я хочу избежать жесткого кодирования этих вещей в сценарии R (что мне кажется плохой практикой кодирования), потому что мне сложнее использовать те же метаданные построения в сценарии Python (или другом сценарии R), например. Я ценю, что вы также можете добавить цвета в сценарий R и использовать их в качестве источника (), но тогда возникает та же проблема при попытке использовать согласованные цвета в графиках Python.
require(ggplot2)
set.seed(42)
# Define test dataset
n_trt <- 3
n_samples <- 5
cols <- c("#F2762E", "#F2AB27", "#4F8C11")
df <- data.frame(
trt = rep(LETTERS[1:n_trt], each = n_samples),
response_x = rep(rnorm(n_trt), each = n_samples) runif(n_trt*n_samples),
response_y = rep(rnorm(n_trt), each = n_samples) runif(n_trt*n_samples),
col = rep(cols, each = n_samples),
lab = rep(paste0(LETTERS[1:n_trt], letters[1:n_trt]), each = n_samples))
#> print(head(df))
# trt response_x response_y col lab
#1 A 2.1075468 -0.1803944 #F2762E Aa
#2 A 1.5056250 -0.6391629 #F2762E Aa
#3 A 2.0279507 -0.2501283 #F2762E Aa
#4 A 2.0760232 -0.3485370 #F2762E Aa
#5 A 1.8287002 -0.2750774 #F2762E Aa
#6 B 0.1544141 2.0014811 #F2AB27 Bb
# Plotting routine
p <- ggplot(df, aes(x = response_x, y = response_y,
color = col, labels = lab, group = lab))
geom_point(size = 2.5)
scale_colour_identity(guide = "legend", aes(labels = lab))
theme_bw()
theme(legend.position = "top")
ggsave("test.png", p, width = 6, height = 4)
Ответ №1:
Управляйте своими надписями с помощью отдельного слоя.
Чтобы метки не перекрывались с вашими точками, вы можете смещать их с помощью nudge_x или nudge_y.
Если у вас возникнут проблемы с перекрывающимися метками, ознакомьтесь с geom_text_repel().
p <- ggplot(df, aes(x = response_x, y = response_y,
color = col, labels = lab, group = lab))
geom_point(size = 2.5)
geom_text(aes(label = lab), nudge_x = 0.2)
scale_colour_identity(guide = "legend", aes(labels = lab))
theme_bw()
theme(legend.position = "top")
p
Комментарии:
1. Спасибо за комментарий. Я искал общее решение, в котором они помечены в легенде (например, test.png в вопросе). Добавление меток на рисунке неприменимо для других геом (например, линий) или в нетривиальных наборах данных, содержащих 100 точек.
2. нет проблем @p-робот. Вы заметили решение своей проблемы, которое не было очевидно из вашего вопроса. Здорово.
Ответ №2:
Можно использовать unique()
с _manual_
набором функций, но это зависит от упорядоченного поведения unique()
, которое не является идеальным.
df$col <- as.character(df$col)
df$lab <- as.character(df$lab)
# Plotting routine
p <- ggplot(df, aes(x = response_x, y = response_y, group = lab))
geom_point(aes(color = lab), size = 2.5)
theme_bw()
scale_color_manual(name = "", values = unique(df$col), labels = unique(df$lab))
theme(legend.position = "top")
ggsave("test.png", p, width = 6, height = 4)
Комментарии:
1. в принципе, вы нашли способ сделать это. Имейте в виду, что вы можете предоставить
values
иlabels
то, что хотите контролировать_manual
. Таким образом, вы можете задать значения/метки с помощью вектора. Очевидно, что это делается вручную, и такая функция, как unique (), не поможет. Но вы можете работать с факторами или упорядочивать векторные элементы по-другому. Надеюсь, это поможет.
Ответ №3:
Вместо использования unique()
вы можете передать нужные цвета и метки в виде именованного вектора scale_color_manual
, который гарантирует, что цвета будут назначены правильным категориям. Поскольку у вас есть цвета и метки внутри фрейма данных, вы можете использовать dplyr::distinct
и tibble::deframe
создавать именованные векторы таким образом:
require(ggplot2)
library(dplyr)
cols <- dplyr::distinct(df, trt, col) %>% tibble::deframe()
cols
#> A B C
#> "#F2762E" "#F2AB27" "#4F8C11"
labs <- dplyr::distinct(df, trt, lab) %>% tibble::deframe()
labs
#> A B C
#> "Aa" "Bb" "Cc"
# Plotting routine
ggplot(df, aes(x = response_x, y = response_y, color = trt))
geom_point(size = 2.5)
scale_colour_manual(values = cols, labels = labs)
theme_bw()
theme(legend.position = "top")