2013-09-26 23 views
5

Ví dụ: tôi muốn ánh xạ màu thành z, với 0 bản đồ thành "trắng".Các cách tiếp cận khác để xử lý các giá trị/phân phối cực đoan khi sử dụng scale_fill_gradient?

> a <- data.frame(x=1:10, y=1, z=c(rnorm(8),-12,12)) 
> a 
    x y   z 
1 1 1 -0.4603911 
2 2 1 -0.4868471 
3 3 1 0.2180346 
4 4 1 -0.8807652 
5 5 1 1.7379462 
6 6 1 -0.1334904 
7 7 1 -0.3675578 
8 8 1 0.9225425 
9 9 1 -12.0000000 
10 10 1 12.0000000 

ggplot(a,aes(x=x,y=y,fill=z)) + geom_bar(stat="identity") + 
    scale_fill_gradient2(high="green", mid="white", low="red") 

Như bạn có thể nhìn thấy màu sắc là không thực sự chỉ hữu ích, thay vì truyền đạt một ý tưởng chung về cách các giá trị được phân tán, bây giờ là màu chỉ nói mà giá trị là cực đoan, để lại những giá trị lớn không thể phân biệt bằng mắt chưa qua đào tạo .

Có một phương pháp Non-linear color distribution over the range of values in a geom_raster nhưng có vẻ hơi phức tạp và tôi chỉ có thể mơ hồ hiểu cách hoạt động của nó.

enter image description here

sau đó tôi nghĩ có lẽ order là một rescale cách tốt, do đó:

ggplot(a,aes(x=x,y=y,fill=ecdf(z)(z))) + geom_bar(stat="identity") + 
scale_fill_gradient2(high="green", mid="white", low="red", midpoint=ecdf(a$z)(0)) 

Nó làm việc chừng mực nào đó (ở đây tôi sử dụng ecdf thay vì order để tìm giá trị 0 được rescaled. Tuy nhiên, nhược điểm là, tôi muốn giữ cho các nhãn của huyền thoại là các giá trị chưa được đánh giá, thay vì các giá trị đã được thay đổi kích thước.Vì vậy, một cái gì đó như labels=function(x) quantile(a$z, x), mà tôi không thể làm cho nó hoạt động. quantile để rescale về phía trước và lạc hậu.

Có cách tiếp cận nào tốt hơn hay đơn giản hơn trong các trường hợp này, ví dụ: mạnh mẽ (không cần phải tối ưu hoặc rất chính xác) đủ để lấp đầy màu sắc hợp lý cho tất cả các loại phân phối của các giá trị được ánh xạ.

enter image description here

Trả lời

3

Không có một cách dễ dàng mà tôi biết, nhưng bạn có thể có quyền kiểm soát đầy đủ các bản đồ với scale_fill_gradientn. Điều quan trọng là ánh xạ màu sắc cho các giá trị trong phạm vi 0-1 trong đó 0 là giá trị nhỏ nhất của bạn và 1 là giá trị tối đa của bạn. Dưới đây là một tùy chọn:

library(ggplot2) 
a <- data.frame(x=1:10, y=1, z=c(rnorm(8),-12,12)) 
get_col <- colorRamp(c("red", "white", "green")) # make fun to interpolate colors 
quantiles <- (0:6)/6       # how many quantiles we want to map 
quantile.vals <- quantile(a$z, quantiles, names=F)# the values for each quantile 
colours <- rgb(get_col(quantiles), max=255)  # 7 evenly interpolated colors 
val.remap <- (quantile.vals - min(a$z))/
    diff(range(a$z))        # The values corresponding to the quantiles 

ggplot(a, aes(x=x,y=y,fill=z)) + 
    geom_bar(stat="identity") + 
    scale_fill_gradientn(
    colours=colours, 
    values=val.remap, 
    breaks=quantile.vals,# Necessary to get legend values spread appropriately 
    guide="legend")  # Necessary to get legend values spread appropriately 

Ở đây chúng tôi đã chọn gán màu sắc nội suy đồng đều cho các giá trị dựa trên phân phối giá trị. Vì vậy, nếu một phạm vi giá trị tương ứng với một phần lớn của phân phối mặc dù nó thực sự trải rộng một phần tương đối nhỏ trong phạm vi min-max, nó sẽ được phân bổ nhiều màu hơn.

Nếu bạn muốn chỉ định một màu cụ thể bằng 0, bạn có thể làm như vậy bằng cách chỉnh sửa vectơ tương ứng với các đối số colours, valuesbreaks. Điều này dao động từ tầm thường nếu bạn có cùng số giá trị trên và dưới 0, gây phiền nhiễu nếu không.


Version w/0 thiết lập để trắng:

library(ggplot2) 
a <- data.frame(x=1:10, y=1, z=c(rnorm(8), -12, 12)) 
splits <- 7  # should be odd number 
mid.point <- 0 
pos.vals <- a$z[a$z > mid.point] 
neg.vals <- a$z[a$z < mid.point] 
pos.quants <- quantile(c(mid.point, pos.vals), 0:((splits - 1)/2)/((splits - 1)/2), names=F) 
neg.quants <- quantile(c(mid.point, neg.vals), 0:((splits - 1)/2)/((splits - 1)/2), names=F) 
quants <- c(neg.quants, pos.quants[-1]) # drop of the mid-point from pos.quants since otherwise double counted 

get_col <- colorRamp(c("red", "white", "green")) # make fun to interpolate colors 
colours <- rgb(get_col(0:(splits - 1)/(splits - 1)), max=255)  # 7 evenly interpolated colors 
val.remap <- (quants - min(quants))/
    diff(range(quants))        # The values corresponding to the quantiles 

ggplot(a, aes(x=x,y=y,fill=z)) + 
    geom_bar(stat="identity") + 
    scale_fill_gradientn(
    colours=colours, 
    values=val.remap, 
    breaks=quants, 
    guide="legend") 

color mapping result http://i42.tinypic.com/qzmzgn.png

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