polygonPlot is an R package for visualizing multivariate ranges using polygon-based representations. Unlike traditional scatter or radar plots that display individual data points, polygonPlot allows users to display min–max intervals and mean values across 3 to 6 variables simultaneously.
You can install polygonPlot with the following code:
There are two types of input accepted by the polygonPlot function.
Just be sure that the input object is data.frame
type.
In both cases, the function returns a ggplot2 object, which includes the mean points of each axis connected by lines.
the input data.frame should be composed as follows:
axis_min,
axis_max and data in that row order.axis_min and axis_max
respectively.
extra parameter).Examples of an input data.frame
df <- read.csv(system.file(file.path("extdata", "example.csv"), package="polygonPlot"))
df
#> info data1 data2 data3 data4 data5 data6
#> 1 axis_min -300 -4 0 0 NA -0.5
#> 2 axis_max 500 14 1000 50 NA 0.5
#> 3 data 300 -2 10 20 5 0.1
#> 4 320 12 50 40 10 0.3
#> 5 340 NA 90 NA NA NA
#> 6 360 NA 130 NA NA NA
#> 7 380 NA 170 NA NA NA
#> 8 400 NA 210 NA NA NA
#> 9 420 NA NA NA NA NA
#> 10 440 NA NA NA NA NA
#> 11 460 NA NA NA NA NAa minimal version
If you have a classic data.frame, you can prepare it
with the function that we have created
classic_df <- data.frame(
data1=c(-300, 500, 300, 350),
data2=c(4, 14, -2, 12),
data3=c(0, 1000, 10, 50),
data4=c(0, 50, 20, 40)
)
formatted_df <- polygonPlot::prepare_dataframe(classic_df)
# Through this function it becomes the first type of input
formatted_df
#> info data1 data2 data3 data4
#> 1 axis_min NA NA NA NA
#> 2 axis_max NA NA NA NA
#> 3 data -300 4 0 0
#> 4 <NA> 500 14 1000 50
#> 5 <NA> 300 -2 10 20
#> 6 <NA> 350 12 50 40The polygonPlot function requires two mandatory
parameters:
df: the input data.frame
that should be composed as follows:
axis_min,
axis_max and data in that row order.axis_min and axis_max
respectively.
extra parameter).shape: the integer value
indicating the shape of the polygon. Available numbers:
3 for Triangle4 for Square5 for Pentagon6 for Hexagonextra: axis range extensionfillcolor fill color of the
polygonalpha alpha value of the fill
colorlinecolor line color of the polygon
borderlinetype line type of the polygon
borderlwd line width of the polygon
borderlabels_axis vector with the desired
labels of the axismean_line_color color of the mean line
inside the polygonannotation_tick_size size of tick
marks along the polygon axesannotation_label_size size of the
labels displayed along the polygon axestitle title of the plotfix_aspect_ratio boolean flag to fix
the aspect ratio of the plot as 1. It is strongly
recommended to leave it as default value TRUE.
theme
function the following code aspect.ratio = 1 in order to
keep the text and the relative ticks aligned on the axis.See the section About the aspect.ratio for a practical
example.
plot_triangle <- polygonPlot(df, shape = 3, fillcolor = "#e56b6f", linecolor = "#b56576",
labels_axis = c("earth", "moon", "sun"))
#> Perimeter: 24.76
#> Area: 52.96
plot_triangleplot_square <- polygonPlot(df, shape = 4, fillcolor = "#57cc99", linecolor = "#38a3a5", annotation_label_size = 8)
#> Perimeter: 32.76
#> Area: 76.36
plot_squareplot_pentagon <- polygonPlot(df, shape = 5, fillcolor = "#c89f9c", linecolor = "#b36a5e")
#> Perimeter: 42.76
#> Area: 109.70
plot_pentagonplot_hexagon <- polygonPlot(df, shape = 6, fillcolor = "#0077b6", linecolor = "#023e8a",
annotation_label_size = 8)
#> Perimeter: 46.76
#> Area: 180.02
plot_hexagonaspect.ratioSince polygonPlot returns a ggplot2 object,
the aspect ratio must be fixed to preserve the geometry of the
polygon.
When applying a custom theme, always include
theme(aspect.ratio = 1) to maintain alignment between axes
and labels.
plot_pentagon <- polygonPlot(df, shape = 5, fillcolor = "#c89f9c", linecolor = "#b36a5e")
#> Perimeter: 42.76
#> Area: 109.70
plot_pentagon + theme_bw() + theme(aspect.ratio = 1)To perform this task, the polygons must be pre-generated, each sharing the same minimum and maximum values of the axes. This ensures that all polygons are drawn on a consistent scale, allowing for direct and meaningful visual comparison between datasets.
axis_min <- c(-300, -4, 0, 0, NA, -0.5)
axis_max <- c(500, 14, 1000, 50, NA, 0.5)
df1 <- data.frame(
info = c("axis_min", "axis_max", "data", "data", "data"),
data1 = c(axis_min[1], axis_max[1], 300, 460, 120),
data2 = c(axis_min[2], axis_max[2], -2, 12, 4),
data3 = c(axis_min[3], axis_max[3], 10, 270, 80),
data4 = c(axis_min[4], axis_max[4], 20, 40, 15),
data5 = c(axis_min[5], axis_max[5], 5, 10, 3),
data6 = c(axis_min[6], axis_max[6], 0.1, 0.3, -0.2)
)
df2 <- data.frame(
info = c("axis_min", "axis_max", "data", "data", "data"),
data1 = c(axis_min[1], axis_max[1], 250, 380, 490),
data2 = c(axis_min[2], axis_max[2], -3, 8, 10),
data3 = c(axis_min[3], axis_max[3], 30, 200, 850),
data4 = c(axis_min[4], axis_max[4], 10, 30, 45),
data5 = c(axis_min[5], axis_max[5], 2, 6, 8),
data6 = c(axis_min[6], axis_max[6], -0.1, 0.25, 0.4)
)
df1
#> info data1 data2 data3 data4 data5 data6
#> 1 axis_min -300 -4 0 0 NA -0.5
#> 2 axis_max 500 14 1000 50 NA 0.5
#> 3 data 300 -2 10 20 5 0.1
#> 4 data 460 12 270 40 10 0.3
#> 5 data 120 4 80 15 3 -0.2
df2
#> info data1 data2 data3 data4 data5 data6
#> 1 axis_min -300 -4 0 0 NA -0.50
#> 2 axis_max 500 14 1000 50 NA 0.50
#> 3 data 250 -3 30 10 2 -0.10
#> 4 data 380 8 200 30 6 0.25
#> 5 data 490 10 850 45 8 0.40p1 <- polygonPlot(df1, shape=4, fillcolor = "darkgreen", alpha=0.5, linecolor = "darkgreen", mean_line_color = "blue")
#> Perimeter: 39.26
#> Area: 90.06
p1p2 <- polygonPlot(df2, shape=4, fillcolor = "orange", alpha=0.5, linecolor = "orange", mean_line_color = "red")
#> Perimeter: 50.84
#> Area: 234.58
p2Now that we have created the two plots, we can overlay them in a single chart. To do this, we need to define: - a list containing the plots - the corresponding labels
The parameters for the overlay_polygons function
are:
plot_list a list of polygon plots
(ggplot2 objects). All plots should use the same axis ranges. The order
of plots in this list determines which polygons appear in the foreground
and which are in the background.label_list is a vector of strings.
Must have the same length of plot_list objectlegend_title title of the legendinclude_mean_lines logical flag
indicating whether to include mean lines in the overlaid polygonsplt_list <- list(p1,p2)
plt_labels <- c("Example1", "Example2")
overlay_polygons(plt_list, plt_labels, include_mean_lines = T)Even with three plot we can see the differences. However, too many plots may provide a difficult visualization.
axis_min <- c(-300, -4, 0, 0, NA, -0.5)
axis_max <- c(500, 14, 1000, 50, NA, 0.5)
# Terzo dataframe
df3 <- data.frame(
info = c("axis_min", "axis_max", "data", "data", "data"),
data1 = c(axis_min[1], axis_max[1], 100, 250, 400),
data2 = c(axis_min[2], axis_max[2], -1, 6, 10),
data3 = c(axis_min[3], axis_max[3], 50, 300, 700),
data4 = c(axis_min[4], axis_max[4], 5, 25, 35),
data5 = c(axis_min[5], axis_max[5], 4, 8, 9),
data6 = c(axis_min[6], axis_max[6], 0.0, 0.2, 0.45)
)
p3 <- polygonPlot(df3, shape=4, fillcolor = "dodgerblue", alpha = 0.5, linecolor = "dodgerblue", mean_line_color = "yellow")
#> Perimeter: 44.72
#> Area: 158.28
p3
plt_list <- list(p1,p2,p3)
plt_labels <- c("Example1", "Example2", "Example3")
overlay_polygons(plt_list, plt_labels, include_mean_lines = T)Paper in preparation…
sessionInfo#> [1] "2025-10-24 17:22:59 CEST"
#> [1] "2025-10-24"
#> R version 4.5.1 (2025-06-13)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Tahoe 26.0.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: Europe/Rome
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] ggplot2_3.5.2 polygonPlot_1.1.0
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.6.5 cli_3.6.5 knitr_1.50 rlang_1.1.6
#> [5] xfun_0.52 generics_0.1.4 jsonlite_2.0.0 labeling_0.4.3
#> [9] glue_1.8.0 backports_1.5.0 htmltools_0.5.8.1 pracma_2.4.4
#> [13] sass_0.4.10 scales_1.4.0 rmarkdown_2.29 grid_4.5.1
#> [17] evaluate_1.0.4 jquerylib_0.1.4 tibble_3.3.0 fastmap_1.2.0
#> [21] yaml_2.3.10 lifecycle_1.0.4 compiler_4.5.1 dplyr_1.1.4
#> [25] RColorBrewer_1.1-3 pkgconfig_2.0.3 rstudioapi_0.17.1 farver_2.1.2
#> [29] digest_0.6.37 R6_2.6.1 dichromat_2.0-0.1 tidyselect_1.2.1
#> [33] pillar_1.10.2 magrittr_2.0.3 bslib_0.9.0 checkmate_2.3.3
#> [37] withr_3.0.2 gtable_0.3.6 tools_4.5.1 cachem_1.1.0