简体   繁体   中英

ggplot2 fill legend does not display the correct “fill” color

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

在此处输入图片说明

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

在此处输入图片说明

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)

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

带有两个图例的点图

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM