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

r - How to assign a Colour Scale based on Y-axis in ggplot

I am trying to assign a colour scale/gradient to some violin plots based on the y-axis value of Income. However, I only get a white violin plot. I can change the colour based on state.region but not Income.

Data

USA.states <- data.frame(state.region,state.x77)

Code

p <- ggplot(USA.states,aes(x=state.region,y=Income,fill=Income))+
geom_violin(trim = F,)+
ggtitle("Violin plot of income and Population")

p + scale_fill_gradient(low="red",high="blue")

I assigned the fill to Income but it just ends up filled with white.

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

You can create a pseudo-fill from segments, and you can create those from the underlying data (in the ggplot_built object) directly.

If you want an additional polygon outline, you would still need to create the polygons manually though, using x and y coordinates as calculated for the segments. (There is certainly a cleverer way to put this into a data frame than below, so don't take this as gospel).

Of another note, the violins in the original plot seem to be scaled, but I don't exactly understand how, so I just scaled it with a constant which I found with some trial and error.

library(tidyverse)

USA.states <- data.frame(state.region,state.x77)
p <- ggplot(USA.states,aes(x=state.region,y=Income,fill=Income))+
  geom_violin(trim = F)

mywidth <- .35 # bit of trial and error
# This is all you need for the fill: 
vl_fill <- data.frame(ggplot_build(p)$data) %>%
  mutate(xnew = x- mywidth*violinwidth, xend = x+ mywidth*violinwidth) 

# Bit convoluted for the outline, need to be rearranged: the order matters
vl_poly <- 
  vl_fill %>% 
  select(xnew, xend, y, group) %>%
  pivot_longer(-c(y, group), names_to = "oldx", values_to = "x") %>% 
  arrange(y) %>%
  split(., .$oldx) %>%
  map(., function(x) {
    if(all(x$oldx == "xnew")) x <- arrange(x, desc(y))
    x
    }) %>%
  bind_rows()

ggplot() +
  geom_polygon(data = vl_poly, aes(x, y, group = group), 
               color= "black", size = 1, fill = NA) +  
  geom_segment(data = vl_fill, aes(x = xnew, xend = xend, y = y, yend = y,
                                   color = y))  

Created on 2021-04-14 by the reprex package (v1.0.0)


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

...