wdchild
wdchild

Reputation: 51

applying custom color function to plots in R

I'm trying to apply a custom color function to barplots that take in a dataframe. Teams are associated with a color, and depending on the year from which the data is taken, team colors will have a different opacity. So in 2000, the red team would have full opacity, and in 2020, it would have 50% opacity (but the same base color). I've tried passing in rgb formats and hashed values (#FF0011) all to no avail. This was from a shiny app, but I created a reprex to highlight the issue. Thanks in advance.

# team performances in year 2000 and 2020
teams <- c('A2000', 'B2000', 'C2000', 'D2000', 'A2020', 'B2020', 'C2020', 'D2020')
performance  <- c(10, 3, 5, 4, 7, 8, 9, 2)
team_color <- c(1, 2, 3, 4, 5, 6, 7, 8)
df <- data.frame(teams, performance, team_color) 

base_colors <- c("darkgoldenrod2", "darkblue", "darkred","darkcyan")

lighten_color <- function(color_name, opacity = 50, newname = NULL) {
  rgb.val <- col2rgb(color_name)   ## Get RGB values for named color

  # Make new color using input color as base and alpha set by transparency
  lighter_color <- rgb(rgb.val[1], rgb.val[2], rgb.val[3],
                       max = 255,
                       alpha = opacity * 255 / 100,
                       names = newname)
  return(lighter_color) # not clear if I need to "unlist"
}

# Function so that "reds" will be associated with one team, "blues" with another, ...
choose_color <- function(color_num) {
  if (color_num < 5) { # If from the first year (numbers 1-4) will use a base color as is.
    named_color <- base_colors[color_num]
    rgb_color <- col2rgb(named_color)
    hash_color <- rgb(rgb_color[1,1], rgb_color[2,1], rgb_color[3,1], max=255, alpha = 255, names = '')
  }
  else { # Otherwise, you compute the base color by subtracting 4 and alter opacity
    team_base_color <- color_num - 4
    perf_color <- base_colors[team_base_color]
    hash_color <- lighten_color(perf_color, opacity = 50)
  }
  return(unlist(hash_color))
}

# fails (all bars in red) if I try to apply the function to the barplot
barplot(performance ~ teams, data = df, 
        col = choose_color(team_color)) 
       # also tried col = lapply(team_color, choose_color)

Upvotes: 0

Views: 499

Answers (2)

langtang
langtang

Reputation: 24722

If you make a couple of changes:

  1. team_color should be adjusted
team_color = c(1,5,2,6,3,7,4,8)
  1. use sapply to feed the team colors one by one to your function
barplot(performance ~ teams, data = df, 
        col = sapply(team_color,choose_color)) 

team_colors

Upvotes: 1

wdchild
wdchild

Reputation: 51

I have discovered that one possibility would be to convert all the assigned colors to their hex equivalents and place those values in the dataframe. Then you can simply assign color to the color value given in the dataframe. It's an OK workaround, though I would have liked to know why the first one didn't work.

# team performances in year 2000 and 2020

base_colors <- c("darkgoldenrod2", "darkblue", "darkred","darkcyan")

teams <- c('A2000', 'B2000', 'C2000', 'D2000')
performance  <- c(10, 3, 5, 4)
team_color <- c('#AA2233FF', '#BB000033', '#CC00AA33', '#DD0000FF')
df <- data.frame(teams, performance, team_color) 

barplot(performance ~ teams, data = df, 
        col = team_color)

Upvotes: 0

Related Questions