пользовательский цвет заливки в ggvis (и другие параметры)

Я пытаюсь использовать ggvis для создания диаграммы силы расписания НФЛ на сезон 2014 года. Данные поступают с FootballOutsiders.com, а позже я сделаю приложение Shiny, которое автоматически собирает данные с веб-сайта по мере его обновления в течение сезона. Пример ниже довольно близок, но я хотел бы внести несколько изменений. Я хочу...

  1. Включите числовое значение «защита» в каждую ячейку диаграммы, чтобы визуализация напоминала исходный фрейм данных «df».

  2. Настройте цветовую шкалу так, чтобы положительные значения становились все более оранжевыми, а отрицательные — все более синими (т. е. чем больше отрицательных значений, тем больше синего).

  3. Альтернативой № 2 может быть создание градиента от оранжевого к синему и уменьшение непрозрачности до 0,5 по мере того, как значение «защиты» приближается к нулю.

  4. Иметь возможность выбрать цвет NA, потому что в настоящее время он отображается черным цветом на диаграмме.

Я возился с add_scale() и props(), но пока ничего не работает.

Вот диаграмма: введите здесь описание изображения

Вот данные:

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")

И вот код до сих пор:

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)

person rsoren    schedule 17.07.2014    source источник


Ответы (2)


Я устанавливаю цвета для каждой ячейки, создавая новую переменную def.color, которая сопоставляет каждое значение defense с определенным цветом. В ggplot2 вы можете установить цвета непосредственно в вызове ggplot, используя одну строку кода, например scale_fill_manual(), вместо того, чтобы добавлять переменную цвета во фрейм данных. Я надеюсь, что в ggvis есть способ сделать это, но я пока его не нашел. Итак, на данный момент, здесь мы идем:

# 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)] = ""

Теперь создаем сюжет. Чтобы получить цвета, сопоставьте def.color с fill, используя :=, чтобы переопределить цвета по умолчанию. Чтобы добавить значения defense, используйте layer_text. Я не доволен размещением текста в каждой ячейке, но это лучшее, что я смог придумать на данный момент.

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") 

введите здесь описание изображения

person eipi10    schedule 17.07.2014
comment
Кажется немного нелогичным, что нужно вручную сопоставлять переменную с цветом. Разве функции масштабирования ggvis еще не сделали этого? - person Peter Ellis; 15.01.2015
comment
Я давно не пытался использовать ggvis, и он быстро развивается. Я согласен, что было бы гораздо предпочтительнее, чтобы об этом позаботились функции масштабирования. Надеюсь, есть или скоро появится способ сделать это. Я также хотел бы найти способ получить больше контроля над тем, где числа размещаются в ячейках. - person eipi10; 15.01.2015
comment
Я сам смотрю на ggvis всего несколько дней. Из того, что я читал, это легко сделать в будущем. На данный момент вы можете определить шкалу заливки или обводки с произвольным цветом на каждом конце, но у вас пока нет эквивалента {scales}' scale_fill_gradientn, который необходим для таких ситуаций, как сине-бело-красный или просто цвета друг в друга с сине-красным. - person Peter Ellis; 16.01.2015
comment
любопытно, смог ли @eipi10 добавить легенду к сюжету? - person altimit; 22.04.2015

Решение, которое я нашел для отображения легенды, используя функцию scale_ordinal. Я использовал много кода, написанного @eipi10, спасибо!

# 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") 

Добавлена ​​легенда в матрицу ggvis

person skasch    schedule 18.05.2015