2012-10-22 14 views

Odpowiedz

32

Najpierw odtworzyć wykres z postu, aktualizując je na nowsze (0.9.2.1) wersji ggplot2 który ma inny system rozrywki i przywiązuje mniejsze pakiety:

nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv") 
nba$Name <- with(nba, reorder(Name, PTS)) 

library("ggplot2") 
library("plyr") 
library("reshape2") 
library("scales") 

nba.m <- melt(nba) 
nba.s <- ddply(nba.m, .(variable), transform, 
       rescale = scale(value)) 

ggplot(nba.s, aes(variable, Name)) + 
    geom_tile(aes(fill = rescale), colour = "white") + 
    scale_fill_gradient(low = "white", high = "steelblue") + 
    scale_x_discrete("", expand = c(0, 0)) + 
    scale_y_discrete("", expand = c(0, 0)) + 
    theme_grey(base_size = 9) + 
    theme(legend.position = "none", 
     axis.ticks = element_blank(), 
     axis.text.x = element_text(angle = 330, hjust = 0)) 

enter image description here

Używanie różne kolory gradientu dla różnych kategorii nie są takie proste. Podejście koncepcyjne, polegające na odwzorowaniu fill na interaction(rescale, Category) (gdzie Category jest Offensive/Defensive/Other, patrz poniżej) nie działa, ponieważ interakcja współczynnika i zmiennej ciągłej daje dyskretną zmienną, której nie można odwzorować na fill.

Sposób, aby obejść ten problem jest sztucznie robić tego oddziaływania, mapowanie rescale aby nie pokrywających się zakresów dla różnych wartości Category a następnie użyć scale_fill_gradientn mapować każdy z tych regionów do różnych gradientów kolorów.

Najpierw utwórz kategorie. Myślę, że te mapy do tych w komentarzu, ale nie jestem pewien; zmiana której zmiennej jest w jakiej kategorii jest łatwa.

nba.s$Category <- nba.s$variable 
levels(nba.s$Category) <- 
    list("Offensive" = c("PTS", "FGM", "FGA", "X3PM", "X3PA", "AST"), 
     "Defensive" = c("DRB", "ORB", "STL"), 
     "Other" = c("G", "MIN", "FGP", "FTM", "FTA", "FTP", "X3PP", 
        "TRB", "BLK", "TO", "PF")) 

Od rescale jest w ciągu kilku (3 lub 4) 0, różne kategorie mogą być rekompensowane przez sto, aby przechowywać je oddzielnie. Jednocześnie należy określić, gdzie powinny znajdować się punkty końcowe każdego gradientu kolorów, zarówno pod względem przeskalowanych wartości, jak i kolorów.

nba.s$rescaleoffset <- nba.s$rescale + 100*(as.numeric(nba.s$Category)-1) 
scalerange <- range(nba.s$rescale) 
gradientends <- scalerange + rep(c(0,100,200), each=2) 
colorends <- c("white", "red", "white", "green", "white", "blue") 

Teraz zastąpić zmienną fill z rescaleoffset i zmienić skalę na fill używać scale_fill_gradientn (pamiętając, aby przeskalować wartości):

ggplot(nba.s, aes(variable, Name)) + 
    geom_tile(aes(fill = rescaleoffset), colour = "white") + 
    scale_fill_gradientn(colours = colorends, values = rescale(gradientends)) + 
    scale_x_discrete("", expand = c(0, 0)) + 
    scale_y_discrete("", expand = c(0, 0)) + 
    theme_grey(base_size = 9) + 
    theme(legend.position = "none", 
     axis.ticks = element_blank(), 
     axis.text.x = element_text(angle = 330, hjust = 0)) 

enter image description here

zamianom dostać związanych statystyk razem jest inny zastosowanie funkcji reorder dla różnych zmiennych:

nba.s$variable2 <- reorder(nba.s$variable, as.numeric(nba.s$Category)) 

ggplot(nba.s, aes(variable2, Name)) + 
    geom_tile(aes(fill = rescaleoffset), colour = "white") + 
    scale_fill_gradientn(colours = colorends, values = rescale(gradientends)) + 
    scale_x_discrete("", expand = c(0, 0)) + 
    scale_y_discrete("", expand = c(0, 0)) + 
    theme_grey(base_size = 9) + 
    theme(legend.position = "none", 
     axis.ticks = element_blank(), 
     axis.text.x = element_text(angle = 330, hjust = 0)) 

enter image description here

+0

Imponujące! Dziękuję Ci bardzo. – ThatGuy

+0

Po prostu z ciekawości, w jaki sposób można następnie przypisać różne kolory graczom (tj. Do wierszy zamiast kolumn)? – ThatGuy

+0

Ta sama ogólna koncepcja; zrób skalowaną wartość przesunięcia, która jest funkcją oryginalnej zmiennej skalowania i 'as.numeric (NAME)'. Następnie drażnij punkty końcowe różnych zakresów. Ale myślę, że to byłby zły pomysł, ponieważ twoje porównania są oparte na kolumnach; używanie różnych kolorów (czyli części różnych gradientów) powoduje, że elementy nie są porównywalne w obrębie kolumny. –

2

Oto prostsze sugestia, że ​​używa ggplot2 estetykę mapować zarówno podłużne, jak również kategorie kolorów. Po prostu użyj estetyki alfa, aby wygenerować gradient i wypełnienie-estetykę dla kategorii.

Oto kod, aby to zrobić, refactoring Brian Diggs' Odpowiedź:

nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv") 
nba$Name <- with(nba, reorder(Name, PTS)) 

library("ggplot2") 
library("plyr") 
library("reshape2") 
library("scales") 

nba.m <- melt(nba) 
nba.s <- ddply(nba.m, .(variable), transform, 
      rescale = scale(value)) 

nba.s$Category <- nba.s$variable 
levels(nba.s$Category) <- list("Offensive" = c("PTS", "FGM", "FGA", "X3PM", "X3PA", "AST"), 
    "Defensive" = c("DRB", "ORB", "STL"), 
    "Other" = c("G", "MIN", "FGP", "FTM", "FTA", "FTP", "X3PP", "TRB", "BLK", "TO", "PF")) 

Następnie normalizacji zmiennej rescale się między 0 i 1:

nba.s$rescale = (nba.s$rescale-min(nba.s$rescale))/(max(nba.s$rescale)-min(nba.s$rescale)) 

A teraz zrobić wykreślanie :

ggplot(nba.s, aes(variable, Name)) + 
    geom_tile(aes(alpha = rescale, fill=Category), colour = "white") + 
    scale_alpha(range=c(0,1)) + 
    scale_x_discrete("", expand = c(0, 0)) + 
    scale_y_discrete("", expand = c(0, 0)) + 
    theme_grey(base_size = 9) + 
    theme(legend.position = "none", 
     axis.ticks = element_blank(), 
     axis.text.x = element_text(angle = 330, hjust = 0)) + 
    theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) 

ggplot2 heatmap using alpha aesthetic

Należy zanotować użycie alpha=rescale, a następnie skalowanie zakresu alfa za pomocą scale_alpha(range=c(0,1)), które można dostosować w celu zmiany zakresu odpowiednio do wykresu.

Powiązane problemy