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
258 views
in Technique[技术] by (71.8m points)

r - Using different scales as fill based on factor

cnt = 100
df <- data.frame(x = c(rnorm(cnt, mean = 3), rnorm(cnt, mean = 0)),
                 y = rnorm(2 * cnt), g = rep(0:1, each = cnt))

ggplot(df, aes(x, y, color = as.factor(g))) + 
  stat_density2d(aes(fill = ..level..), alpha = 0.3, geom = "polygon")

This creates a filled contour plot based on factor: enter image description here

I'd like to use a different fill scale for each contour, such that g = 0 has a red fill while g = 1 has a blue fill. Is this possible and if so, how?

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

As already commented by @joran, the basic design in ggplot is one scale per aesthetic. Work-arounds of various degree of ugliness are therefore required. Often they involve creation of one or more plot object, manipulation of the various components of the object, and then producing a new plot from the manipulated object(s).

Here two plot objects with different fill colour palettes - one red and one blue - are created by setting colours in scale_fill_continuous. In the 'red' plot object, the red fill colours in rows belonging to one of the groups, are replaced with blue colours from the corresponding rows in the 'blue' plot object.

library(ggplot2)
library(grid)
library(gtable)

# plot with red fill
p1 <- ggplot(data = df, aes(x, y, color = as.factor(g))) +
  stat_density2d(aes(fill = ..level..), alpha = 0.3, geom = "polygon") +
  scale_fill_continuous(low = "grey", high = "red", space = "Lab", name = "g = 0") +
  scale_colour_discrete(guide = FALSE) +
  theme_classic()

# plot with blue fill
p2 <- ggplot(data = df, aes(x, y, color = as.factor(g))) +
  stat_density2d(aes(fill = ..level..), alpha = 0.3, geom = "polygon") +
  scale_fill_continuous(low = "grey", high = "blue", space = "Lab", name = "g = 1") +
  scale_colour_discrete(guide = FALSE) +
  theme_classic()


# grab plot data
pp1 <- ggplot_build(p1)
pp2 <- ggplot_build(p2)$data[[1]]


# replace red fill colours in pp1 with blue colours from pp2 when group is 2
pp1$data[[1]]$fill[grep(pattern = "^2", pp2$group)] <- pp2$fill[grep(pattern = "^2", pp2$group)]


# build plot grobs
grob1 <- ggplot_gtable(pp1)
grob2 <- ggplotGrob(p2)

# build legend grobs
leg1 <- gtable_filter(grob1, "guide-box") 
leg2 <- gtable_filter(grob2, "guide-box") 
leg <- gtable:::rbind_gtable(leg1[["grobs"]][[1]],  leg2[["grobs"]][[1]], "first")


# replace legend in 'red' plot
grob1$grobs[grob1$layout$name == "guide-box"][[1]] <- leg


# plot
grid.newpage()
grid.draw(grob1)

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

...