Code Monkey home page Code Monkey logo

biscale's Introduction

biscale

GitHub Workflow Coverage status CRAN_status_badge cran checks Downloads Total_Downloads DOI

biscale implements a set of functions for bivariate thematic mapping based on the tutorial written by Timo Grossenbacher and Angelo Zehr as well as a set of bivariate mapping palettes, including Joshua Stevens’ classic color schemes.

In addition to support for two-by-two, three-by-three, and four-by-four maps, the package also supports a range of methods for calculating breaks for bivariate maps.

What’s New in v1.0.0?

New Features

  • bi_class() now accepts factors for one or both of the x and y variables, allowing more flexibility for how breaks are calculated. If you want finer grained control over your categories, calculate them ahead of time and then pass the factors on to bi_class().
  • bi_pal(), bi_legend(), bi_scale_fill(), and bi_scale_color() functions all support four-by-four bivariate maps when dim = 4. Note that the original five palettes do not support four-by-four mapping, but very close approximations (e.g. DkBlue2 instead of DkBlue) are now provided in their place. The legacy palettes are all still included in the package.
  • The number of built-in palettes has been greatly expanded!
  • Palettes can now be flipped and rotated (or both!), so that each built-in palette can be displayed in four different configurations. This includes the built-in palettes and any custom palettes that are four-by-four or smaller. If you want to flip or rotate larger palettes, you should make those decisions while creating the palette itself.
  • The workflow for allowing custom palettes has been overhauled to simply the process - users can provide a named vector for the pal arguments in the bi_pal(), bi_legend(), bi_scale_fill(), and bi_scale_color() functions. All of these functions will validate your input to ensure that it maps correctly.
  • bi_class() can be used to calculate bivariate breaks for maps larger than four-by-four, though it will return a warning reminding you that these maps are hard to read and that biscale does not provide palettes for larger maps. Instead, you should provide a custom palette.
  • bi_class_breaks() can be used with bi_legend() to facilitate optionally adding break values to your legends. Like bi_class(), this new function accepts both continuous and pre-made factors.

Breaking Changes

  • R version 3.4 is no longer supported - please use at least R version 3.5
  • There is no default supplied for bi_class()’s style argument since bi_class() now accepts factors as well. Users that relied on the default behavior of bi_class() will now receive an error asking you to specify a style for calculating breaks.

Deprecated Functions

  • bi_pal_manual() now returns a warning that it has been deprecated and will be removed in a later release of biscale (planned for the end of 2022). Please update your workflows to use the new approach to generating custom palettes.

Internal Improvements

  • sf is now a suggested package instead of an imported package, and several dependencies have been removed in the process of re-factoring all of the code in biscale.

Documentation Improvements

  • Documentation updates have been made, including the addition of a number of new examples and vignettes. These include detailed articles on bivariate palettes, working with breaks and legends, and creating bivariate maps with raster data.

What’s New in the Development Version (v1.1.0.9000)?

These require the development version to be installed using remotes::install_github(), described in the next section.

New Features

  • The bi_legend() function now has a base_family argument, which can be paired with the suggested showtext package to display non-Latin characters. See the “Options for Breaks and Legends” vignette for details on using this new feature.

Installation

Installing biscale

The easiest way to get biscale is to install it from CRAN:

install.packages("biscale")

Alternatively, the development version of biscale can be accessed from GitHub with remotes:

# install.packages("remotes")
remotes::install_github("chris-prener/biscale")

Installing Suggested Dependencies

Since the package does not directly use functions from sf, it is a suggested dependency rather than a required one. However, the most direct approach to using biscale is with sf objects, and we therefore recommend users install sf. Windows and macOS users should be able to install sf without significant issues unless they are building from source. Linux users will need to install several open source spatial libraries to get sf itself up and running.

The other suggested dependency that users may want to consider installing is cowplot. All of the examples in the package documentation utilize it to construct final map images that combine the map with the legend. Like sf, it is suggested because none of the functions in biscale call cowplot directly.

If you want to use them, you can either install these packages individually (faster) or install all of the suggested dependencies at once (slower, will also give you a number of other packages you may or may not want):

## install just cowplot and sf
install.packages(c("cowplot", "sf"))

## install all suggested dependencies
install.packages("biscale", dependencies = TRUE)

Usage

Quick Overview

Creating bivariate plots in the style described by Grossenbacher and Zehr requires a number of dependencies in addition to biscale - ggplot2 for plotting and sf for working with spatial objects in R. We’ll also use cowplot in these examples:

# load dependencies
library(biscale)
library(ggplot2)
library(cowplot)
library(sf)

The biscale package comes with some sample data from St. Louis, MO that you can use to check out the bivariate mapping workflow. Our first step is to create our classes for bivariate mapping. biscale currently supports a both two-by-two and three-by-three tables of classes, created with the bi_class() function:

# create classes
data <- bi_class(stl_race_income, x = pctWhite, y = medInc, style = "quantile", dim = 3)

The default method for calculating breaks is "quantile", which will provide breaks at 33.33% and 66.66% percent (i.e. tercile breaks) for three-by-three palettes. Other options are "equal", "fisher", and "jenks". These are specified with the optional style argument. The dim argument is used to adjust whether a two-by-two and three-by-three tables of classes is returned.

Once breaks are created, we can use bi_scale_fill() as part of our ggplot() call:

# create map
map <- ggplot() +
  geom_sf(data = data, mapping = aes(fill = bi_class), color = "white", size = 0.1, show.legend = FALSE) +
  bi_scale_fill(pal = "GrPink", dim = 3) +
  labs(
    title = "Race and Income in St. Louis, MO",
    subtitle = "Dark Blue (DkBlue) Palette"
  ) +
  bi_theme()

There are a variety of other options for palettes. See the “Bivarite Palettes” vignette or ?bi_pal for more details. The bi_theme() function applies a simple theme without distracting elements, which is preferable given the already elevated complexity of a bivariate map. We need to specify the dimensions of the palette for bi_scale_fill() as well.

To add a legend to our map, we need to create a second ggplot object. We can use bi_legend() to accomplish this, which allows us to easily specify the fill palette, the x and y axis labels, and their size along with the dimensions of the palette:

legend <- bi_legend(pal = "GrPink",
                    dim = 3,
                    xlab = "Higher % White ",
                    ylab = "Higher Income ",
                    size = 8)

Note that plotmath is used to draw the arrows since Unicode arrows are font dependent. This happens internally as part of bi_legend() - you don’t need to include them in your xlab and ylab arguments!

With our legend drawn, we can then combine the legend and the map with cowplot. The values needed for this stage will be subject to experimentation depending on the shape of the map itself.

# combine map with legend
finalPlot <- ggdraw() +
  draw_plot(map, 0, 0, 1, 1) +
  draw_plot(legend, 0.2, .65, 0.2, 0.2)

The completed map, created with the sample code in this README, looks like this:

Contributor Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

biscale's People

Contributors

bransonf avatar chris-prener avatar kguidonimartins avatar rickpack avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

biscale's Issues

CRAN Note

Somehow utils and stats ended up in the DESCRIPTION file even though functions from those packages are not used!

CRAN errors reproduced in sf/sp/rgdal/raster revdeps

Please try to replicate the errors with PROJ >= 6, GDAL >= 3, and CRAN sf:

* checking examples ... ERROR
Running examples in ‘biscale-Ex.R’ failed
The error most likely occurred in:

> ### Name: bi_class
> ### Title: Create Classes for Bivariate Maps
> ### Aliases: bi_class
> 
> ### ** Examples
> 
> # quantile breaks, 2x2
> data <- bi_class(stl_race_income, x = pctWhite, y = medInc, style = "quantile", dim = 2)
Warning in bi_class(stl_race_income, x = pctWhite, y = medInc, style = "quantile",  :
  The 'sf' package is not loaded, and the class 'sf' attribute of the given data set has been lost. Load 'sf' to retain the class when using 'bi_class'.
Error: All columns in a tibble must be vectors.
✖ Column `geometry` is a `sfc_POLYGON/sfc` object.
Backtrace:
     █
  1. └─biscale::bi_class(...)
  2.   ├─dplyr::mutate(.data, bi_x = cut(!!xQ, breaks = bins_x, include.lowest = TRUE))
  3.   └─dplyr:::mutate.data.frame(...)
  4.     ├─base::as.data.frame(mutate(tbl_df(.data), ...))
  5.     ├─dplyr::mutate(tbl_df(.data), ...)
  6.     └─dplyr::tbl_df(.data)
  7.       ├─tibble::as_tibble(data, .name_repair = "check_unique")
  8.       └─tibble:::as_tibble.data.frame(data, .name_repair = "check_unique")
  9.         └─tibble:::lst_to_tibble(unclass(x), .rows, .name_repair)
 10.           └─tibble:::check_valid_cols(x)
Execution halted
* checking for unstated dependencies in ‘tests’ ... OK
* checking tests ... ERROR
  Running ‘testthat.R’
Running the tests in ‘tests/testthat.R’ failed.
Last 13 lines of output:
  Backtrace:
    1. testthat::expect_warning(...)
    6. biscale::bi_class(...)
    8. dplyr:::mutate.data.frame(...)
   11. dplyr::tbl_df(.data)
   13. tibble:::as_tibble.data.frame(data, .name_repair = "check_unique")
   14. tibble:::lst_to_tibble(unclass(x), .rows, .name_repair)
   15. tibble:::check_valid_cols(x)
  
  ══ testthat results  ═══════════════════════════════════════════════════════════
  [ OK: 82 | SKIPPED: 0 | WARNINGS: 0 | FAILED: 1 ]
  1. Error: sf warning is triggered (@test_bi_class.R#10) 
  
  Error: testthat unit tests failed
  Execution halted

Please refer to sf PROJ issues for links to containers, or install PROJ/GDAL yourself to check.

Probably a dplyr/tidyverse non-backwards-compatible problem, mute test if easier.

Insufficient values in manual scale. 10 needed but only 9 provided.

Before you open your issue:

Describe the bug
I am trying to create a bivariate map of some data on the city census block group level. For 8 out of the 10 cities I am analyzing, I have had no issues. However, for certain fields for a particular city, I get the error as shown in the title.

Expected behavior
Normally there is an output of a bivariate map with 9 classes. However, there is no output.

To Reproduce
Please include a minimal reproducible example (AKA a reprex). If you've never
heard of a reprex before, start by reading
https://www.tidyverse.org/help/#reprex. When you create your reprex, please use a data set available in a package.
mke.zip

# inset reprex here

library(sf)
library(ggplot2)
library(biscale)
library(cowplot)

d = read_sf('cities/mke.shp')


breaks = bi_class(d, x=cbg_o_medi, y=median_inc, style='equal', dim=3)

# create map
map <- ggplot() +
  geom_sf(data = breaks, mapping = aes(fill = bi_class), color = "#DEDEDE", size = 0.1, show.legend = FALSE)+
  bi_scale_fill(pal = "DkViolet", dim = 3) +
  labs(
    subtitle = "Distance and Income in Milwaukee at CBG Level"
  ) +
  bi_theme()
map

legend <- bi_legend(pal = "DkViolet",
                    dim = 3,
                    xlab = "Median Distance ",
                    ylab = "Median Income ",
                    size = 26)

# combine map with legend
finalPlot <- ggdraw() +
  draw_plot(map, 0, 0, 1, 1) +
  draw_plot(legend, 0.55, .65, 0.2, 0.2)

finalPlot

Screenshots
If applicable, add screenshots to help explain your problem.
bug

Desktop (please complete the following information):

  • OS: Windows 10
  • Version of R 3.6.1
  • Version of RStudio 1.2.5001

Additional context
Please unzip the file I attached and use the code I had to reproduce the problem. You can also see that if you change y=median_inc to y=entropy, there is no issue. It is strange. I double checked the columns for the data set and it seems 100% fine and is read in another GIS program.

Although I run `showtext::showtext_auto()` before plot, `bi_legend` doesn't allow chinese character

A minimal example

library(biscale)
library(ggplot2)
library(cowplot)
library(sf)
#> Linking to GEOS 3.10.2, GDAL 3.4.2, PROJ 8.2.1; sf_use_s2() is TRUE

showtext::showtext_auto()

# create classes
data <- bi_class(stl_race_income, x = pctWhite, y = medInc, style = "quantile", dim = 3)

# create map
map <- ggplot() +
  geom_sf(data = data, mapping = aes(fill = bi_class), color = "white", size = 0.1, show.legend = FALSE) +
  bi_scale_fill(pal = "GrPink", dim = 3) +
  labs(
    title = "Race and Income in St. Louis, MO",
    subtitle = "Dark Blue (DkBlue) Palette"
  ) +
  bi_theme()

legend <- bi_legend(pal = "GrPink",
                    dim = 3,
                    xlab = "Higher % 白人", # Here are some chinese characters.
                    ylab = "Higher 收入 ", # Here are some chinese characters.
                    size = 8)

# combine map with legend
finalPlot <- ggdraw() +
  draw_plot(map, 0, 0, 1, 1) +
  draw_plot(legend, 0.2, .65, 0.2, 0.2)


sessionInfo()
#> R version 4.2.0 (2022-04-22)
#> Platform: x86_64-apple-darwin17.0 (64-bit)
#> Running under: macOS Big Sur/Monterey 10.16
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib
#> 
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] sf_1.0-7      cowplot_1.1.1 ggplot2_3.3.6 biscale_1.0.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] styler_1.7.0       tidyselect_1.1.2   xfun_0.31          purrr_0.3.4       
#>  [5] colorspace_2.0-3   vctrs_0.4.1        generics_0.1.2     htmltools_0.5.2   
#>  [9] s2_1.0.7           yaml_2.3.5         utf8_1.2.2         rlang_1.0.2       
#> [13] R.oo_1.24.0        e1071_1.7-9        pillar_1.7.0       glue_1.6.2        
#> [17] withr_2.5.0        DBI_1.1.2          R.utils_2.11.0     wk_0.6.0          
#> [21] R.cache_0.15.0     lifecycle_1.0.1    stringr_1.4.0      munsell_0.5.0     
#> [25] gtable_0.3.0       R.methodsS3_1.8.1  evaluate_0.15      labeling_0.4.2    
#> [29] knitr_1.39         fastmap_1.1.0      class_7.3-20       fansi_1.0.3       
#> [33] highr_0.9          Rcpp_1.0.8.3       KernSmooth_2.23-20 scales_1.2.0      
#> [37] classInt_0.4-3     showtext_0.9-5     sysfonts_0.8.8     farver_2.1.0      
#> [41] fs_1.5.2           digest_0.6.29      stringi_1.7.6      showtextdb_3.0    
#> [45] dplyr_1.0.9        grid_4.2.0         cli_3.3.0          tools_4.2.0       
#> [49] magrittr_2.0.3     proxy_0.4-26       tibble_3.1.7       crayon_1.5.1      
#> [53] pkgconfig_2.0.3    ellipsis_0.3.2     reprex_2.0.1       assertthat_0.2.1  
#> [57] rmarkdown_2.14     rstudioapi_0.13    R6_2.5.1           units_0.8-0       
#> [61] compiler_4.2.0

Created on 2022-05-27 by the reprex package (v2.0.1)

Rplot

Improving legend style

I would like to propose a change in the style of the legend by changing to open axes with arrows. The following are changes I made on the basis of a biscale's older version.

leg <- tidyr::separate(x, bi_class, into = c("x", "y"), 
                        sep = "-")
 leg <- dplyr::mutate(leg, x = as.integer(x), y = as.integer(y))
 legend <- ggplot2::ggplot() + ggplot2::geom_tile(data = leg, 
                                                  mapping = ggplot2::aes(x = x, y = y, fill = bi_fill), 
                                                  lwd = pad_width, col = pad_color) + ggplot2::scale_fill_identity() + 
   ggplot2::labs(x = xQN, y = yQN) + bi_theme() + 
   ggplot2::theme_light() +
   ggplot2::theme(panel.border=element_blank(), 
                  axis.title.x = element_text(vjust = -.7, hjust = .2, size = size),
                  axis.title.y = element_text(vjust = .7, hjust = .2, size = size),
                  axis.line = element_line( size = .5, arrow = arrow(type = "closed", length = unit(.07, "in"))), 
                  axis.ticks = element_blank(),
                  axis.text = element_blank(),
                  panel.grid = element_blank(),
                  panel.background = element_blank(),
                  plot.background = element_blank()) + 
   lemon::coord_capped_cart(bottom="both", left = "both") 

Example:
image

Title for legend

Curious if there is any work being done to add a title for the bi_legend function.

Thanks!

GitHub Actions

Tasks:

  1. Set-up CI build on GitHub actions
  2. Address build errors
  3. Add pkgdown GitHub action for site build
  4. README.md and repo housekeeping (remove old CI files, update badges)
  5. Ensure code coverage is working correctly

fisher transformation in `bi_class`

Hi there - no reprex to provide here - I couldn't find in your documentation or wiki a reference as to how style "fisher" is calculated in function bi_class. Would you mind providing a reference for example? Thanks in advance for this - and many thanks for this package!

Bivariate plot for point data

Hi, I asked about this on twitter first (tweet link: https://twitter.com/umairdurrani87/status/1138644593799520256)

Data description and feature request

I have annual snowfall and the proportion of road crashes in bad weather in different locations in Ontario. I want to visualize the combination of these two variables, e.g. which locations get a lot of snow and also have a higher proportion of crashes; similarly which locations have almost no snowfall but a higher proportion of crashes, etc.

What I have tried

I thought that if I create geom_raster layers for both variables and then plot them on top of each other then I might see some combined effect. However, using the original data size, even a single rasterized layer exceeds the memory size.

Reproducible example

Following is a reproducible example that shows the maps for both snow and the proportion of crashes. I want to visualize them both effectively on a single map.

# Load Libraries------------------------
library(tidyverse)
library(sf)
library(raster)



# Load Data-----------------------------
## Ontario boundary file (cropped):
cdn <-  getData("GADM",country="can",level=1)
ont <-  cdn[9,]
ont <-  st_as_sf(ont) # rgeos package might be required
ont_central <- st_crop(ont, xmin=-80.5, xmax=-78, ymin=42.5, ymax=44.9)


## Snowfall and Crash data (download here: https://1drv.ms/u/s!AsMFpkDhWcnw7yA4L9q5AJ2ffwl_?e=Rrs6Ra):
data_central <- sf::st_read("data/tidy_data/data_central.shp")



# Create maps of snowfall and proportion of crashes in bad weather--------------------
snow_plot <- ggplot() + 
  geom_sf(data = ont_central, fill = "grey", col = "white") +
  geom_sf(data = data_central, aes(color= totalsnow), size = 1.5, show.legend = "line")  +
  scale_color_viridis_c(na.value = NA, direction = -1)


prop_plot <- ggplot() + 
  geom_sf(data = ont_central, fill = "grey", col = "white") +
  geom_sf(data = data_central, aes(color= Ratio1517), size = 1.5, show.legend = "line")  +
  scale_color_viridis_c(na.value = NA, direction = -1)

Error in cut.default(.data[[var]], breaks = classInt::classIntervals(.data[[var]], : 'breaks' are not unique

Hello,

I am using biscale for the first time. I get this error when applying the function bi_class() to my tibble:

Error in cut.default(.data[[var]], breaks = classInt::classIntervals(.data[[var]],  : 
  'breaks' are not unique

Here is a reprex

library(biscale)

structure(
  list(
    Wind = c(0, 0, 0, 3.075, 0, 0, 0, 0, 0, 0, 0, 
             0, 0, 0, 0, 0, 0, 0, 0, 0, 6.95, 0, 0, 0, 0, 0, 0, 0, 0.8, 0, 
             0, 0, 5.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0075, 0, 
             0, 0), 
    Solar = c(0.18458, 0.293515, 0.00612, 0.127635, 0.66814, 
              0.725785, 0.179215, 0.043085, 0.07204, 0.01341, 0.02189, 0.199785, 
              0.47441, 0.362335, 0.291116, 0.05846, 0.41429, 0.242265, 0.01014, 
              0.147255, 0.065362, 0.17468, 0.715965, 0.378433, 0.10354, 0.153748, 
              0.00722, 0.014, 0.107345, 0.08022, 0.12878, 0.22564, 0.152975, 
              0.6022, 0.22945, 0.0136, 0.342495, 0.192355, 0.27368, 0.285308, 
              0.429722, 0.106095, 0.00951, 2.21347, 0.069035, 0.370935, 0.07958, 
              0.03371, 0.392245, 0.18588)), 
  row.names = c(NA, -50L), 
  class = c("tbl_df", "tbl", "data.frame")) |> 
  bi_class(
    x = Solar, 
    y = Wind, 
    style = "quantile", 
    dim = 3
  )  
#> Error in cut.default(.data[[var]], breaks = classInt::classIntervals(.data[[var]], : 'breaks' are not unique

Created on 2022-08-15 by the reprex package (v2.0.1)

Thanks a lot!

Fix documentation typos

The following typos exist in documentation:

  • areal references in main vignette
  • missing mapping = aes() in examples on README and main vignette
  • references to bs_ functions, which were changed to bi_ prior to release

Vignette example code error

Describe the bug
Vignette example code does not work. I guess it's because of mapping that appears before aes().

# create map
map <- ggplot() +
  geom_sf(data = data, mapping aes(fill = bi_class), color = "white", size = 0.1, show.legend = FALSE) +
  bi_scale_fill(pal = "DkBlue", dim = 3) +
  labs(
    title = "Race and Income in St. Louis, MO",
    subtitle = "Dark Blue (DkBlue) Palette"
  ) +
  bi_theme()

Expected behavior
The vignette should probably look the same as work the same as the readme code.

Custom color palette to apply in 'biscale' package

Thank you for the wonderful 'biscale' package. I intend to apply a custom 3 x 3 color palette adapted from the 'DkViolet' palette to suit my purposes.

R Code:

Creating custom 3x3 color palette

bivariate_color_scale_2 <- tibble(
"3 - 3" = "#77324C",
"2 - 3" = "#AE3A4E",
"1 - 3" = "#BC7C8F",
"3 - 2" = "#3F2949",
"2 - 2" = "#806A8A",
"1 - 2" = "#CABED0",
"3 - 1" = "#435786",
"2 - 1" = "#4885C1",
"1 - 1" = "#89A1C8"
)

R Code:

Visualizing color palette

bivariate_color_scale_2 %>%
gather("group", "fill") %>%
separate(group, into = c("x", "y"), sep = " - ") %>%
mutate(x = as.integer(x),
y = as.integer(y)) %>%
ggplot(aes(x, y)) +
geom_tile(aes(fill = fill)) +
scale_fill_identity()

When creating the plots, I switched out the 'bi_scale_fill' function with 'scale_fill_manual'.

R Code:

Create plots

plot <- ggplot() +
geom_sf(data = data, mapping = aes(fill = bi_class), color = NA, size = 0.01, show.legend = FALSE) + scale_fill_manual(pal = bivariate_color_scale_2)`

However, this did not work, and I received an error message;
"Error in self$palette(n) : attempt to apply non-function.", which tells me that my usage of scale_fill_manual is wrong.

May I kindly inquire how to go about creating my own custom color palettes (e.g. DkViolet, GrPink) that I can use in the 'bi_scale_fill' function? I am asking this because I am not having much luck tampering with the 'scale_fill_manual' function.

Thank you kindly. Hope to hear from you soon.

add color hex code labels to bi_pal()

When running bi_pal() to check my palette, it would be helpful to have an option to see the color hex codes printed on top of the palette tiles, like this:
custom_pal3.plot_biscale_palette.pdf

Describe the solution you'd like
I think this is pretty easy to implement. Just add a boolean on/off switch to bi_pal() and then a line like:
ggplot2::geom_text(data = leg, ggplot2::aes(x = x, y = y, label = bi_fill)) +
to the ggplot call in bi_legend_build().

Describe alternatives you've considered
I implemented this as standalone code. I can't think of a reason it shouldn't be part of the biscale package itself. But maybe I'm missing something?

Plotting bivariate rasters

It would be interesting to add the possibility to plot bivariate rasters.
I tried to start a sample code and went up to the biclass function, although I could not find the way to plot it in GGPLOT:
library(raster)
library(biscale)
library(sp)
rh<-raster("rh_suitability_mean.tif")
ppd <- raster("ppd.tif")
rh_resampled<-resample(x=rh,y=ppd)
bivariate_grid<-as(ppd,"SpatialPixelsDataFrame")
bivariate_grid$rh <- (extract(rh_resampled,bivariate_grid))
bivariate_grid.df<-as.data.frame(bivariate_grid)
View(bivariate_grid.df)
bi_class <- bi_class(bivariate_grid.df, x = ppd, y = rh, style = "quantile", dim = 3)

Custom Palette not Allowed

Error message: "Error in pal_validate(pal = pal, dim = dim, flip_axes = flip_axes, rotate_pal = rotate_pal) :
The given palette is not one of the allowed options for bivariate mapping. Please see bi_pal's help file for a list of included palettes."

`custom_pal <- c(
"1-1" = "#1054BF", # low x, low y
"2-1" = "#BF1054", # high x, low y
"1-2" = "#0C3F90", # low x, high y
"2-2" = "#900C3F" # high x, high y
)

bi_pal(pal = custom_pal, dim = 2)

legend = bi_legend(pal = "custom_pal",
dim = 2,
size = 7)`

What's going wrong here?

Add formatting to numbers output by bi_class_breaks()

Might you enable the passing of functions to bi_class_breaks() to format numbers?

Or, for my particular interest, you could add an SI_lab (International System of Units) parameter that would pass digits to the si_number function in my code below.

This reduction of text for large numbers makes it easier to increase the font size and position the legend.

Currently

image

With proposed SI_lab parameter

Using SI_lab(3)
image

Code to aid addition of SI_lab parameter

First, create miami_rent_income object using my code at https://stackoverflow.com/a/72591940/2305061.

Then, focusing on modification to labels1.

miami_rent_income_bivar <-
  biscale::bi_class(miami_rent_income,
                    x = Median_Rent,
                    y = Median_Income, 
                    style = "jenks",
                    dim = 3)

labels1 <- bi_class_breaks(miami_rent_income, 
                           x = Median_Rent, 
                           y = Median_Income, 
                           style = "jenks", 
                           dim = 3, dig_lab = c(20,20), split = FALSE)

## function found at https://stackoverflow.com/a/59086755/2305061
si_number = function(x, digits) {
  
  compress = function(x, n) {
    signif(x * 10^(-n), digits)
  }
  
  case_when(
    ## decimals like 0.33
    abs(x) <    1   ~ as.character(x),   
    abs(x) >= 1e6   ~ paste0(compress(x, 6), "M"),
    abs(x) >= 1000  ~ paste0(compress(x, 3), "k"),
    abs(x) >= 1     ~ as.character(compress(x, 0)),
    abs(x) >= 0.001 ~ paste0(compress(x, -3), "m"),
    abs(x) >= 1e-6  ~ paste0(compress(x, -6), "u"),
    ## number of 0
    TRUE ~ as.character(x)
  )
}

labels1$bi_x <- paste0(si_number(as.numeric(str_extract(labels1$bi_x, ".+?(?=-)")), 3)
                       ,"-",
                       si_number(as.numeric(str_extract(labels1$bi_x, "(?<=\\-).*")), 3)
)
labels1$bi_y <- paste0(si_number(as.numeric(str_extract(labels1$bi_y, ".+?(?=-)")), 3)
                       ,"-",
                       si_number(as.numeric(str_extract(labels1$bi_y, "(?<=\\-).*")), 3)
)


miami_rent_income_bivar_legend <- bi_legend(pal = "DkCyan",
                                             breaks = labels1,
                                             xlab = "Median Rent ($)",
                                             ylab = "Median Income ($)",
                                             size = 08)

Generate Custom Palettes

Hi both - I just pulled together a function which allows for n x n sequential colours schemes using {colorspace} for a project am working on (needed a 5x5 for quartiles plus a zero category).
Not sure if useful for you guys - but would be happy to handover to integrate in {biscale}.

See function here: https://github.com/R4IDSR/epichecks/blob/master/R/bivarcolours.R
And ggplot map code here: https://github.com/R4IDSR/epichecks/blob/master/inst/rmarkdown/templates/monthly_bulletin/skeleton/skeleton.Rmd#L1007

Originally posted by @aspina7 in #12 (comment)

allow ordered factors, arbitrary dimensions in bivariate color scales

I would like to compose bivariate color scales with arbitrary dimensions to accommodate ordered factors. This feature would expand use of this package to a broader set of data that could benefit from a cross-classified color scale. For example, a bivariate color scale might allow an ordered factor (low vs. high) to be encoded as lightness or saturation variants of the other dimension's color scale.

I'm imagining a color scale that looks something like this:
image

Proposed solution
I think bi_class is the main function that would need modification. The style and dim would gain the option of being specified as vectors of length 2 corresponding to the argument values to use for x and y. style would also gain a new possible value, something like ordered, factor, or levels. This option would retrieve the unique values of the variable rather than trying to calculate breaks as for a continuous variable. (Add a warning here if the variable isn't ordered.)

In the above figure, this solution would look something like: bi_class(.data, x = ord, y = cont, style = c("levels", "quantile"), dim = c(2, 3))

Some careful thought is needed to ensure that the color modification for the factor doesn't cause collisions. If willing to add a dependency, colorspace has some nice functions for automating the calculation of lightened or desaturated colors for an arbitrary number of levels. An additional argument might allow the user to specify the type of color modification (lighten vs. desaturate) and the corresponding amounts of adjustment for each factor level (e.g., lightening 0 and 0.4).

Reprex
The code below reproduces the figure above.

library(ggplot2)
library(colorspace)
library(patchwork)

pal <- c("#FECE65", "#E1640E", "#662506")

dat <- data.frame(y = factor(rep(c("<18", "18-45", ">45"), times = 2),
                             levels = c("<18", "18-45", ">45")),
                  x = factor(rep(c("low", "high"), each = 3),
                             levels = c("low", "high")))
dat$bi_class <- paste(as.integer(dat$x), as.integer(dat$y), sep = "-")

d <- ggplot(dat, aes(x = x, y = y, fill = bi_class))+
  geom_tile()+
  labs(title = "Desaturate", x = "[ordered factor]", y = "[continuous variable]")+
  scale_fill_manual(values = c(desaturate(pal, amount = 0.7), pal))+
  coord_equal(expand = FALSE)+
  theme_minimal()+
  theme(legend.position = "none")

l <- ggplot(dat, aes(x = x, y = y, fill = bi_class))+
  geom_tile()+
  labs(title = "Lighten", x = "[ordered factor]", y = "[continuous variable]")+
  scale_fill_manual(values = c(lighten(pal, amount = 0.4), pal))+
  coord_equal(expand = FALSE)+
  theme_minimal()+
  theme(legend.position = "none")

d + l

Check cowplot

Cowplot has a big update pending, and biscale needs to be tested against the update to make sure the objects still work with legend creation

Add padding or margin to cells in bi_legend

Please describe.
I would like to add padding/margin to the cells in bi_legend

Describe the solution you'd like
Here is an example from /r/dataisbeautiful which was done in Python. Notice the white padding/margin between cells in the legend.

https://www.reddit.com/r/dataisbeautiful/comments/ipnqi1/oc_united_states_income_inequality/

Provide a reprex
Here is a reverse engineered version of their graph done in R with the "biscale" package and calling bi_legend with:

https://i.imgur.com/UZss85h.png

g_legend <-
bi_legend(pal = "DkViolet",
dim = 3,
xlab = "Higher Inquality ",
ylab = "Higher Income ",
size = 12)

Ability to have higher dimensions

Hi biscale team,

First of all, I am very impressed with this function. Thank you for developing. I have really enjoyed plotting using biscale.

I was wondering if it would be possible to have 4x4 map legends instead of 3x3 as the maximum, or in general to have higher values for the dim argument. This would allow to plot interesting relationships, for example, using deciles. I am not entirely sure if this would be easy to implement but I thought on writing you in case it was possible.

Thank you,

Danae

Iterating through biscale graphs

Hi,
Thanks for an awesome package. I have a large number of biscale plots to produce, so thought I would try to wrap up the process into a function. However, am struggling with the naming of bi_legend axes.

library(tidyverse)
#> Registered S3 methods overwritten by 'ggplot2':
#>   method         from 
#>   [.quosures     rlang
#>   c.quosures     rlang
#>   print.quosures rlang
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.1.3, PROJ 4.9.3
library(biscale)
library(cowplot)
#> 
#> Attaching package: 'cowplot'
#> The following object is masked from 'package:ggplot2':
#> 
#>     ggsave
library(rlang)
#> 
#> Attaching package: 'rlang'
#> The following objects are masked from 'package:purrr':
#> 
#>     %@%, as_function, flatten, flatten_chr, flatten_dbl,
#>     flatten_int, flatten_lgl, flatten_raw, invoke, list_along,
#>     modify, prepend, splice

mybiscale_func <- function(df, x, y, dim, title){
  quo_x <- rlang::enquo(x)
  quo_y <- rlang::enquo(y)
  name_x <- enexpr(x)
  name_y <- enexpr(y)
  
  data <- biscale::bi_class(df, x = !!quo_x, y = !!quo_y, style = "quantile", dim = dim)
  
  legend <- biscale::bi_legend(pal="GrPink",
                    dim=dim,
                    xlab = as_name(!!name_x),
                    ylab = as_name(!!name_y),
                    size=8)
  
  map <- ggplot() +
    geom_sf(data = data, aes(fill = bi_class), 
          color = "white", 
          size = 0.1, 
          show.legend = FALSE) +
    bi_scale_fill(pal = "GrPink", dim = dim) +
    labs(title = title) +
    theme_minimal()
  
  finalPlot <- cowplot::ggdraw() +
  draw_plot(map, 0, 0, 1, 1) +
  draw_plot(legend, 0.2, .7, 0.2, 0.2)

finalPlot
  
}

mybiscale_func(df = stl_race_income, x=pctWhite, y=medInc, dim=3, title= "Race and Income in St. Louis, MO")
#> Error in !name_x: invalid argument type

Created on 2019-06-09 by the reprex package (v0.3.0)

Very grateful if you can provide any insight into what I am doing wrong.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.