Why ggplot use different color scheme on factor type and how to change the default color scheme to "hue" globally?

Viewed 76

I meet a problem that makes me very confusing.

I try to convert a column into an ordered factor and plot with ggplot2. However, the ggplot2 used a different color scheme after I converted. The script shows as follows:

ta <- data.frame(x=c('b','a','d'),
                 y=c(1.2, 2.4, 3.3))

tta <- ggplot(data=ta, aes(x=x, y=y, fill=x))+
    geom_bar(stat='identity', position=position_dodge())
ggsave(file='p1.png', height=2, width=2.6)
    
ta$x <- factor(ta$x, levels=c('a','d','b'), ordered=TRUE)
## ta$x <- ordered(ta$x, levels=c('a','d','b'))
tta <- ggplot(data=ta, aes(x=x, y=y, fill=x))+
    geom_bar(stat='identity', position=position_dodge())
ggsave(file='p2.png', height=2, width=2.6)

  • p1.png enter image description here
  • p2.png enter image description here

I would like the ggplot2 to use the default color theme as p1.png showed even though I convert a column into an ordered factor.

Yes, I could use scale_fill_discrete() to specify the color. However, I want to know what is the reason that ggplot2 use a different color theme and I am looking for a more elegant way.

Thanks for your help.

> sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.4 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=zh_CN.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=zh_CN.UTF-8        LC_COLLATE=zh_CN.UTF-8    
 [5] LC_MONETARY=zh_CN.UTF-8    LC_MESSAGES=zh_CN.UTF-8   
 [7] LC_PAPER=zh_CN.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=zh_CN.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
[1] extrafont_0.17 dplyr_1.0.7    plyr_1.8.6     reshape2_1.4.4 ggplot2_3.3.5 
[6] stringr_1.4.0  stringi_1.7.6 

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.7        Rttf2pt1_1.3.8    magrittr_2.0.1    tidyselect_1.1.1 
 [5] munsell_0.5.0     viridisLite_0.4.0 colorspace_2.0-2  R6_2.5.0         
 [9] rlang_0.4.11      fansi_0.5.0       tools_3.6.3       gtable_0.3.0     
[13] utf8_1.2.2        cli_2.5.0         extrafontdb_1.0   withr_2.4.2      
[17] systemfonts_1.0.2 ellipsis_0.3.2    digest_0.6.27     tibble_3.1.2     
[21] lifecycle_1.0.0   crayon_1.4.1      farver_2.1.0      purrr_0.3.4      
[25] vctrs_0.3.8       glue_1.4.2        labeling_0.4.2    compiler_3.6.3   
[29] pillar_1.6.1      generics_0.1.0    scales_1.1.1      svglite_2.0.0    
[33] pkgconfig_2.0.3  
1 Answers

This is the intended behavior of ggplot2. If your factor is ordered, their corresponding colors should be ordered, too. By default, colors are ordered using the viridis sequential color scheme. On the other hand, for unordered factors, one wants to have no explicit color order, so here the categorial hue color scheme is used instead. Ironically, this hue palette has also an implicit color ordering which follows the rainbow spectrum. Finally, it is a little bit subjective to define color ordering at all.

If you want to get the p1.png in ordered factors, you could add scale_fill_hue() in the scripts as follows:

ta$x <- factor(ta$x, levels=c('a','d','b'), ordered=TRUE)
## ta$x <- ordered(ta$x, levels=c('a','d','b'))
tta <- ggplot(data=ta, aes(x=x, y=y, fill=x))+
    geom_bar(stat='identity', position=position_dodge())+
    scale_fill_hue()
ggsave(file='p3.png', height=2, width=2.6)

And If you want to globally change the default behavior on ordered factors, you could add the flowing script to .Rprofile in linux(It did not work, what happened?) :

options(ggplot2.continuous.colour="hue")
options(ggplot2.continuous.fill = "hue")
options(ggplot2.discrete.colour="hue")
options(ggplot2.discrete.fill = "hue")
Related