Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
363 views
in Technique[技术] by (71.8m points)

r - custom fill color in ggvis (and other options)

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 automatically scrapes data from the website as it's updated during the season. The example below is pretty close, but I'd like to make a few modifications. I want to...

  1. Include the numeric value of "defense" in each cell of the chart, so the visualization resembles the original "df" data frame.

  2. Customize the color scale so positive values are increasingly orange and negative values are increasingly blue (i.e. more negative = more blue).

  3. An alternative to #2 could be to make a gradient from orange to blue, and make the opacity decrease to 0.5 as the value of "defense" approaches zero.

  4. Be able to choose the color of NA, because it currently shows up as black in the chart.

I've been tinkering around with add_scale() and props(), but nothing has been working so far.

Here's the chart: enter image description here

Here's the data:

df <- structure(list(team = c("ARI", "ATL", "BAL", "BUF", "CAR", "CHI", 
"CIN", "CLE", "DAL", "DEN", "DET", "GB", "HOU", "IND", "JAX", 
"KC", "MIA", "MIN", "NE", "NO", "NYG", "NYJ", "OAK", "PHI", "PIT", 
"SD", "SEA", "SF", "STL", "TB", "TEN", "WAS"), w1 = c(17.5, -5.8, 
-12.6, 8.7, -6.8, -13.8, -8.7, 4, -4.6, 0.9, -11.4, -25.9, 4.2, 
-0.2, 4.9, 4.2, 4.2, -5.7, 2.4, 13.5, -0.8, 10.3, -5.6, 10.9, 
8.2, -16.4, 14.4, 13.8, 10.5, -15.7, -6.7, 2.5), w2 = c(-11.4, 
-12.6, 4, 2.4, -0.8, -4.6, 13.5, -5.8, 4.2, -6.7, -15.7, -5.6, 
10.3, 4.9, 4.2, -0.2, -13.8, 4.2, 10.5, 8.2, -16.4, 14.4, 2.5, 
0.9, -8.7, -25.9, 17.5, 8.7, -6.8, -5.7, 13.8, 10.9), w3 = c(-4.6, 
-6.8, 8.2, 17.5, 4, -5.6, 4.2, -8.7, -5.7, -25.9, 14.4, -0.8, 
-11.4, 10.9, 0.9, 2.4, -6.7, -5.8, 10.3, 10.5, 2.5, 8.7, 4.2, 
4.2, -15.7, -13.8, -0.2, -16.4, 13.8, 13.5, -12.6, 4.9), w4 = c(NA, 
10.5, -15.7, 2.5, -8.7, 14.4, NA, NA, -5.8, NA, -5.6, 8.7, -13.8, 
4.2, 17.5, 4.2, 10.3, 13.5, -6.7, 13.8, 4.2, -0.8, 2.4, -4.6, 
-6.8, 10.9, NA, 4.9, NA, 4, 0.9, -11.4), w5 = c(-0.2, -11.4, 
0.9, -0.8, 8.7, -15.7, 4.2, 4.2, 2.5, -16.4, -13.8, 10.5, 13.8, 
-8.7, 4, -4.6, NA, 14.4, -12.6, -6.8, 13.5, 17.5, NA, -5.7, 10.9, 
-5.6, 4.2, -6.7, 4.9, -5.8, 8.2, -25.9), w6 = c(4.2, 8.7, -6.8, 
4.2, -12.6, 13.5, -15.7, 4, -25.9, -5.6, 10.5, 2.4, 0.9, 2.5, 
4.2, NA, 14.4, -0.8, -13.8, NA, 4.9, -0.2, 17.5, -11.4, 8.2, 
10.3, 13.8, -5.7, -4.6, -8.7, 10.9, -16.4), w7 = c(10.3, -8.7, 
13.5, 10.5, 14.4, 2.4, 0.9, 10.9, -11.4, -4.6, -5.8, -15.7, 4, 
-12.6, 8.2, 17.5, 8.7, -13.8, -5.6, -0.8, 13.8, 4.2, -16.4, NA, 
2.5, -6.7, -5.7, -0.2, -25.9, NA, 4.2, 4.2), w8 = c(4.9, -0.8, 
-12.6, -5.6, -25.9, 4.2, -8.7, 10.3, 4.2, 17.5, 13.5, -5.8, 4.2, 
4, 2.4, -5.7, 10.9, -6.8, 8.7, 14.4, NA, -13.8, 8.2, -16.4, 0.9, 
-0.2, -15.7, NA, -6.7, 10.5, 2.5, 13.8), w9 = c(13.8, NA, 4, 
NA, -5.8, NA, 10.9, -6.8, -16.4, 4.2, NA, NA, 4.9, -11.4, -12.6, 
-5.6, 17.5, 4.2, -0.2, -15.7, 0.9, -6.7, -25.9, 2.5, -8.7, 2.4, 
10.3, -5.7, -4.6, 8.2, NA, 10.5), w10 = c(-5.7, -6.8, 4.2, -6.7, 
4.9, 14.4, 8.2, -12.6, 10.9, 10.3, 2.4, 8.7, NA, NA, 13.8, -13.8, 
-0.8, NA, NA, -4.6, -25.9, 4, -0.2, -15.7, -5.6, NA, -11.4, -5.8, 
-16.4, 13.5, -8.7, NA), w11 = c(-0.8, -15.7, NA, 2.4, 13.5, 10.5, 
-5.8, 2.5, NA, -5.7, -16.4, 4.9, 8.2, 4.2, NA, -25.9, -13.8, 
8.7, 0.9, -12.6, -4.6, NA, 17.5, 14.4, 4.2, 10.3, -6.7, -11.4, 
-0.2, 4.2, 4, -6.8), w12 = c(-25.9, 8.2, -5.8, -5.6, NA, -6.8, 
2.5, 13.5, -11.4, 2.4, 4.2, 10.5, -12.6, 10.9, 0.9, 10.3, -0.2, 
14.4, -0.8, -8.7, 13.8, -13.8, -6.7, 4.2, NA, -5.7, -16.4, 4.2, 
17.5, 8.7, 4.9, -4.6), w13 = c(13.5, -16.4, 17.5, 8.2, 10.5, 
-0.8, -6.8, -13.8, 4.9, -6.7, 8.7, 4.2, 4.2, 4.2, -11.4, -0.2, 
-5.6, -15.7, 14.4, 4, 10.9, 2.4, -5.7, 13.8, -5.8, -8.7, -4.6, 
-25.9, 10.3, -12.6, 2.5, 0.9), w14 = c(-6.7, 14.4, 2.4, -0.2, 
-5.8, 13.8, 4, 0.9, 8.7, -13.8, -6.8, 13.5, 10.9, 8.2, 2.5, -16.4, 
-8.7, -5.6, 17.5, -15.7, 4.2, 10.5, -4.6, -25.9, -12.6, 4.2, 
4.9, 10.3, 4.2, -0.8, -11.4, -5.7), w15 = c(-5.7, 4, 10.9, 14.4, 
-6.8, -5.8, 8.2, -12.6, 4.9, 17.5, 10.5, -13.8, 0.9, 2.5, -8.7, 
10.3, 4.2, -0.8, 2.4, 8.7, 4.2, 4.2, -6.7, 13.8, 13.5, -0.2, 
-4.6, -25.9, -16.4, -15.7, -5.6, -11.4), w16 = c(-25.9, -5.8, 
2.5, 10.3, 8.2, -0.8, -0.2, -15.7, 0.9, -12.6, 8.7, -6.8, -8.7, 
13.8, 4.2, 4, 10.5, 2.4, -5.6, 13.5, -5.7, 4.2, -13.8, 4.2, -6.7, 
-4.6, -16.4, 17.5, -11.4, 14.4, 10.9, 4.9), w17 = c(-4.6, -15.7, 
8.2, 4.2, 13.5, 10.5, 4, -8.7, 4.2, 10.3, 14.4, -0.8, 10.9, 4.2, 
2.5, 17.5, -5.6, 8.7, -13.8, -6.8, 4.9, 2.4, -0.2, -11.4, -12.6, 
-6.7, -5.7, -16.4, -25.9, -5.8, 0.9, 13.8)), .Names = c("team", 
"w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", 
"w11", "w12", "w13", "w14", "w15", "w16", "w17"), row.names = c(NA, 
32L), class = "data.frame")

And here's the code so far:

require(dplyr)
require(ggvis)
require(tidyr) # For the gather function

df2 <- df %>% gather(key, value, w1:w17)
names(df2) <- c("team", "week", "defense")

df2 %>% 
  ggvis(~week, ~team, fill = ~defense) %>%
  layer_rects(width = band(), height = band()) %>%
  scale_nominal("x", padding = 0, points = FALSE) %>%
  scale_nominal("y", padding = 0, points = FALSE)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...