Spencer Graves
Spencer Graves

Reputation: 111

How to specify color with geom_line, geom_point, and annotate in ggplot2?

I'm trying to modify Jeff Lewis (2023-10-23) Polarization in Congress, and I cannot control the color in geom_line and geom_point.

The following seems to be the closest I've come to what I want with a subset of 12 of his 2774 points:

library(ggplot2)
PolarDatSmpl <- data.frame(
  year=rep(c(1879, 1951, 2023), 4), 
  chamber=rep(c('House', 'Senate'), e=3, len=12), 
  party=rep(c('DEM', 'REP'), e=6), 
  value=c(-.39, -.26, -.38, -.45, -.20, -.35, 
           .40,  .28,  .51,  .30,  .28,  .55) )

PolarDatSmpl$pc <- with(PolarDatSmpl, 
    interaction(party, chamber))
  
# I want lines and points labeled with colors 
# and text 

PolarColors <- data.frame(
  chamber=rep(c('House', 'Senate'), e=2), 
  party=rep(c('DEM', 'REP'), 2), 
  Color=c('blue', 'red', 'darkblue', 'darkred'), 
  yearTxt=c(1960.3, 1944.3, 1961, 1945),  
  yearPch=c(1944.3, 1927.8, 1944, 1928), 
  value=c(-.4, .5, -.33, .4) )

#value=c(-.5, .4, -.43, .35) )
#c(.5, .4, -.43, -.35) 
PolarColors$pc <- with(PolarColors, 
    interaction(party, chamber))
rownames(PolorColors) <- PolarColors$pc

PolarDatSmpl$Color <- PolarColors[
  PolarDatSmpl$pc, 'Color']

p1 <- ggplot(data=PolarDatSmpl, 
    aes(x=year, y=value, group=pc, color=Color)) +
  theme_bw() + 
  theme(legend.position='none') + 
  geom_line() + geom_point(mapping=aes(
    shape=factor(chamber) )) 

# What do I need to do to get the desired colors? 

p2 <- p1 + with(PolarColors, annotate('text', 
    x=yearTxt, y=value, label=pc, color=Color)) + 
  geom_point(PolarColors, mapping = aes( 
    x=yearPch, y=value, shape=factor(chamber) ))
p2

This gives me everything I want EXCEPT for the color of points and lines. I can specify the color with annotate and a companion cal to geom_plot to put a legend where I want it, but I have failed to control the line color. (I once got the points and lines colored, but that broke when I added annotate.)

Suggestions? Thanks, Spencer Graves

Upvotes: 1

Views: 58

Answers (2)

L Tyrone
L Tyrone

Reputation: 7065

To use R colour names/hex values from a df column, use scale_color_identity(). Note that the default behaviour for scale_color_identity() is to not create a legend, but you still need theme(legend.position = "none") to suppress the shape aesthetic legend.

library(ggplot2)

ggplot(data = PolarDatSmpl,
       aes(year, value, group = pc, colour = Color)) +
  geom_line() +
  geom_point(aes(shape = factor(chamber))) +
  geom_point(data = PolarColors, 
             aes(yearPch, value, group = pc, color = Color, shape = factor(chamber))) +
  with(PolarColors,
       annotate('text', yearTxt, value, label = pc, color = Color)) + 
  scale_color_identity() +
  theme_bw() +  
  theme(legend.position = "none")

1

Based on your comment, using geom_text():

ggplot(data = PolarDatSmpl,
       aes(year, value, group = pc, colour = Color)) +
  geom_line() +
  geom_point(aes(shape = factor(chamber))) +
  geom_point(data = PolarColors, 
             aes(yearPch, value, group = pc, color = Color, shape = factor(chamber))) +
  geom_text(data = PolarColors,
            aes(yearPch, value, label = pc, color = Color),
            hjust = 0,
            nudge_x = 2) + 
  scale_color_identity() +
  theme_bw() +  
  theme(legend.position = "none")

Upvotes: 1

Spencer Graves
Spencer Graves

Reputation: 111

Using geom_point()+geom_text() instead of annotate()

It's easier to specify the joint position of symbol and text using geom_point()+geom_text() instead of annotate(). This can be done as follows:

PolarDatSmpl <- data.frame(
  year=rep(c(1879, 1951, 2023), 4), 
  chamber=rep(c('House', 'Senate'), e=3, len=12), 
  party=rep(c('DEM', 'REP'), e=6), 
  value=c(-.39, -.26, -.38, -.45, -.20, -.35, 
           .40,  .28,  .51,  .30,  .28,  .55) )

PolarDatSmpl$pc <- with(PolarDatSmpl, 
    interaction(party, chamber))
  
# I want lines and points labeled with colors 
# and text 

PolarColors <- data.frame(
  chamber=rep(c('House', 'Senate'), e=2), 
  party=rep(c('DEM', 'REP'), 2), 
  Color=c('blue', 'red', 'darkblue', 'darkred'), 
  yearTxt=c(1960.3, 1944.3, 1961, 1945),  
  yearPch=c(1944.3, 1927.8, 1944, 1928), 
  value=c(-.4, .5, -.33, .4) )

PolarColors$pc <- with(PolarColors, 
    interaction(party, chamber))
rownames(PolarColors) <- 
  as.character(PolarColors$pc)

PolarDatSmpl$Color <- PolarColors[
  PolarDatSmpl$pc, 'Color']

P1 <- ggplot(data = PolarDatSmpl,
       aes(x = year, y = value, group = pc, color = Color)) +
  geom_line() +
  geom_point(aes(shape = factor(chamber))) +
  geom_point(PolarColors, mapping = aes(x = yearPch, 
      y = value, shape = factor(chamber))) +
  scale_color_identity() +
  theme_bw() +  theme(legend.position = "none")

P2 <- P1 + geom_point(PolarColors, mapping=
        aes(x=yearPch, y=value, group=pc, 
            color=Color, shape = factor(chamber))) 

P2 + geom_text(PolarColors, mapping=aes(
          x=yearPch, y=value, group=pc, color=Color), 
       label=PolarColors$pc, hjust = 0, nudge_x = 2)

It took me a while to figure this out. I provide it here in case it might help someone else.

Upvotes: 1

Related Questions