Skip to content
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

Implement labeller option for facet_wrap() #1127

Merged
merged 5 commits into from Jul 28, 2015
Merged

Conversation

lionel-
Copy link
Member

@lionel- lionel- commented Jun 14, 2015

so I finally understood what was the concern in #656. I found a somewhat hacky solution (documented in the source code) that should nevertheless work in most cases.

@hadley
Copy link
Member

hadley commented Jun 18, 2015

We are going to make other API breaking changes in the next release, so it would be ok to consider a less-hacky solution, if you're interested.

@lionel-
Copy link
Member Author

lionel- commented Jun 18, 2015

I may have time in July.

@hadley
Copy link
Member

hadley commented Jun 18, 2015

That should work - my crazy summer conference schedule starts on next Wednesday, and I won't be back doing much development until July 20.

@lionel-
Copy link
Member Author

lionel- commented Jun 30, 2015

@hadley Would it be ok to have multiple factors (e.g., ~ cyl + am) labelled on multiple rows as in grid facetting? Currently facet_wrap() label them with a single row with comma separation and I think it'd be better to have the same behaviour as with grid facets. Or should we avoid making visible changes?

@lionel-
Copy link
Member Author

lionel- commented Jul 1, 2015

I'll add a parameter to the labellers to specify whether it should be one row or multiple rows. I think multiple rows is more readable but kind of ugly so it'll be nice to have the single row option for publications.

Then we can either change the default of wrap to match that of grid. Or we can have the old behaviour by setting the default to this lambda: labeller = function(labels) label_value(labels, newline = FALSE).

@lionel- lionel- force-pushed the wrap-exp branch 5 times, most recently from af81805 to d82966d Compare July 1, 2015 18:32
@lionel-
Copy link
Member Author

lionel- commented Jul 1, 2015

@hadley ready for review.

Currently facet_wrap() with multiple factors will display the labels on multiple lines by default, which introduces a slight change from previous behaviour. I can change it back if you prefer.

Additionally, I think we should have a new default labeller for both wrap and grid. It would call label_value() in case of a single factor, and label_both() in case of multiple factors. This would make ggplot facets much more readable.

@lionel- lionel- force-pushed the wrap-exp branch 2 times, most recently from bc4dcd5 to e515b0c Compare July 2, 2015 10:15
@lionel-
Copy link
Member Author

lionel- commented Jul 2, 2015

ok, I added label_default() which behaves as discussed above. I made it the default. Now the following:

ggplot(mtcars, aes(wt, mpg)) +
  geom_point() +
  facet_grid(gear ~ am + cyl)

yields

rplot

which is more readable because you can tell which values belong to which variable. Let me know if you'd prefer no changes in the visual defaults.

@lionel-
Copy link
Member Author

lionel- commented Jul 3, 2015

If you look closely there is currently a visible thin line separating the rows of the labels with the default theme. And here is what happens when strip.background colour property is set:

rplot2

I think it's not so nice. I could implement the row separation as a newline \n instead of a gtable row, which would get rid of this. But I don't know if this would break some plots/software relying on this for grid facetting?

label_both(labels, multi_line)
}
}
class(label_default) <- c("function", "labeller")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be just class(label_default) <- "labeller") (technically function isn't a class, but a type)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hadley when I remove the "function" class, roxygen stops documenting the usage of these functions, which leads to bad documentation and a CMD CHECK warning. I'll leave the function class for now and file an issue for roxygen.

@hadley
Copy link
Member

hadley commented Jul 27, 2015

I'd prefer to make no changes to the default display. I also wonder if it would make sense to document all the labeller functions in one Rd file, so there's a place to document how the labeller function works in more detail.

@lionel-
Copy link
Member Author

lionel- commented Jul 27, 2015

I'd prefer to make no changes to the default display.

Alright, I'll rename label_default() to label_flexible() then.

Does this also applies to wrap facetting? I.e., currently wrap facets display multiple factors on a single line while grid facets display them on multiple lines. In this PR, they are both displayed consistently as multiple lines but I could pass a lambda function(labels) label_value(labels, multi_line = FALSE) as default argument to facet_wrap() to produce the same default as before.

@hadley
Copy link
Member

hadley commented Jul 27, 2015

I think making that consistent is fine - it's fairly unusual to use multiple vars with facet_wrap() anyway.

@lionel- lionel- force-pushed the wrap-exp branch 2 times, most recently from 4e9a9d6 to e453999 Compare July 28, 2015 11:13
@lionel-
Copy link
Member Author

lionel- commented Jul 28, 2015

@hadley The labellers are now documented together.

Also the last commit proposes another API update for label_bquote(). Before the commit, this labeller mapped variables of multiple factors to x, y and z in the order they occur in the formula. I think this is a bit obscure, so the new commit makes label_bquote() keep the original names. So, instead of

p + facet_grid(. ~ vs + am, labeller = label_bquote(.(x) ^ .(y)))

we have

p + facet_grid(. ~ vs + am, labeller = label_bquote(.(vs) ^ .(am)))

For backward compatibility, it still bounds x to the first factor with a deprecation warning, except when one of the factor facetted over is also called x.

I'll cancel the commit if you prefer the old behaviour.

@hadley
Copy link
Member

hadley commented Jul 28, 2015

This will break existing custom labellers, right?

@lionel-
Copy link
Member Author

lionel- commented Jul 28, 2015

yes, before the labellers took a value and variable arguments and returned a character vector, now they take and return a rectangular list of character vectors.

@hadley
Copy link
Member

hadley commented Jul 28, 2015

Can you make that more clear in the NEWS?

#' @section Writing New Labeller Functions:
#'
#' A labeller function accepts a dataframe of labels (character
#' vectors) containing one column for each factor. Muultiple factors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Muultiple typo

result <- values
# If the facetting margin (i.e. `variable`) was not specified when
# calling labeller, default to use the actual values.
if (is.null(labeller)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switch seems overly complicated to me. Why not just require that you use a "labeller function", i.e. a function that has arguments labels and multiline? (obviously you're just copying the existing structure, but that now seems overly complex)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a legacy from before. We could remove the ability to use non-labeller functions that take and return a chr vector if you prefer?

Before the labeller function was checking the arguments to determine which functions are labellers, now I use the S3 class because I thought it was more robust. I can make it check the arguments as before if you think that'd be easier to create custom labellers. But we can't rely on multi_line, only on labels.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I guess it's documented and you've already done it, so lets leave it.

@hadley
Copy link
Member

hadley commented Jul 28, 2015

Overall, this looks good. I like the unification across wrap and grid, and the code is not much more complicated than previously.

Any thoughts on unit testing?

@hadley
Copy link
Member

hadley commented Jul 28, 2015

Can you please merge/rebase and squash and then I'll merge?

@lionel-
Copy link
Member Author

lionel- commented Jul 28, 2015

Here you go

@hadley
Copy link
Member

hadley commented Jul 28, 2015

And squash please?

@lionel-
Copy link
Member Author

lionel- commented Jul 28, 2015

hmm I can squash into Winston's commit (which is the earliest one) but then he gets credited as the author of the whole patch. What's the proper way to do it?

@hadley
Copy link
Member

hadley commented Jul 28, 2015

Oh I see - don't worry about it then.

hadley added a commit that referenced this pull request Jul 28, 2015
Implement `labeller` option for facet_wrap()
@hadley hadley merged commit 91d3041 into tidyverse:master Jul 28, 2015
@lionel- lionel- mentioned this pull request Sep 2, 2015
lionel- added a commit to lionel-/ggplot2 that referenced this pull request Sep 2, 2015
lionel- added a commit to lionel-/ggplot2 that referenced this pull request Sep 2, 2015
lionel- added a commit to lionel-/ggplot2 that referenced this pull request Sep 2, 2015
@lock
Copy link

lock bot commented Jan 18, 2019

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 Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants