Skip to content

Strip placement (bottom, outside) and empty slots #2622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
zz77zz opened this issue May 17, 2018 · 6 comments · Fixed by #2628
Closed

Strip placement (bottom, outside) and empty slots #2622

zz77zz opened this issue May 17, 2018 · 6 comments · Fixed by #2628
Labels
bug an unexpected problem or unintended behavior

Comments

@zz77zz
Copy link

zz77zz commented May 17, 2018


[issue raised at https://stackoverflow.com/questions/50385053/ggplot2-unexpected-vapply-error]

In some situations, empty slots in a row together with the "bottom" parameter lead to the following error:

"Error in vapply(row_axes, is.zero, logical(length(row_axes))) : values must be length 3, but FUN(X[[1]]) result is length 1"

library(ggplot2)

zzz <- data.frame(gp = c("a","b","c","d","e","f","g"), 
                  c1 = c(1,1,1,1,1,1,1), 
                  c2 = c(1,1,1,1,1,1,1))

ggplot(zzz, aes(x = c1, y = c2)) +
  facet_wrap(~ gp, scales = "free", nrow = 3, strip.position = "bottom") +
  geom_point() +
  theme(
    aspect.ratio = 1,
    strip.background = element_blank(),
    strip.placement = "outside"
  )
@batpigandme
Copy link
Contributor

reprex with working example without strip.position = "bottom" and one with strip.position = "left" (works with others as well):

library(ggplot2)

zzz <- data.frame(gp = c("a","b","c","d","e","f","g"), 
                  c1 = c(1,1,1,1,1,1,1), 
                  c2 = c(1,1,1,1,1,1,1))

# without strip position argument
ggplot(zzz, aes(x = c1, y = c2)) +
  facet_wrap(~ gp, scales = "free", nrow = 3) +
  geom_point() +
  theme(
    aspect.ratio = 1,
    strip.background = element_blank(),
    strip.placement = "outside"
  )

ggplot(zzz, aes(x = c1, y = c2)) +
  facet_wrap(~ gp, scales = "free", nrow = 3, strip.position = "bottom") +
  geom_point() +
  theme(
    aspect.ratio = 1,
    strip.background = element_blank(),
    strip.placement = "outside"
  )
#> Error in vapply(row_axes, is.zero, logical(length(row_axes))): values must be length 2,
#>  but FUN(X[[1]]) result is length 1
# works for other positions
ggplot(zzz, aes(x = c1, y = c2)) +
  facet_wrap(~ gp, scales = "free", nrow = 3, strip.position = "left") +
  geom_point() +
  theme(
    aspect.ratio = 1,
    strip.background = element_blank(),
    strip.placement = "outside"
  )

Created on 2018-05-17 by the reprex package (v0.2.0).

@batpigandme
Copy link
Contributor

batpigandme commented May 17, 2018

n.b. also works when total number of facets is divisible by the row number

library(ggplot2)

zzz <- data.frame(gp = c("a","b","c","d","e","f"), 
                  c1 = c(1,1,1,1,1,1), 
                  c2 = c(1,1,1,1,1,1))

ggplot(zzz, aes(x = c1, y = c2)) +
  facet_wrap(~ gp, scales = "free", nrow = 3, strip.position = "bottom") +
  geom_point() +
  theme(
    aspect.ratio = 1,
    strip.background = element_blank(),
    strip.placement = "outside"
  )

Created on 2018-05-17 by the reprex package (v0.2.0).

Also, though, with a missing facet that's 2 of 2…

zzz <- data.frame(gp = c("a","b","c","d","e"), 
                  c1 = c(1,1,1,1,1), 
                  c2 = c(1,1,1,1,1))

ggplot(zzz, aes(x = c1, y = c2)) +
  facet_wrap(~ gp, scales = "free", nrow = 3, strip.position = "bottom") +
  geom_point() +
  theme(
    aspect.ratio = 1,
    strip.background = element_blank(),
    strip.placement = "outside"
  )
#> Warning: Suppressing axis rendering when strip.position = 'bottom' and
#> strip.placement == 'outside'

@clauswilke
Copy link
Member

I can't say I understand the code in question, but one way or another this line looks suspicious:

any(!vapply(row_axes, is.zero, logical(length(row_axes))))) {

There's a similar line a little further down, though I wasn't able to create a crash at that position:

any(!vapply(col_axes, is.zero, logical(length(col_axes))))) {

The problem with these lines is the last argument to vapply(), e.g. logical(length(row_axes)). When row_axes holds more than one grob, logical(length(row_axes)) will be a vector of bools, but is.zero() will always return only a single bool, hence the error message. I suspect the correct code would be vapply(row_axes, ggplot2:::is.zero, logical(length(1))).

Reprex to show what I mean:

library(grid)
library(ggplot2)

row_axes <- list(zeroGrob(), textGrob("test"))
vapply(row_axes, ggplot2:::is.zero, logical(length(1)))
#> [1]  TRUE FALSE
vapply(row_axes, ggplot2:::is.zero, logical(length(row_axes)))
#> Error in vapply(row_axes, ggplot2:::is.zero, logical(length(row_axes))): values must be length 2,
#>  but FUN(X[[1]]) result is length 1

Created on 2018-05-17 by the reprex package (v0.2.0).

@clauswilke clauswilke added the bug an unexpected problem or unintended behavior label May 18, 2018
@thomasp85
Copy link
Member

I’ll look into it today

@thomasp85
Copy link
Member

thomasp85 commented May 18, 2018

It seems to be a simple matter of me messing up the the vapply call...

The reason @clauswilke can't provoke an error on the second instance is that it is not possible to have more than a single unfinished row

@lock
Copy link

lock bot commented Nov 14, 2018

This old issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with reprex) and link to this issue. https://reprex.tidyverse.org/

@lock lock bot locked and limited conversation to collaborators Nov 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug an unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants