Reputation: 11
I'm trying to create a custom ggplot2 geom called geom_geoheat, but I'm running into an error when converting the geom to a grob. I am using ggprotos of GeomTile and GeomRect (where tile inherits most of rect's properties). The error message indicates an issue with grid::unit() in grid::rectGrob(), but I can't seem to debug the x and units parts. Here is my function and the error message:
library(ggplot2)
geom_geoheat <- function(
mapping = NULL, data = NULL,
border_col = "white", border_size = 2,
lbl_size = 3, dark_lbl = "black", light_lbl = "white",
radius = grid::unit(6, "pt"),
...,
na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) {
ggplot2::layer(
data = data,
mapping = mapping,
stat = "identity",
geom = GeomGeoHeat,
position = "identity",
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
border_col = border_col,
border_size = border_size,
lbl_size = lbl_size,
dark_lbl = dark_lbl,
light_lbl = light_lbl,
radius = radius,
na.rm = na.rm,
...
)
)
}
GeomGeoHeat <- ggproto("GeomGeoHeat", GeomTile,
required_aes = c("fill", "facet_col"),
default_aes = aes(
fill = "grey20", colour = NA, size = 0.1, linetype = 1,
facet_col = "country",
label = "code",
angle = 0, hjust = 0.5,
vjust = 0.5, alpha = NA, family = "", fontface = 1, lineheight = 1.2
),
extra_params = c("na.rm"),
setup_data = function(data, params) {
facet_data <- data.frame(data, stringsAsFactors=FALSE)
facet_col <- facet_col
merged_data <- mergeGridAndData(facet_data, grid_data, facet_col)
merged_data$y <- -merged_data$y
print(summary(merged_data))
merged_data
},
draw_panel = function(self, data, panel_params, coord,
border_col = "white", border_size = 2,
lbl_size = 3, dark_lbl = "black", light_lbl = "white",
radius = grid::unit(6, "pt")) {
print(head(data))
coord <- coord_equal()
grid::gList(
GeomTile$draw_panel(data, panel_params, coord)
) -> grobs
ggname("geom_geoheat", grid::grobTree(children = grobs))
},
draw_key = ggplot2::draw_key_polygon
)
# Merge user data with grid data
mergeGridAndData <- function(facet_data, grid_data, facet_col)
{
print(summary(facet_data))
if (max(nchar(facet_data[,"facet_col"])) <= 3) {
merge.grid <- "code"
} else {
merge.grid <- "name"
}
# Rename rows and columns to x and y for panel coordinates. Flip row coordinates to start at bottom left.
colnames(grid_data) <- c("name", "code", "y", "x")
merged_data <- merge(grid_data, facet_data,
by.x = merge.grid, by.y = "facet_col", all = FALSE, sort=TRUE)
}
and the error:
Error in `geom_geoheat()`:
! Problem while converting geom to grob.
ℹ Error occurred in the 1st layer.
Caused by error in `unit()`:
! 'x' and 'units' must have length > 0
—> more specifically, the error occurs in grid::rectGrob(...)
└─grid::unit(x, default.units)
└─base::stop("'x' and 'units' must have length > 0")
The desired output would be a CARTOGRAM HEATMAP. I believe the issue is in the draw_panel part of GeomRect (as draw_panel gets inherited into the Tile). However, I've been unsuccessful in debugging the x and units part, primarily because I don’t know how to call units from what seems a deeply entrenched grid function within rectGrob.
Here is minimal code needed to try it out yourselves:
# Example dataset
data <- data.frame(
country = c("USA", "Canada", "Germany", "Japan"),
usage = c(50, 30, 45, 60)
)
# Dummy grid_data
grid_data <- data.frame(
name = c("United States", "Canada", "Germany", "Japan"),
code = c("US", "CA", "DE", "JP"),
row = c(1, 2, 3, 4),
col = c(1, 2, 3, 4)
)
facet_data <- data
facet_col <- "country"
# Example usage
ggplot(data = data,
mapping = aes(fill = usage, facet_col = country)) +
geom_geoheat()
I am a relative novice when it comes to asking questions here, so if I left out anything you feel is critical, please let me know and I'd be happy to provide it :) .
Any insights on what might be causing this error and how to resolve it would be greatly appreciated!
Upvotes: 1
Views: 120