Change shape with line on legend ggplot2

cortapato

I'm new with R and I'm trying to plot a graph with some legend, the problem is I can't change the "shape-line" icon with another shape, it just make another legend, the correct icon should be the "triangle-line" and the "square-line"

library(lubridate)
library(ggplot2)
library(tidyverse)
ano <- c(1999:2019)
comeco <- mdy("01-01-1999")
fim <- mdy("01-01-2019")
por <- "1 year"

x <- seq(comeco, fim, by = por)
ano <- x
inferior <- c(6, 4, 2, 1.5, 1.5, 3, 2, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 3, 3, 2.75)
superior <- c(10, 8, 6, 5.5, 6.5, 8, 7, 6.5, 6.5, 6.5, 6.5, 6.5, 6.5, 6.5, 6.5, 6.5, 6.5, 6.5, 6, 6, 5.75)
meta <- c(8, 6, 4, 3.5, 4, 5.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.25)
inflacao <- c(8.94, 5.97, 7.67, 12.53, 9.3, 7.6, 5.69, 3.14, 4.46, 5.9, 4.31, 5.91, 6.5, 5.84, 5.91, 6.41, 10.67, 6.29, 2.95, 3.75, 4.31)

df1 <- data.frame(ano, inferior, superior, inflacao, meta)

df1 %>% 
  ggplot(aes(ano, inflacao)) +
  theme(text = element_text(family = "serif")) +
  theme(axis.text = element_text(size = 8)) +
  theme(legend.title = element_blank()) +
  labs(
    x = "Anos",
    y = "Taxa (%)"
  ) +
  scale_x_date(date_labels = "%Y", breaks = df1$ano) + 
  theme(axis.text.x = element_text(vjust = 0)) +
  theme(axis.title.x = element_text(vjust = -1)) +
  theme(legend.position = "top") +
  
  geom_line(aes(x = ano, y = meta, linetype = "Meta de Inflação")) +
  geom_line(aes(x = ano, y = inflacao, linetype = "Inflação Efetiva"), size = 0.5) +
  
  geom_point(aes(x = ano, y = superior, color = "Limite Superior", shape = "Limite Superior"), size = 2) +
  geom_line(aes(x = ano, y = superior, color = "Limite Superior"), size = 0.5) +
  
  geom_point(aes(x = ano, y = inferior, color = "Limite Inferior", shape = "Limite Inferior"), size = 2) +
  geom_line(aes(x = ano, y = inferior, color = "Limite Inferior"), size = 0.5) +
  
  scale_color_manual(values = c("Meta de Inflação" = "black", "Inflação Efetiva" = "black", 
                                "Limite Superior" = "blue", "Limite Inferior" = "black")) +
  scale_linetype_manual(values = c("Meta de Inflação" = "solid", "Inflação Efetiva" = "dashed",
                                   "Limite Superior" = "solid", "Limite Inferior" = "solid")) +
  scale_shape_manual(values = c("Limite Superior" = 17, "Limite Inferior" = 15))

enter image description here

chemdork123

I would highly suggest you check out this vignette on Tidy Data, which is a conceptual way to organize your datasets to be easier to plot and analyze. This is the basis of the "tidyverse", which includes packages like ggplot2. While I can help you combine your legends given your existing dataset, df1, it will be much much easier if we reshape your data frame to be "tidy" and then use that. I'll show you that approach here.

Tidying-up Your Data

A general priciple of tidy data is that you should not have your data "spread" out over multiple columns when it shows the same type of value. In your case, you have ano, which shows the date and is just fine. The rest of your columns are all filled with values for "taxa", with each column representing a different way you would identify that particular "taxa". We need to therefore first gather together these other columns such that your dataset now reads with 3 columns: ano | type | taxa. Overall, this means your data frame is much "longer" (more observations/rows). You can do this a number of ways, but I'm showing here one way I typically use, which is to use the gather() function from the dplyr package. It's all part of the tidyverse package though:

df1 <- df1 %>% gather(key='type', value='taxa', -c(ano))

You should be able to follow that, but basically we're telling gather() to ignore the ano column, and for the rest, push the column names into a new column (key=) called "type", and put the values in those cells into a new column (value=) called "taxa".

Plotting Your Data

For the plot, it becomes a lot simpler. You only need one line for each geom call, and we will be assigning the shapes, colors, and values. Before we do that, I'm going to create a named vector that's going to make it easier to specify how we want the legend labels to look like for any of the values in df1$type:

my_labels <- c(
  'superior'='Limite Superior',
  'inferior'='Limite Inferior',
  'meta'='Meta de Inflação',
  'inflacao'='Inflação Efetiva'
)

For the plot code, I'll show you the code and plot, then explain a bit on how it works:

df1 %>% 
  # plot mapping and geoms
  ggplot(aes(ano, taxa)) +
  geom_line(aes(linetype = type, color = type), size = 0.5) +
  geom_point(aes(color = type, shape = type), size = 2) +
  
  # scale functions
  scale_x_date(date_labels = "%Y", breaks = df1$ano) +
  scale_color_manual(values = c(
    "meta" = "black", "inflacao" = "black", "superior" = "blue", "inferior" = "black"),
    labels=my_labels) +
  scale_linetype_manual(values = c(
    "meta" = "solid", "inflacao" = "dashed", "superior" = "solid", "inferior" = "solid"),
    labels=my_labels) +
  scale_shape_manual(values = c(
    "meta"=NA, "inflacao"=NA, "superior"=17, "inferior"=15),
    labels=my_labels) +
  
  # labeling and theme elements
  labs(
    x = "Anos",
    y = "Taxa (%)"
  ) +
  
  theme(
    text = element_text(family = "serif"),
    axis.text = element_text(size = 8),
    legend.title = element_blank(),
    axis.text.x = element_text(vjust = 0),
    axis.title.x = element_text(vjust = -1),
    legend.position = "top"
  )

enter image description here

I like to organize my plot code into specific sections that are dedicated to the main parts of the plot.

Plot mapping and geoms

This part is where we specify how the dataframe is transformed into specific geoms. Note that since we have a nice and tidy data frame, all we need to do is specify one y aesthetic (taxa), and use type as the aesthetic mapped to shape, color, and linetype. We will then specify within the scale_ functions our preferred values to be associated with our mapping. Note that all aesthetics for which we want to have differentiated in our legend are included within aes().

Scale Functions

This part of the code is where we supply values and specify colors to all the aesthetics we mapped in the first part of the plot code. You also can specify labels here. I could have changed the label by first converting df1$type to a factor before plotting, but I prefer doing this here just because it's a bit more straightforward with so many specific mappings. This is why we first created the my_labels named vector. Note that you need to specify the labeling identically for each scale_ function. If not or if there is a difference in title, you will force ggplot2 to separate the legends and you'll get something similar to what you showed when you started.

In order to not show points for two of the type lines, I am specifying the shape value to be NA for both of those type values. So in the final plot, the points are actually drawn for everything, but for these, they are drawn with a shape=NA... in other words, they are invisible. :)

Theme Elements and Labels

The final part of the plot is where I put all the theme and generalized plot labels. You will note that it's good practice to combine all the theme elements into one call to theme().

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related