Como mesclar cor, estilo de linha e legendas de forma em ggplot

Suponha que eu tenha o seguinte gráfico em ggplot:

gráfico ggplot

Foi gerado usando o código abaixo:

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() 

Eu gostaria de ter apenas uma legenda que exibe corretamente as formas, as colors e os tipos de linha (as legendas de interação (Type, Method) são as mais próximas do que eu gostaria, mas não tem os formatos / tipos de linha corretos) .

Eu sei que se eu usar scale_xxx_manual e eu especificar os mesmos labels para todas as legendas eles serão mesclados, mas eu não quero ter que definir os labels manualmente: se houver novos methods ou tipos, eu não quero ter para modificar meu código : um desejo algo genérico.

Editar

Como apontado nas respostas abaixo, existem várias maneiras de realizar o trabalho neste caso específico. Todas as soluções propostas exigem a configuração manual dos tipos e formas da linha de legenda, usando a scale_xxx_manual function s ou com a function de guides .

No entanto, as soluções propostas ainda não funcionam no caso geral: por exemplo, se eu adicionar um novo quadro de dados ao dataset com um novo método “method3”, ele não funciona mais, temos que adicionar manualmente o novo formas de legenda e tipos de linha:

 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) 

Isto dá:

5 curvas

Agora a questão é: como gerar automaticamente os vetores override.linetype e override.linetype ?

Observe que o tamanho do vetor é 5 porque temos 5 curvas, enquanto o fator de interaction(Type, Method) tem tamanho 6 (não tenho dados para a combinação cos / método3)

Eu tive esse problema no outro dia. A seção R Cookbook on Legends explica:

Se você usar cor e forma, ambos precisam receber especificações de escala. Caso contrário, haverá duas duas legendas separadas.

No seu caso, você precisa de especificações para shape e tipo de linetype .

Editar

Era importante ter os mesmos dados criando as formas de colors e linhas, combinei sua fase de interação definindo a coluna diretamente. Em vez de scale_linetype_discrete para criar a legenda, usei scale_linetype_manual para especificar os valores, pois eles assumem quatro valores diferentes por padrão.

Se você quiser um layout detalhado de todas as possíveis formas e tipos de linha, verifique este site R Graphics para ver todos os identificadores numéricos:

 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)) 

insira a descrição da imagem aqui

O código abaixo resulta na legenda desejada, se eu entendi sua pergunta, mas não tenho certeza de que entendi o problema da etiqueta. Então, informe-me se não é isso que você estava procurando.

 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)) 

insira a descrição da imagem aqui

Aqui está a solução no caso geral:

 # 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) 

O resultado é o seguinte:

A solução

  • As curvas de sinus são desenhadas como linhas sólidas e curvas cosinus como linhas tracejadas.
  • Os dados "method1" usam círculos preenchidos para a forma.
  • Os dados do "método2" usam um triângulo preenchido para a forma.
  • Os dados "method3" usam diamantes preenchidos para a forma.
  • A legenda corresponde à curva

Para resumir, os truques são:

  • Use a interaction Tipo / Método para todas as representações de dados (cor, forma, tipo de linha, etc.)
  • Em seguida, defina manualmente os estilos de curva e os estilos de legendas com scale_xxx_manual .
  • scale_xxx_manual permite que você forneça um vetor de valores que seja maior do que o número real de curvas, por isso é fácil calcular os valores de vetor de estilo dos tamanhos dos fatores Tipo e Método.

Um só precisa nomear os dois guias o mesmo. Por exemplo:

 g+ scale_linetype_manual(name="Guide1",values= c('solid', 'solid', 'dotdash'))+ scale_colour_manual(name="Guide1", values = c("blue", "green","red")) 

Use labs() e defina o mesmo valor para todas as estéticas que definem a aparência das geometrys.

 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")