@@ -322,7 +322,7 @@ GuideLegend <- ggproto(
322
322
323
323
get_layer_key = function (params , layers , data ) {
324
324
325
- decor <- lapply( layers , function (layer ) {
325
+ decor <- Map( layer = layers , df = data , f = function (layer , df ) {
326
326
327
327
matched_aes <- matched_aes(layer , params )
328
328
@@ -343,9 +343,10 @@ GuideLegend <- ggproto(
343
343
" Failed to apply {.fn after_scale} modifications to legend" ,
344
344
parent = cnd
345
345
)
346
- layer $ geom $ use_defaults(params $ key [matched ], layer_params , list ())
346
+ layer $ geom $ use_defaults(params $ key [matched_aes ], layer_params , list ())
347
347
}
348
348
)
349
+ data $ .draw <- keep_key_data(params $ key , df , matched_aes , layer $ show.legend )
349
350
} else {
350
351
reps <- rep(1 , nrow(params $ key ))
351
352
data <- layer $ geom $ use_defaults(NULL , layer $ aes_params )[reps , ]
@@ -510,7 +511,12 @@ GuideLegend <- ggproto(
510
511
draw <- function (i ) {
511
512
bg <- elements $ key
512
513
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
+ }
514
520
})
515
521
c(list (bg ), keys )
516
522
}
@@ -804,3 +810,38 @@ measure_legend_keys <- function(decor, n, dim, byrow = FALSE,
804
810
heights = pmax(default_height , apply(size , 1 , max ))
805
811
)
806
812
}
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