@@ -322,7 +322,7 @@ GuideLegend <- ggproto(
322322
323323 get_layer_key = function (params , layers , data ) {
324324
325- decor <- lapply( layers , function (layer ) {
325+ decor <- Map( layer = layers , df = data , f = function (layer , df ) {
326326
327327 matched_aes <- matched_aes(layer , params )
328328
@@ -343,9 +343,10 @@ GuideLegend <- ggproto(
343343 " Failed to apply {.fn after_scale} modifications to legend" ,
344344 parent = cnd
345345 )
346- layer $ geom $ use_defaults(params $ key [matched ], layer_params , list ())
346+ layer $ geom $ use_defaults(params $ key [matched_aes ], layer_params , list ())
347347 }
348348 )
349+ data $ .draw <- keep_key_data(params $ key , df , matched_aes , layer $ show.legend )
349350 } else {
350351 reps <- rep(1 , nrow(params $ key ))
351352 data <- layer $ geom $ use_defaults(NULL , layer $ aes_params )[reps , ]
@@ -510,7 +511,12 @@ GuideLegend <- ggproto(
510511 draw <- function (i ) {
511512 bg <- elements $ key
512513 keys <- lapply(decor , function (g ) {
513- g $ draw_key(vec_slice(g $ data , i ), g $ params , key_size )
514+ data <- vec_slice(g $ data , i )
515+ if (data $ .draw %|| % TRUE ) {
516+ g $ draw_key(data , g $ params , key_size )
517+ } else {
518+ zeroGrob()
519+ }
514520 })
515521 c(list (bg ), keys )
516522 }
@@ -804,3 +810,38 @@ measure_legend_keys <- function(decor, n, dim, byrow = FALSE,
804810 heights = pmax(default_height , apply(size , 1 , max ))
805811 )
806812}
813+
814+ # For legend keys, check if the guide key's `.value` also occurs in the layer
815+ # data when `show.legend = NA` and data is discrete. Note that `show.legend`
816+ # besides TRUE (always show), FALSE (never show) and NA (show in relevant legend),
817+ # can also take *named* logical vector to set this behaviour per aesthetic.
818+ keep_key_data <- function (key , data , aes , show ) {
819+ # First, can we exclude based on anything else than actually checking the
820+ # data that we should include or drop the key?
821+ if (! is.discrete(key $ .value )) {
822+ return (TRUE )
823+ }
824+ if (is_named(show )) {
825+ aes <- intersect(aes , names(show ))
826+ show <- show [aes ]
827+ } else {
828+ show <- show [rep(1L , length(aes ))]
829+ }
830+ if (isTRUE(any(show )) || length(show ) == 0 ) {
831+ return (TRUE )
832+ }
833+ if (isTRUE(all(! show ))) {
834+ return (FALSE )
835+ }
836+ # Second, we go find if the value is actually present in the data.
837+ aes <- aes [is.na(show )]
838+ match <- which(names(data ) %in% aes )
839+ if (length(match ) == 0 ) {
840+ return (TRUE )
841+ }
842+ keep <- rep(FALSE , nrow(key ))
843+ for (column in match ) {
844+ keep <- keep | vec_in(key $ .value , data [[column ]])
845+ }
846+ keep
847+ }
0 commit comments