Вопрос: Можно ли добавить к сюжету легенду, которая не имеет ничего общего с самим сюжетом и - что крайне важно - не будет мешать цветам на сюжете?
Объяснение
У меня есть вся необходимая информация для легенды. В частности, у меня есть шестнадцатеричные коды цветов и ярлыки. Мне все равно, какие фигуры показаны (линии, точки, в зависимости от того, что проще).
Я надеялся, что это поможет (это очень упрощенный минимальный рабочий пример):
the_colors <- c("#e6194b", "#3cb44b", "#ffe119", "#0082c8", "#f58231", "#911eb4", "#46f0f0", "#f032e6",
"#d2f53c", "#fabebe", "#008080", "#e6beff", "#aa6e28", "#fffac8", "#800000", "#aaffc3",
"#808000", "#ffd8b1", "#000080", "#808080", "#ffffff", "#000000")
the_labels <- c("01", "02", "03", "04", "05", "06", "07", "08", "09", "10")
the_df <- data.frame("col1"=c(1, 2, 2, 1), "col2"=c(2, 2, 1, 1), "col3"=c(1, 2, 3, 4))
the_plot <- ggplot() + geom_point(data=the_df, aes(x=col1, y=col2), color=the_colors[[4]])
the_plot <- the_plot +
scale_color_manual("Line.Color", values=the_colors[1:length(the_labels)],
labels=the_labels)
К сожалению, он даже не покажет легенду.
Играя по правилам и включая аргумент color
внутри элемента aesthetics
, я могу заставить его показать легенду.
the_plot <- ggplot() + geom_point(data=the_df, aes(x=col1, y=col2, color=the_colors[[4]]))
Но тогда, конечно, он больше не будет воспринимать значение, переданное как аргумент color
серьезным, а вместо этого будет интерпретировать его как некую метку и изменить цвет этих данные указывают на первый цвет в списке the_colors
. В то же время, он будет включать только этот в легенду, и, похоже, в аду нет способа убедить его в том, что он включает и другие.
На других языках это невероятно просто. В R / ggplot2 это кажется невероятно сложным.
Причина, по которой я хочу это сделать: Мне нужна легенда, которая не влияет на цвета в моем сюжете. Это иногда очень неудобно. Нет также более глубокой причины, по которой легенда должна связываться с цветами на графике, просто она реализована в R / ggplot2.
Подход: Я надеялся, что это способ легко сделать это, все еще рассматривая это как легенду. Если это не удастся, возможно, можно будет добавить поле с несколькими цветными точками и текстом, таким образом создавая легенду с нуля.
Другие вопросы: Были и другие вопросы, задающие то же самое предмет. Вместо этого в ответах предлагались обходные пути для решения конкретной проблемы ОП (обычно путем применения melt()
или около того) без предоставления решения поставленного вопроса (как добавить легенду вручную, не вмешиваясь в сюжет). Например, здесь и здесь . Это не то, что меня интересует. Я хотел бы знать, могу ли я добавить произвольную легенду к произвольному сюжету и, если да, то как.
Программное обеспечение: R 3.6. 3, ggplot2 3.2.1
Редактировать (30 марта 2020 г.):
Решение: Как описано в ответе @ Tjebo ниже, легенда о том, что является достаточно независимым от графика и определяет дополнительные ряды данных, не показанные на графике, могут быть созданы с помощью scale_color_identity
. С помощью опции # 1 в ответе @Tjebo я мог решить свою непосредственную проблему:
the_colors <- sort(c("#e6194b", "#3cb44b", "#ffe119", "#0082c8", "#f58231", "#911eb4", "#46f0f0", "#f032e6",
"#d2f53c", "#fabebe", "#008080", "#e6beff", "#aa6e28", "#fffac8", "#800000", "#aaffc3",
"#808000", "#ffd8b1", "#000080", "#808080"))
color_df <- data.frame(the_colors=the_colors[1:length(the_labels)], the_labels=the_labels)
the_df <- data.frame("col1"=c(1, 2, 2, 1), "col2"=c(2, 2, 1, 1), "col3"=c(1, 2, 3, 4))
the_plot <- ggplot() +
geom_point(data = color_df, aes(x = the_df$col1[[1]], y = the_df$col2[[1]], color = the_colors)) +
scale_color_identity(guide = 'legend', labels = color_df$the_labels)
the_plot <- the_plot +
geom_point(data=the_df, aes(x=col1, y=col2), color=the_colors[[4]])
print(the_plot)
Объяснение решения: В более общем смысле, как объясняет Tjebo, он отделяет сюжет от легенда. Легенда еще нуждается в сюжете. Сначала он строится следующим образом:
the_plot <- ggplot() +
geom_point(data = color_df, aes(x = the_df$col1[[1]], y = the_df$col2[[1]], color = the_colors)) +
scale_color_identity(guide = 'legend', labels = color_df$the_labels)
Созданный график все еще имеет неправильный цвет, но точки выбираются так, чтобы они были скрыты путем добавления графика, который я действительно хочу показать в соответствующем цвете:
the_plot <- the_plot +
geom_point(data=the_df, aes(x=col1, y=col2), color=the_colors[[4]])
Он также гибок в том, что можно добавлять дополнительные ряды данных в любом из цветов, которые предварительно определены в переменной the_colors
:
the_plot <- the_plot +
geom_point(data=the_df, aes(x=col1, y=col3), color=the_colors[[6]])
(Примечание. Ряд данных также может быть нанесен на график сразу, если цвет определен как третий столбец во фрейме данных. Я просто хотел отметить, что решение является гибким, и график может быть изменен позднее, не влияя на легенду или цвета точки данных, которые уже расположены на графике.)
Редактировать 2 (30 марта 2020 г.), Дополнительное примечание: При таком решении легенда сортирует цвета по их шестнадцатеричным кодам. Я не могу понять, почему он это делает, но это так. Таким образом, чтобы цвета в легенде соответствовали предполагаемым цветам, вектор шестнадцатеричных кодов должен быть отсортирован заранее (как это сделано в приведенном выше коде).
Неожиданное поведение, подобное этому, не будет проблемой при обычном использовании R и ggplot2 (когда вы разрешаете ggplot2 делать легенду за вас и строго ограничиваетесь тем, какие конструкции предназначены для использования). Это решение по сути является хакерским указанием на то, как легенда будет использоваться в ggplot2 (к сожалению, довольно ограниченно). Таким образом, возможно, что этот взлом будет сломан в будущих версиях ggplot или R.