ggplot2:通过设置连续的色标来处理极值 [英] ggplot2: dealing with extremes values by setting a continuous color scale

查看:254
本文介绍了ggplot2:通过设置连续的色标来处理极值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试绘制一些全局贴图(栅格文件),但是在为数据设置合适的色标时遇到一些问题。我想做的是使用不同的调色板绘制数据(例如 cm.colors ),我想将这样的比例尺的颜色白色居中值为零,但不必在比例尺中设置对称值(即负值和正值相同的值,即 limits = c(-1,1))。另外,我想用相同的颜色绘制一个特定值之上和/或之下的所有值。

I am trying to plot some global maps (raster files) and I have some problems in setting up a good color scale for my data. What I would like to do is to plot my data using a divergent palette (e.g. cm.colors), and I would like to center the color "white" of such scale with the value zero, but without having to set symmetric values in the scale (i.e. the same value both negative and positive, i.e. limits=c(-1,1)). Additionally, I would like to plot all values above and/or below a certain value all with the same color.

换句话说,如果我们假设我的地图的范围是-100到150,我想用带有白色的发散调色板绘制我的地图颜色对应于值0,并具有所有值,例如低于-20和高于50分别绘制相同的颜色,即分别具有调色板的负极端和正极端。

In other words, if we suppose that my map has a range of -100 to 150, I would like to plot my map with a diverging palette with a "white" color corresponding to the value 0, and having all values e.g. below -20 and above 50 plotted with the same color, i.e. respectively with the negative and positive extremes of the color palette.

这里是我使用的代码示例目前:

Here an example of the code that I am using for the moment:

ggplot(df, aes(y=Latitude, x=Longitude)) +
  geom_raster(aes(fill=MAP)) +
  coord_equal()+ 
  theme_gray() +
  theme(panel.background = element_rect(fill = 'skyblue2', colour = 'black'), 
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "right",
        legend.key = element_blank()) +
  scale_fill_gradientn("MAP", limits=c(-0.5,1), colours=cm.colors(20))


推荐答案

有简单的方法可以完成此操作,例如事前截断数据或使用 cut 为适当的标签创建离散的纸槽。

There are simple ways to accomplish this, such as truncating your data beforehand, or using cut to create discrete bins for appropriate labels.

require(dplyr)
df %>% mutate(z2 = ifelse(z > 50, 50, ifelse(z < -20, -20, z))) %>% 
  ggplot(aes(x, y, fill = z2)) + geom_tile() + 
  scale_fill_gradient2(low = cm.colors(20)[1], high = cm.colors(20)[20])

df %>% mutate(z2 = cut(z, c(-Inf, seq(-20, 50, by = 10), Inf)),
              z3 = as.numeric(z2)-3) %>% 
  {ggplot(., aes(x, y, fill = z3)) + geom_tile() + 
  scale_fill_gradient2(low = cm.colors(20)[1], high = cm.colors(20)[20],
                       breaks = unique(.$z3), labels = unique(.$z2))}

但是我之前曾考虑过这项任务,对此感到不满意。预截断不会留下漂亮的标签,并且 cut 选项总是很随意(特别是必须调整 seq cut 里面的$ c>并找出如何更新垃圾箱)。因此,我尝试定义一个可重用的转换,该转换将为您执行截断和重新标记的操作。

But I'd thought about this task before, and felt unsatisfied with that. The pre-truncating doesn't leave nice labels, and the cut option is always fiddly (particularly having to adjust the parameters of seq inside cut and figure out how to recenter the bins). So I tried to define a reusable transformation that would do the truncating and relabeling for you.

我还没有完全调试它,所以我要出门了,所以希望您或其他答复者能对此有所帮助。主要问题似乎是在边缘情况下发生冲突,因此有时限制在视觉上与预期的中断重叠,以及格式化的某些意外行为。我只是使用一些虚拟数据来创建所需的-100至150的范围来进行测试。

I haven't fully debugged this and I'm going out of town, so hopefully you or another answerer can take a crack at it. The main problem seems to be collisions in the edge cases, so occasionally the limits overlap the intended breaks visually, as well as some unexpected behavior with the formatting. I just used some dummy data to create your desired range of -100 to 150 to test it.

require(scales)
trim_tails <- function(range = c(-Inf, Inf)) trans_new("trim_tails", 
                transform = function(x) {
                  force(range)
                  desired_breaks <- extended_breaks(n = 7)(x[x >= range[1] & x <= range[2]])
                  break_increment <- diff(desired_breaks)[1]
                  x[x < range[1]] <- range[1] - break_increment
                  x[x > range[2]] <- range[2] + break_increment
                  x
                },
                inverse = function(x) x,

                breaks = function(x) {
                  force(range)
                  extended_breaks(n = 7)(x)
                },
                format = function(x) {
                  force(range)
                  x[1] <- paste("<", range[1])
                  x[length(x)] <- paste(">", range[2])
                  x
                })

ggplot(df, aes(x, y, fill = z)) + geom_tile() + 
  guides(fill = guide_colorbar(label.hjust = 1)) +
  scale_fill_gradient2(low = cm.colors(20)[1], high = cm.colors(20)[20],
                       trans = trim_tails(range = c(-20,50)))

还可以使用盒装图例而不是颜色条,只需使用 ... + guides(fill = guide_legend(label.hjust = 1,reverse = T))+ ...

Also works with a boxed legend instead of a colorbar, just use ... + guides(fill = guide_legend(label.hjust = 1, reverse = T)) + ...

这篇关于ggplot2:通过设置连续的色标来处理极值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆