Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
277 views
in Technique[技术] by (71.8m points)

r - Increase resolution of color scale for values close to zero

I'd like to make small returns in this plot more visible. The most appropriate function seems to be scale_colour_gradient2, but this washes out the small returns, which happen most often. Using limits helped but I couldn't work out how to set oob (out of bounds) so it would just have a "saturated" value rather than be grey. And the log transform just made small values stand out. Has someone else figured out how to do this elegantly?

library(zoo)
library(ggplot2)
library(tseries)

spx <- get.hist.quote(instrument="^gspc", start="2000-01-01",
                      end="2013-12-14", quote="AdjClose",
                      provider="yahoo", origin="1970-01-01",
                      compression="d", retclass="zoo")
spx.rtn <- diff(log(spx$AdjClose)) * 100
rtn.data <- data.frame(x=time(spx.rtn),yend=spx.rtn)

p <- ggplot(rtn.data) +
  geom_segment(aes(x=x,xend=x,y=0,yend=yend,colour=yend)) +
  xlab("") + ylab("S&P 500 Daily Return %") +
  theme(legend.position="null",axis.title.x=element_blank())

# low returns invisible
p + scale_colour_gradient2(low="blue",high="red")
# extreme values are grey
p + scale_colour_gradient2(low="blue",high="red",limits=c(-3,3))

# log transform returns has opposite problem
max_val <- max(log(abs(spx.rtn)))
values <- seq(-max_val, max_val, length = 11)

library(RColorBrewer)
p + scale_colour_gradientn(colours = brewer_pal(type="div",pal="RdBu")(11),
                           values = values
                           , rescaler = function(x, ...) sign(x)*log(abs(x)), oob = identity)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is another possibility, using scale_colour_gradientn. Mapping of colours is set using values = rescale(...) so that resolution is higher for values close to zero. I had a look at some colour scales here: http://colorbrewer2.org. I chose a 5-class diverging colour scheme, RdBu, from red to blue via near-white. There might be other scales that suit your needs better, this is just to show the basic principles.

# check the colours
library(RColorBrewer)
# cols <- brewer_pal(pal = "RdBu")(5) # not valid in 1.1-2
cols <- brewer.pal(n = 5, name = "RdBu") 
cols
# [1] "#CA0020" "#F4A582" "#F7F7F7" "#92C5DE" "#0571B0"
# show_col(cols) # not valid in 1.1-2
display.brewer.pal(n = 5, name = "RdBu")

Using rescale, -10 corresponds to blue #0571B0; -1 = light blue #92C5DE; 0 = light grey #F7F7F7; 1 = light red #F4A582; 10 = red #CA0020. Values between -1 and 1 are interpolated between light blue and light red, et c. Thus, mapping is not linear and resolution is higher for small values.

library(ggplot2)
library(scales) # needed for rescale
ggplot(rtn.data) +
  geom_segment(aes(x = x, xend = x, y = 0, yend = yend, colour = yend)) +
  xlab("") + ylab("S&P 500 Daily Return %") +
  scale_colour_gradientn(colours = cols, 
                         values = rescale(c(-10, -1, 0, 1, 10)),
                         guide = "colorbar", limits=c(-10, 10)) +
  theme(legend.position = "null", axis.title.x = element_blank())

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...