Как объединить цвета, стиль и легенды формы в ggplot
Предположим, у меня есть следующий график в ggplot:
![ggplot graph]()
Он был сгенерирован с использованием следующего кода:
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df.merged <- rbind(df1, df2, df3, df4)
ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
Я хотел бы иметь только одну легенду, которая правильно отображает фигуры, цвета и типы линий (легенды взаимодействия (тип, метод) наиболее близки к тому, что я хотел бы, но у них нет правильных форм/типов линий),
Я знаю, что если я использую scale_xxx_manual, и я укажу те же метки для всех легенд, они будут объединены, но я не хочу устанавливать метки вручную: если есть новые методы или типы, я не хочу иметь изменить мой код: нужно что-то общее.
редактировать
Как указано в ответах ниже, есть несколько способов сделать работу в этом конкретном случае. Все предлагаемые решения требуют вручную устанавливать типы и формы линий легенды либо с помощью scale_xxx_manual function
, либо с помощью scale_xxx_manual function
guides
.
Однако предлагаемые решения все еще не работают в общем случае: например, если я добавлю новый кадр данных в набор данных с помощью нового метода method3, он больше не работает, мы должны вручную добавить новый формы легенды и типы линий:
y5 <- sin(x - pi / 4)
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
df.merged <- rbind(df1, df2, df3, df4, df5)
override.shape <- c(16, 17, 16, 17, 16)
override.linetype <- c(1, 1, 3, 3, 4)
g <- ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
g <- g + guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype)))
g <- g + scale_shape(guide = FALSE)
g <- g + scale_linetype(guide = FALSE)
print(g)
Это дает:
![5 curves]()
Теперь возникает вопрос: как автоматически генерировать векторы override.shape
и override.linetype
?
Обратите внимание, что размер вектора равен 5, потому что у нас есть 5 кривых, а коэффициент interaction(Type, Method)
имеет размер 6 (у меня нет данных для комбинации cos/method3)
Ответы
Ответ 1
Вот решение в общем случае:
# Create the data frames
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
y5 <- sin(x - pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
# Merge the data frames
df.merged <- rbind(df1, df2, df3, df4, df5)
# Create the interaction
type.method.interaction <- interaction(df.merged$Type, df.merged$Method)
# Compute the number of types and methods
nb.types <- nlevels(df.merged$Type)
nb.methods <- nlevels(df.merged$Method)
# Set the legend title
legend.title <- "My title"
# Initialize the plot
g <- ggplot(df.merged, aes(x,
y,
colour = type.method.interaction,
linetype = type.method.interaction,
shape = type.method.interaction)) + geom_line() + geom_point()
# Here is the magic
g <- g + scale_color_discrete(legend.title)
g <- g + scale_linetype_manual(legend.title,
values = rep(1:nb.types, nb.methods))
g <- g + scale_shape_manual(legend.title,
values = 15 + rep(1:nb.methods, each = nb.types))
# Display the plot
print(g)
В результате получается следующее:
![The solution]()
- Кривые синуса рисуются сплошными линиями и кривыми косинуса как пунктирные линии.
- Данные "method1" используют заполненные круги для формы.
- "method2" использует треугольник для формы.
- Данные "method3" используют заполненные алмазы для формы.
- Легенда соответствует кривой
Подводя итог, трюки:
- Используйте
interaction
Тип/Метод для всех представлений данных (цвет, форма, тип линии и т.д.). - Затем вручную задайте стили кривой и стили легенд с помощью
scale_xxx_manual
. -
scale_xxx_manual
позволяет вам предоставить вектор значений, который длиннее фактического числа кривых, поэтому легко вычислить значения вектора стиля из размеров факторов типа и метода
Ответ 2
У меня была эта проблема на днях. Раздел R Cookbook в разделе " Легенды" объясняет:
Если вы используете как цвет, так и форму, им нужно дать спецификации масштаба. В противном случае будет две две отдельные легенды.
В вашем случае вам нужны спецификации для shape
и linetype
.
редактировать
Было важно иметь те же данные, которые создают цвета и линии фигур, я объединил вашу фазу взаимодействия, напрямую определяя столбец. Вместо scale_linetype_discrete
для создания легенды я использовал scale_linetype_manual
для указания значений, поскольку по умолчанию они будут принимать по четыре разных значения.
Если вам нужна подробная схема всех возможных форм и типов линий, проверьте этот сайт R Graphics, чтобы увидеть все идентификаторы номеров:
df.merged$int <- paste(df.merged$Type, df.merged$Method, sep=".")
ggplot(df.merged, aes(x, y, colour = int, linetype=int, shape=int)) +
geom_line() +
geom_point() +
scale_colour_discrete("") +
scale_linetype_manual("", values=c(1,2,1,2)) +
scale_shape_manual("", values=c(17,17,16,16))
![enter image description here]()
Ответ 3
Приведенный ниже код приводит к желаемой легенде, если я понимаю ваш вопрос, но я не уверен, что понимаю проблему с ярлыком, поэтому дайте мне знать, если это не то, что вы искали.
p = ggplot(df.merged, aes(x, y, colour=interaction(Type, Method),
linetype=interaction(Type, Method),
shape=interaction(Type, Method))) +
geom_line() +
geom_point()
p + scale_shape_manual(values=rep(16:17, 2)) +
scale_linetype_manual(values=rep(c(1,3),each=2))
![enter image description here]()
Ответ 4
Нужно просто назвать оба направителя одинаковыми. Например:
g+ scale_linetype_manual(name="Guide1",values= c('solid', 'solid', 'dotdash'))+
scale_colour_manual(name="Guide1", values = c("blue", "green","red"))
Ответ 5
Используйте labs()
и установите одинаковое значение для всей эстетики, определяющей внешний вид геометрий.
library('ggplot2')
ggplot(iris) +
aes(x = Sepal.Length, y = Sepal.Width,
color = Species, linetype = Species, shape = Species) +
geom_line() +
geom_point() +
labs(color = "Guide name", linetype = "Guide name", shape = "Guide name")
![]()