Suppose we have a data that has so many series that it is hard to identify them by their colours as the differences are so subtle.
To filter the data to the reasonable number of lines, we can use dplyr’s
But, it seems not so handy. For example, what if we want to change the threshold in predicate (
max(value) > 20) and highlight other series as well? It’s a bit tiresome to type all the code above again every time we replace
20 with some other value.
Besides, considering one of the main purposes of visualization is to get the overview of a data, it may not be good to simply filter out the unmatched data because the plot loose its context then.
Here comes gghighlight package,
dplyr::filter() equivalent for ggplot2.
(If you are interested in the more details behind the idea of highlighting, please read this post: Anatomy of gghighlight.)
The main function of gghighlight package is
gghighlight(). For example, by using this function, we can highlight the lines whose max values are larger than 20 like below:
You can specify as many predicates as you like. For example, the following code highlights the data that satisfies both
max(value) > 15 and
mean(flag) > 0.55.
gghighlight() results in a ggplot object, it is fully customizable just as we usually do with ggplot2 like custom themes.
The plot also can be facetted:
There are also some options to control the way of highlighting. See “Options” section below.
gghighlight() can highlight almost every geoms. Here are some examples.
gghighlight() can highlight bars.
Are you wondering if this is really highlighted? Yes, it is. But, the unhighlighted bars are all overwritten by the highlighted bars. This seems not so useful, until you see the fecetted version:
As is explained in Anatomy of gghighlight, lines and points typically have different semantics (group-wise or not). But, in most cases, you don’t need to be careful about the difference with
gghighlight() because it automatically picks the right way of calculation.
gghighlight() takes the following strategy:
groupexists, use it.
To construct a predicate expression like bellow, we need to determine a threshold (in this example,
20). But it is difficult to choose a nice one before we draw plots.
gghighlight() allows predicates that return non-logical (e.g. numeric and character) results. The values are used for sorting data and the top
max_highlight of rows/groups are highlighted:
gghighlight() adds the direct labels for some geoms. Currently, the following geoms are supported:
point: add labels at each highlighted points.
line: add labels at the right ends of each highlighted lines.
bar: (do not add labels)
If you don’t want them to be labelled automatically, you can specify
use_direct_labels = FALSE
Labels are drawn by
geom_label_repel(). If you want to customize the labels, you can pass parameters to it via
You can also add labels by yourself. It is easy to add labels on only highlighted data because
gghighlight() replaces the plot’s data to the filtered one.
p <- ggplot(d2, aes(idx, value)) + geom_point(size = 4) + gghighlight(value > 0, use_direct_label = FALSE) # the filtered data p$data #> idx value type flag #> 1 78 2.91137069 n FALSE #> 4 7 0.21285231 s TRUE #> 6 344 5.82021950 f TRUE #> 12 299 0.09233384 o FALSE #> 18 343 17.78239148 g FALSE #> 19 141 1.25227154 k FALSE p + geom_label(aes(label = type), hjust = 1, vjust = 1, fill = "purple", colour = "white", alpha= 0.5)
If you want to change the style of unhighlighted layers, use
If you want to keep the original scales, set
p <- ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() p + gghighlight(cyl == 6) #> Warning: Tried to calculate with group_by(), but the calculation failed. #> Falling back to ungrouped filter operation... p + gghighlight(cyl == 6, keep_scales = TRUE) + ggtitle("keep_scale = TRUE") #> Warning: Tried to calculate with group_by(), but the calculation failed. #> Falling back to ungrouped filter operation...
If you want to highlight each facet individually, set
TRUE. Note that
gghighlight() affects the plot before
gghighlight(). If you add
facet_*() after adding
gghighlight(), this option doesn’t work.
d <- data.frame( idx = c(1, 2, 3, 4, 1, 2, 3, 4), value = c(10, 11, 12, 13, 4, 8, 16, 32), cat1 = rep(c("a", "b"), each = 4), cat2 = rep(rep(c("1-2", "3-4"), each = 2), 2), stringsAsFactors = FALSE ) p <- ggplot(d, aes(idx, value, colour = cat1)) + geom_line() + facet_wrap(vars(cat2)) p + gghighlight(max(value) > 10) #> label_key: cat1 p + gghighlight(max(value) > 10, use_facet_vars = TRUE) + ggtitle("use_facet_vars = TRUE") #> label_key: cat1