2012-10-22 32 views
21

This Learning R blog post cho biết cách tạo bản đồ nhiệt của thống kê bóng rổ bằng ggplot2. Các Heatmap thành trông như thế này:ggplot2 bản đồ nhiệt: sử dụng các độ dốc khác nhau cho các danh mục

enter image description here

Câu hỏi của tôi (lấy cảm hứng từ Jake người nhận xét về các bài viết trên blog Learning R) là: nó sẽ có thể sử dụng màu sắc gradient khác nhau cho các loại khác nhau của số liệu thống kê (tấn công, phòng thủ, khác)?

Trả lời

32

Thứ nhất, tái tạo biểu đồ từ đăng bài, cập nhật nó cho mới hơn (0.9.2.1) phiên bản của ggplot2 trong đó có một hệ thống chủ đề khác nhau và gắn gói ít:

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

Sử dụng màu gradient khác nhau cho các loại khác nhau không phải là tất cả những điều đơn giản. Cách tiếp cận khái niệm, để ánh xạ fill đến interaction(rescale, Category) (trong đó Category là Tấn công/Phòng thủ/Khác; xem bên dưới) không hoạt động vì tương tác với một yếu tố và biến liên tục cho một biến rời rạc mà không thể ánh xạ tới fill.

Cách để làm được việc này là để làm nhân tạo tương tác này, lập bản đồ rescale để không chồng chéo dãy cho các giá trị khác nhau của Category và sau đó sử dụng để lập bản đồ scale_fill_gradientn mỗi một trong các khu vực để gradient màu sắc khác nhau.

Đầu tiên tạo danh mục. Tôi nghĩ rằng những bản đồ này cho những người trong nhận xét, nhưng tôi không chắc chắn; thay đổi biến nào trong danh mục nào là dễ dàng.

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

Kể từ rescale là trong vòng vài (3 hoặc 4) 0, các loại khác nhau có thể được bù đắp bằng một trăm để giữ chúng riêng biệt. Đồng thời, xác định vị trí của các điểm cuối của mỗi gradient màu, cả về giá trị và màu sắc được thay đổi kích thước.

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

Bây giờ thay thế các biến fill với rescaleoffset và thay đổi quy mô fill sử dụng scale_fill_gradientn (nhớ để rescale các giá trị):

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

Sắp xếp lại để có được số liệu thống kê liên quan với nhau là khác áp dụng chức năng reorder trên các biến khác nhau:

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

Ấn tượng! Cảm ơn nhiều. – ThatGuy

+0

Chỉ vì tò mò, làm thế nào một người có thể gán màu sắc khác nhau cho người chơi thay vào đó (tức là các hàng thay vì các cột)? – ThatGuy

+0

Khái niệm chung tương tự; tạo một biến được chia tỷ lệ bù trừ là một hàm của biến tỷ lệ gốc và 'as.numeric (NAME)'. Sau đó, trêu chọc các điểm cuối của các phạm vi khác nhau. Nhưng tôi nghĩ rằng đó sẽ là một ý tưởng tồi vì các so sánh của bạn là theo chiều kim đồng hồ; sử dụng các màu khác nhau (nghĩa là các phần của các độ dốc khác nhau) làm cho các phần tử không thể so sánh được trong một cột. –

2

Dưới đây là một gợi ý đơn giản có sử dụng thẩm mỹ ggplot2 để lập bản đồ cả gradient cũng như loại màu. Đơn giản chỉ cần sử dụng một tính thẩm mỹ alpha để tạo ra độ dốc và tính thẩm mỹ cho loại đó.

Đây là đoạn mã để làm như vậy, refactoring Brian Diggs' phản ứng:

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

Sau đó, bình thường hóa biến rescale đến giữa 0 và 1:

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

Và bây giờ, thực hiện âm mưu :

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

Lưu ý việc sử dụng alpha=rescale và sau đó mở rộng phạm vi alpha bằng cách sử dụng scale_alpha(range=c(0,1)), có thể được điều chỉnh để thay đổi phạm vi phù hợp cho cốt truyện của bạn.

Các vấn đề liên quan