Skip to contents

Introduction

benviplot provides color palettes and ggplot2 helper functions for exploratory data analysis. The color schemes are based on Benvi, a discontinued brand of the Brazilian proptech QuintoAndar1. The package ships with a custom ggplot2 theme, a family of discrete and continuous color scales, and convenience wrappers for common chart types.

Installation

# Install remotes if needed
install.packages("remotes")

remotes::install_github("viniciusoike/benviplot")

Font Setup (Optional)

benviplot bundles the Poppins font family and registers it automatically when the package loads (requires the systemfonts package). When Poppins is registered, theme_benvi() uses it by default. Without systemfonts, the theme falls back to the system sans-serif font.

For the best rendering quality with custom fonts, install the ragg package. When ragg is set as the graphics device (the default in RStudio and Positron), Poppins renders correctly in all output formats.

You can check your full font and device status at any time with:

Quick Start

The core of the package is theme_benvi() combined with the scale_*_benvi_*() functions. Together, they give any ggplot2 chart a consistent look with minimal effort. In the example below, scale_fill_benvi_d() maps the discrete cylinder variable to the "qual_8" qualitative palette, while theme_benvi() handles the rest of the styling.

ggplot(mtcars, aes(x = wt, y = mpg, fill = as.factor(cyl))) +
  geom_point(shape = 21, size = 3, color = "#000000") +
  scale_fill_benvi_d(name = "Cylinders", pal_name = "qual_8") +
  labs(
    title = "Fuel Efficiency vs. Weight",
    x = "Weight (1000 lbs)",
    y = "Miles per Gallon"
  ) +
  theme_benvi()

Color Palettes

The package organizes its palettes into several families: theme, sequential, qualitative, diverging, city-specific, and brand. Each family serves a different purpose, and choosing the right one depends on the nature of your variable.

Browsing palettes

show_palettes() gives a visual overview of all available palettes. Calling it without arguments displays every palette in the package; pass a type name to narrow the output.

You can filter by type: "theme", "sequential", "qualitative", "city", or "brand".

show_palettes("sequential")

Accessing palette colors

benvi_palette() returns a named vector of hex codes. Printing it renders a color swatch in the console, which is useful for quick visual comparison.

# Preview a palette
benvi_palette("qual_2")
#> [1] "#C5C9BA" "#816242" "#F2C037" "#009850" "#466795" "#9A75B4" "#EA4E58"
#> [8] "#C64729"
#> attr(,"class")
#> [1] "palette"
#> attr(,"pal_name")
#> [1] "qual_2"

To use the colors outside of ggplot2 (e.g. in base R or as input to another package), coerce to a plain character vector.

# Get hex codes as a plain character vector
as.character(benvi_palette("benvi_blue"))
#>  [1] "#021841" "#192C50" "#2F405F" "#46546E" "#5D687D" "#737C8C" "#8A919C"
#>  [8] "#A0A5AB" "#B7B9BA" "#CECDC9"

Discrete palettes contain between 4 and 9 fixed colors. When you need more granularity, set type = "continuous" to interpolate an arbitrary number of colors along the palette gradient.

benvi_palette("seq_greens", n = 20, type = "continuous")
#>  [1] "#245825" "#255929" "#275A2D" "#295C31" "#2A5D36" "#2C5F3B" "#2E613F"
#>  [8] "#2F6243" "#316448" "#33664C" "#356751" "#376955" "#396B5A" "#3A6C5E"
#> [15] "#3C6E62" "#3E7067" "#3F716C" "#417370" "#437575" "#46777A"
#> attr(,"class")
#> [1] "palette"
#> attr(,"pal_name")
#> [1] "seq_greens"

Using ggplot2 Scales

The scale functions follow the standard ggplot2 naming convention: scale_{aesthetic}_benvi_{d|c}(), where d is for discrete variables and c is for continuous ones. Both color and fill variants are available, and colour spellings work as expected.

Discrete scales

Discrete scales map categorical variables to a qualitative or city-specific palette. The pal_name argument (or the first positional argument) selects which palette to use.

iqaiw_total <- subset(iqaiw, rooms == "Total")

ggplot(iqaiw_total, aes(x = date, y = index, color = name_muni)) +
  geom_line(linewidth = 0.7) +
  geom_hline(yintercept = 100) +
  scale_color_benvi_d("rio_qual", name = NULL) +
  labs(
    title = "IQAIW Rental Index by City",
    x = NULL,
    y = "Index (base = 100)"
  ) +
  theme_benvi()

Continuous scales

Continuous scales interpolate across a sequential or brand palette. They are well suited for heatmaps, choropleths, and any visualization where a numeric variable needs a smooth color gradient. Use direction = -1 to reverse the palette.

iqaiw_total <- subset(iqaiw_total, !is.na(acum12m))

ggplot(iqaiw_total, aes(x = date, y = name_muni, fill = acum12m * 100)) +
  geom_tile(height = 0.6, color = "#ffffff") +
  scale_fill_benvi_c(
    pal_name = "benvi_blue",
    name = "YoY Change (%)",
    direction = -1
  ) +
  scale_x_continuous(
    breaks = seq(2023, 2025, 1),
    expand = expansion(0)
  ) +
  labs(x = NULL, y = NULL) +
  theme_benvi() +
  theme(
    legend.title = element_text(hjust = 0.5, vjust = 0.75),
    axis.text = element_text(size = 12),
    panel.grid = element_blank()
  )

Plot Helper Functions

benviplot includes convenience wrappers for common chart types. These functions accept a data frame and column names via tidy evaluation, apply theme_benvi() automatically, and return a standard ggplot2 object. They are designed for quick exploratory work; for publication-quality figures, building the plot from scratch gives you full control.

Line chart

plot_line() draws a single-series line chart. Pass color to map a grouping variable and get multiple lines with an automatic legend.

plot_line(economics, x = date, y = uempmed)

Bar chart

plot_column() creates a vertical bar chart. Setting text = TRUE adds value labels above each bar; for bars with enough height, text_inside = TRUE places labels inside the bars instead (requires the ggfittext package).

sales <- data.frame(
  cities = c(
    "São Paulo",
    "Rio de Janeiro",
    "Belo Horizonte",
    "Porto Alegre",
    "Curitiba"
  ),
  revenue = c(125, 200, 150, 175, 80)
)

plot_column(sales, x = cities, y = revenue, text = TRUE)

Scatter plot

plot_scatter() maps x and y to a scatter plot. A color argument maps a grouping variable to the point fill using a Benvi palette. Set smooth = TRUE to overlay a regression line.

plot_scatter(
  mtcars,
  x = wt,
  y = mpg,
  color = as.factor(cyl),
  palette = "qual_5",
  scale_name = "Cylinders"
)

Adding layers

Because all helpers return ggplot2 objects, you can extend them with additional layers, scales, or theme adjustments as you normally would.

plot_line(economics, x = date, y = unemploy / 1000) +
  geom_smooth(se = FALSE, color = benvi_palette("oranges")[3]) +
  labs(
    title = "US Unemployment with Smoothed Trend",
    subtitle = "Unemployment figures in millions",
    x = NULL,
    y = "Unemployed (millions)",
    caption = "Data: economics dataset"
  )

Base R

The palettes are not tied to ggplot2. Since benvi_palette() returns plain hex codes, you can use them anywhere that accepts color strings, including base R graphics, lattice, or any other plotting system.

colors <- as.character(benvi_palette("purples"))

plot(
  mtcars$wt,
  mtcars$mpg,
  col = colors[mtcars$cyl / 2 - 1],
  pch = 19,
  cex = 1.5,
  xlab = "Weight (1000 lbs)",
  ylab = "Miles per Gallon",
  main = "Using Benvi colors in base R"
)