Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

geom_point fill legend does not display the color with shapes

Tags:

r

ggplot2

I am confused of this problem for a long time. A simple data frame is constructed as follows

data <- data.frame(
  x = 1:5,
  y = 5:1,
  fill = c(rep("pink", 3), rep("blue", 2)),
  shape = c(rep(21, 3), rep(22, 2))
)

Suppose I wand to show the legend of the fill

uniFill <- unique(data$fill)
p <- ggplot(data,
       mapping = aes(x = x,
                     y = y,
                     fill = fill)) + 
  geom_point(shape = data$shape) + 
  # show legend so that I do not call `scale_fill_identity()`
  scale_fill_manual(values = uniFill,
                    labels = uniFill,
                    breaks = uniFill)
p

The graphics are OK, however, the legend is not correct

enter image description here

I guess, maybe different shapes (21 to 25) cannot be merged? Then, I partition the data into two subsets where the first set has shape 21 and the second has shape 22.

data1 <- data[1:3, ]
data2 <- data[4:5, ]
# > data1$shape
# [1] 21 21 21
# > data2$shape
# [1] 22 22
ggplot(mapping = aes(x = x,
                     y = y,
                     fill = fill)) + 
  geom_point(data = data1, shape = data1$shape) + 
  geom_point(data = data2, shape = data2$shape) + 
  scale_fill_manual(values = uniFill,
                    labels = uniFill,
                    breaks = uniFill)

Unfortunately, the legend does not change. Then, I changed the shape from a vector to a scalar, as in

ggplot(mapping = aes(x = x,
                     y = y,
                     fill = fill)) + 
  geom_point(data = data1, shape = 21) + 
  geom_point(data = data2, shape = 22) + 
  scale_fill_manual(values = uniFill,
                    labels = uniFill,
                    breaks = uniFill)

The legend of the fill color is correct finally...

enter image description here

So what happens here? Is it a bug? Is it possible to just add a single layer but with different shapes (21 to 25)?

A possible solution is that one can add component guides(), as in

p + 
  guides(fill = guide_legend(override.aes = list(fill = uniFill,
                                                 shape = 21)))

But I am more interested in why p does not work (legend)

like image 467
Zane Avatar asked Oct 28 '25 10:10

Zane


1 Answers

The main reason your legend is not working in your first example is because you did not put your shape in the aesthetics.

I have a couple other suggestions: Do not define colors in your data frame; instead define a column to change the aesthetics using a code. Then define your fill and shape values explicitly. Each of the scales needs to have the same name - in this case "Legend."

Give this edit a try.

data <- data.frame(
  x = 1:5,
  y = 5:1,
  fill = c(rep("p", 3), rep("b", 2))
 )

uniFill <- c("p"="pink", "b"="blue")
uniShape <- c("p" = 21, "b" = 22)

p <- ggplot(data,
            mapping = aes(x = x,
                          y = y,
                          fill = fill,
                          shape = fill)) + 
  geom_point() + 
  # show legend so that I do not call `scale_fill_identity()`
  scale_fill_manual("Legend",values = uniFill,
                    labels = uniFill)+
  scale_shape_manual("Legend",values = uniShape,
                     labels = uniFill)
p

(edit) If your fill and shape aesthetics do not match up, I don't see any other way than to use guides and two legends. Notice that if your attribute column is descriptive, you do not need to set the labels and your code will be cleaner (see shape vs fill aesthetics).

data <- data.frame(
  x = 1:5,
  y = 5:1,
  fill = c(rep("p", 3), rep("b", 2)),
  shape = c(rep("circles", 2), rep("squares", 3))
)

uniFill <- c("p"="pink", "b"="blue")
uniShape <- c("circles" = 21, "squares" = 22)

p <- ggplot(data,
            mapping = aes(x = x,
                          y = y,
                          fill = fill,
                          shape = shape)) + 
  geom_point() + 
  # show legend so that I do not call `scale_fill_identity()`
  scale_fill_manual("Legend fill",values = uniFill,
                    labels = uniFill)+
  scale_shape_manual("Legend shape",values = uniShape  )+
  guides(fill = guide_legend("Legend fill", override.aes = list(shape = 21)))
p

point plot with two legends

like image 113
Dan Slone Avatar answered Oct 31 '25 02:10

Dan Slone



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!