Home > other >  ggplot: how to assign both color and shape for one factor, and also shape for another factor?
ggplot: how to assign both color and shape for one factor, and also shape for another factor?

Time:02-01

I must code factor age with both color and shape. I know how to do that (see the plot and data/code below).

In addition, I also have to code factor day with shape.

Is it somehow possible to assign specified different shapes to two different factors?

Below is the legend I would love to achieve (I made an example in power point). The plot is not quite right, as only factor age is coded with color and shape.

enter image description here

df = data.frame(test = c(1,2,3, 1,2,3, 1,2,3,  1,2,3, 1,2,3, 1,2,3),
                age = c(1,1,1, 2,2,2, 3,3,3,   1,1,1, 2,2,2, 3,3,3),
                day = c(1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2),
                result = c(1,2,2,1,1,2,2,1,0, 2,2,0,1,2,1,2,1,0))

df$test <- factor((df$test))
df$age <- factor((df$age))
df$day <- factor((df$day))

windows(width=4, height=3 )

df %>%
  ggplot( aes(x=test, y=result))  
  geom_point(aes(color=age, shape=age, group=age), 
             position=position_jitterdodge(dodge.width=0.8,jitter.height=0.2, jitter.width=0), 
             size=2, stroke=0.8)   
  scale_shape_manual(values=c(16, 15, 17), name="", labels=c("young","older","the oldest"))  
  scale_color_manual(name="", labels=c("young","older","the oldest"), values=c('#009E73','#56B4E9','#D55E00'))  
  
  theme_bw() 
  theme(panel.border = element_blank(), axis.ticks = element_blank(),
        legend.position=c(), legend.text=element_text(size=10, face="bold"), legend.title=element_text(size=10),
        panel.grid.major.x = element_blank() ,
        panel.grid.major.y = element_blank() ,
        plot.title = element_text(size=10, face = "bold"), axis.title=element_text(size=11),
        axis.text.y = element_text(size=9, angle = 45), 
        axis.text.x = element_text(size=9, angle = 90),
        plot.margin = unit(c(0.5,0.2,0,0), "cm"))  
  
  labs(title= "", x = "",y = "Test result")  
  scale_y_continuous(breaks=c(0,1,2), labels=c('good','better','the best'))  
  geom_vline(xintercept=c(0.5,1.5,2.5),color="grey90") 
  geom_hline(yintercept=-0.5, color="grey90") 
  expand_limits(x=3.9, y=c(0,2.35))  
  scale_x_discrete(limits = c("1", "2", "3"),labels = c("test a", "test b", "test c"))   
  coord_cartesian(clip = "off") 

CodePudding user response:

So again following: Filled and hollow shapes where the fill color = the line color the following code provides the goods without giving you the legend.

df %>%
  ggplot( aes(x=test, y=result))  
  geom_point(aes(color=age, 
                 shape=age, 
                 group=age,
                 fill=factor(ifelse(day==1, NA, age))), # STEP 1
             position=position_jitterdodge(dodge.width=0.8,jitter.height=0.2, jitter.width=0), 
             size=2, stroke=0.8)   
  scale_shape_manual(values=c(22,21,24), name="", labels=c("young","older","the oldest"))  
  scale_color_manual(name="", labels=c("young","older","the oldest"), values=c('#009E73','#56B4E9','#D55E00'))  
  scale_fill_manual(name="",
                      labels=c("young","older","the oldest"), 
                      values=c('#009E73','#56B4E9','#D55E00'), 
                      na.value=NA, guide="none") # STEP 2

I was misleading in my comment, rather than "hallow" shapes, we want shapes 21 through 26. These apparently accept distinct fill and color.

CodePudding user response:

You can use shapes on an interaction between age and day, and use color only one age. Then remove the color legend and color the shape legend manually with override.aes.

This comes close to what you want - labels can be changes, I've defined them when creating the factors.

In a few minutes I'll show a solution with a proper legend.

library(ggplot2)
df = data.frame(test = c(1,2,3, 1,2,3, 1,2,3,  1,2,3, 1,2,3, 1,2,3),
                age = c(1,1,1, 2,2,2, 3,3,3,   1,1,1, 2,2,2, 3,3,3),
                day = c(1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2),
                result = c(1,2,2,1,1,2,2,1,0, 2,2,0,1,2,1,2,1,0))

df$test <- factor(df$test)
## note I'm changing this here already!! If you udnergo the effor tof changing to
## factor, define levels and labels here
df$age <- factor(df$age, labels = c("young", "older", "the oldest"))
df$day <- factor(df$day, labels = paste("Day", 1:2))

ggplot(df, aes(x=test, y=result))  
  geom_jitter(aes(color=age, shape=interaction(day, age)),
              width = .1, height = .1)  
  ## you won't get around manually defining the shapes
  scale_shape_manual(values = c(0, 15, 1, 16, 2, 17))  
  scale_color_manual(values = c('#009E73','#56B4E9','#D55E00'))  
  guides(color = "none", 
         shape = guide_legend(
          override.aes = list(color = rep(c('#009E73','#56B4E9','#D55E00'), each = 2)),
          ncol = 3))

Created on 2022-01-31 by the reprex package (v2.0.1)

  •  Tags:  
  • Related