custom fill color in ggvis (and other options)

前端 未结 2 391
不思量自难忘°
不思量自难忘° 2020-12-16 03:54

I\'m trying to use ggvis to create a NFL strength-of-schedule chart for the 2014 season. The data comes from FootballOutsiders.com, and later I\'ll make a Shiny app that aut

相关标签:
2条回答
  • 2020-12-16 04:40

    A solution I found to display a legend, making use of the scale_ordinal function. I used a lot of the code written by @eipi10, thank you!

    # Functions to create color ramps for the blue and orange color ranges,
    # combined in a single palette with 10 colors of each ramp and gray for NAs
    Blue <- colorRampPalette(c("darkblue","lightblue"))
    Orange <- colorRampPalette(c("orange","darkorange3"))
    palette <- c(Blue(10), "#E5E5E5", Orange(10))
    
    # Negative values of defense get a blue color scale with 10 colors, indexes
    # from 1 to 10
    df2$def.label[!is.na(df2$defense) & df2$defense<0] <- 
        as.character(cut(df2$defense[!is.na(df2$defense) & df2$defense<0], 
                     seq(min(df2$defense - 0.1, na.rm = TRUE), 0, length.out = 11), 
                     labels = palette[1:10]))
    
    # Positive values of defense get an orange color scale with 10 colors,
    # indexes from 12 to 21
    df2$def.label[!is.na(df2$defense) & df2$defense>=0] <-
        as.character(cut(df2$defense[!is.na(df2$defense) & df2$defense>=0], 
                     seq(0, max(df2$defense, na.rm = TRUE) + 0.1, length.out = 11), 
                     labels = palette[12:21]))
    
    # Set NA values in df2$defense to 11 in def.label, the label for gray color
    df2$def.label[is.na(df2$defense)] <- palette[[11]] 
    
    # Define the values to be displayed on the legend
    pos.cut.values <- seq(0, max(df2$defense, na.rm = TRUE) + 0.1, length.out = 11)
    neg.cut.values <- seq(min(df2$defense - 0.1, na.rm = TRUE), 0, length.out = 11)
    legend.values <- c(paste(neg.cut.values[1:10], '..', neg.cut.values[2:11]),
                       'NA', paste(pos.cut.values[1:10], '..', pos.cut.values[2:11]))
    
    # Set NA values in df2$defense to blanks so that we won't get "NaN" in cells
    # with missing data
    df2$defense[is.na(df2$defense)] <- ""
    
    df2 %>% 
        ggvis(~week, ~team, fill:=~def.label) %>% 
        scale_ordinal('fill', range = palette) %>%
        add_legend(scales = 'fill', values = legend.values) %>%
        layer_rects(width = band(), height = band()) %>%
        scale_nominal("x", padding = 0, points = FALSE) %>%
        scale_nominal("y", padding = 0, points = FALSE) %>%
        layer_text(text := ~defense, stroke := "white", align := "left",
                   baseline := "top") 
    

    Added legend to ggvis matrix

    0 讨论(0)
  • 2020-12-16 04:52

    I set the colors for each cell by creating a new variable def.color that maps each value of defense to a specific color. In ggplot2 you can set the colors directly within the call to ggplot using one line of code, such as scale_fill_manual(), rather than adding a color variable to the data frame. I'm hoping there's a way to do that in ggvis, but I haven't found it yet. So, for now, here we go:

    # Create a new variable df2$def.color for mapping df2$defense values to colors
    
    # Functions to create color ramps for the blue and orange color ranges
    Blue = colorRampPalette(c("darkblue","lightblue"))
    Orange = colorRampPalette(c("orange","darkorange3"))
    
    # Negative values of defense get a blue color scale with 10 colors
    df2$def.color[!is.na(df2$defense) & df2$defense<0] = 
      as.character(cut(df2$defense[!is.na(df2$defense) & df2$defense<0], 
                       seq(min(df2$defense - 0.1, na.rm=TRUE), 0, length.out=11), 
                       labels=Blue(10)))
    
    # Positive values of defense get an orange color scale with 10 colors
    df2$def.color[!is.na(df2$defense) & df2$defense>=0] = 
      as.character(cut(df2$defense[!is.na(df2$defense) & df2$defense>=0], 
                       seq(0, max(df2$defense, na.rm=TRUE)+0.1, length.out=11), 
                       labels=Orange(10)))
    
    # Set NA values in df2$def.color to light gray in df2$def.color
    df2$def.color[is.na(df2$defense)] = "#E5E5E5"  
    
    # Set NA values in df2$defense to blanks so that we won't get "NaN" in cells with 
    # missing data
    df2$defense[is.na(df2$defense)] = ""
    

    Now we create the plot. To get the colors, map def.color to fill using := to override the default colors. To add the values of defense use layer_text. I'm not happy with the text placement within each cell, but this is the best I've been able to come up with for now.

    df2 %>% 
      ggvis(~week, ~team, fill:=~def.color) %>% 
      layer_rects(width = band(), height = band()) %>%
      scale_nominal("x", padding = 0, points = FALSE) %>%
      scale_nominal("y", padding = 0, points = FALSE) %>%
      layer_text(text:=~defense, stroke:="white", align:="left", baseline:="top") 
    

    enter image description here

    0 讨论(0)
提交回复
热议问题