I am creating a world map with pie charts depicting sampling conducted.
I am having trouble getting the labeller
option within geom_scatterpie_legend()
- it appears to be producing non-sensical labels. The radius of my pies is set by Plot3.dat$lradius
. Plot3.dat$lradius
is equal to log(Plot3.dat$radius + 1)
. Despite my radius being on the log scale, I do not want the labels of my legend to be on the log scale, hence I am trying to use the labeller
option to back-transform my legend labels. However, the back-transformation of the labels does not seem to produce results in line with the coded labeller
function.
I have tried running this on a second machine and I get the same result.
ggplot() +
geom_polygon(data = countries,
aes(x = long, y = lat, group = group),
colour = "black", fill = NA) +
geom_scatterpie(data = Plot3.dat,
aes(x = long, y = lat, r = lradius),
sorted_by_radius = T,
cols = c("Prop.carn", "Prop.herb", "Prop.om")) +
geom_scatterpie_legend(c(log(2), log(31), log(151), log(751)),
x = -150.54, y = -50, n = 4,
labeller = function(x) round(exp(x) - 1, digits = 0))
The legend labels that should be produced for the four concentric circles are 1, 30, 150 and 750. As you can see the produced legend labels are 0, 6, 54 and 402.
This is my data:
Plot3.dat <- structure(list(Country = structure(1:28, levels = c("Australia",
"Belgium", "Cambodia", "Canada", "Ecuador", "England", "Ethiopia",
"France", "French Polynesia", "Germany", "India", "Indonesia",
"Iran", "Israel", "Japan", "Malaysia", "Mexico", "Mongolia",
"Morocco", "New Zealand", "Pakistan", "Philipines", "Spain",
"Switzerland", "Thailand", "United Kingdom", "United States of America",
"Wales"), class = "factor"), Carnivore = c(566L, 0L, 0L, 0L,
2L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 147L,
0L, 0L, 0L, 1L, 0L, 0L, 88L, 0L), Herbivore = c(242L, 0L, 0L,
34L, 0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L, 0L, 3L, 0L, 0L, 0L, 0L,
0L, 46L, 0L, 0L, 0L, 0L, 0L, 0L, 79L, 0L), Omnivore = c(130L,
1L, 24L, 2L, 0L, 161L, 0L, 5L, 1L, 17L, 409L, 5L, 6L, 0L, 4L,
11L, 4L, 2L, 1L, 728L, 278L, 4L, 6L, 0L, 27L, 10L, 282L, 1L),
lat = c(-25.2744, 50.5039, 12.5657, 56.1304, -1.8312, 52.3555,
9.145, 46.2276, -17.6797, 51.1657, 20.5937, -0.7893, 32.4279,
31.0461, 36.2048, 4.2105, 23.6345, 46.8625, 31.7917, -40.9006,
30.3753, 12.8797, 40.4637, 46.8182, 15.87, 55.3781, 37.0902,
52.1307), long = c(133.7751, 4.4699, 104.991, -106.3468,
-78.1834, -1.1743, 40.4897, 2.2137, -149.4068, 10.4515, 78.9629,
113.9213, 53.688, 34.8516, 138.2529, 101.9758, -102.5528,
103.8467, -7.0926, 174.886, 69.3451, 121.774, -3.7492, 8.2275,
100.9925, -3.436, -95.7129, -3.7837), Prop.carn = c(0.603411513859275,
0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.159609120521173,
0, 0, 0, 1, 0, 0, 0.195991091314031, 0), Prop.herb = c(0.257995735607676,
0, 0, 0.944444444444444, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0.0499457111834962, 0, 0, 0, 0, 0, 0, 0.175946547884187,
0), Prop.om = c(0.138592750533049, 1, 1, 0.0555555555555556,
0, 1, 0, 0.5, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0.790445168295331,
1, 1, 1, 0, 1, 1, 0.628062360801782, 1), radius = c(938,
1, 24, 36, 2, 161, 3, 10, 1, 17, 409, 5, 6, 3, 4, 11, 4,
2, 1, 921, 278, 4, 6, 1, 27, 10, 449, 1), lradius = c(6.84481547920826,
0.693147180559945, 3.2188758248682, 3.61091791264422, 1.09861228866811,
5.08759633523238, 1.38629436111989, 2.39789527279837, 0.693147180559945,
2.89037175789616, 6.01615715969835, 1.79175946922805, 1.94591014905531,
1.38629436111989, 1.6094379124341, 2.484906649788, 1.6094379124341,
1.09861228866811, 0.693147180559945, 6.82654522355659, 5.63121178182137,
1.6094379124341, 1.94591014905531, 0.693147180559945, 3.3322045101752,
2.39789527279837, 6.10924758276437, 0.693147180559945)), row.names = c(NA,
-28L), class = "data.frame")
IMHO you misunderstood the radius
argument of geom_scatterpie_legend
. It does not allow you to set your desired breaks
but is simply used to provide the data range to be displayed in the legend. The breaks are computed under the hood using scales::breaks_extended
.
This can be seen from the following lines of code which first give the breaks chosen by geom_scatterpie_legend
and the labels returned by your labeller
function.
radius <- c(log(2), log(31), log(151), log(751))
labeller <- function(x) round(exp(x) - 1, digits = 0)
breaks <- scales::breaks_extended(n = 4)(radius)
breaks
#> [1] 0 2 4 6
labeller(breaks)
#> [1] 0 6 54 402
Unfortunately the computation of the breaks is "hard-coded" but you the function could be extended quite easily to allow to set custom breaks and to achieve your desired result. To this end I added a breaks
argument to geom_scatterpie_legend
.
library(ggplot2)
library(scatterpie)
library(ggforce)
countries <- map_data("world")
# Copy and Paste from `scattterpie::geom_scatterpie_legend`
geom_scatterpie_legend2 <- function (radius = NULL, breaks = NULL, x, y, n = 5, labeller) {
if (n <= 1) {
stop("The n argument requires larger than 1.")
}
if (is.null(breaks)) {
radius <- (scales::breaks_extended(n = n))(radius)
} else {
radius <- breaks
}
label <- FALSE
if (!missing(labeller)) {
if (!inherits(labeller, "function")) {
stop("labeller should be a function for converting radius")
}
label <- TRUE
}
dd <- data.frame(r = radius, start = 0, end = 2 * pi, x = x,
y = y + radius - max(radius), maxr = max(radius))
if (label) {
dd$label <- labeller(dd$r)
}
else {
dd$label <- dd$r
}
list(geom_arc_bar(aes_(x0 = ~x, y0 = ~y, r0 = ~r, r = ~r,
start = ~start, end = ~end), data = dd, inherit.aes = FALSE),
geom_segment(aes_(x = ~x, xend = ~x + maxr * 1.5, y = ~y +
r, yend = ~y + r), data = dd, inherit.aes = FALSE),
geom_text(aes_(x = ~x + maxr * 1.6, y = ~y + r, label = ~label),
data = dd, hjust = "left", inherit.aes = FALSE))
}
ggplot() +
geom_polygon(
data = countries,
aes(x = long, y = lat, group = group),
colour = "black", fill = NA
) +
geom_scatterpie(
data = Plot3.dat,
aes(x = long, y = lat, r = lradius),
sorted_by_radius = T,
cols = c("Prop.carn", "Prop.herb", "Prop.om")
) +
coord_quickmap() +
geom_scatterpie_legend2(breaks = radius,
x = -150.54, y = -50, n = 5,
labeller = labeller
)