Skip to content

Conversation

@mthulin
Copy link

@mthulin mthulin commented Mar 20, 2025

Currently, when tinyplot is used with pipes, data = _ must be passed to the function:

airquality |> subset(Month == 5) |> tinyplot(Temp ~ Wind, data = _)

This PR adds the method tinyplot.data.frame, which lets users run tinyplot after a pipe without having to use the data argument:

airquality |> subset(Month == 5) |> tinyplot(Temp ~ Wind)

This should make it easier for pipe users to adopt tinyplot into their workflows.

The function will throw an error if no formula is supplied. Running

airquality |> subset(Month == 5) |> tinyplot(Wind, Temp)

yields

Error in tinyplot.data.frame(subset(airquality, Month == 5), Wind, Temp) : 
  If the first argument to tinyplot is a data frame, then the second must be a formula.

I added an example in the documentation, wrapped in \dontrun{} to avoid creating a dependency on R>=4.1.

@zeileis
Copy link
Collaborator

zeileis commented Mar 20, 2025

Thanks for proposing this PR, it's a nice trick.

However, I'm not sure whether we want to give away the possibility to have a dedicated tinyplot.data.frame method serving a different purpose, e.g., creating a pairs plot of all possible combinations of variables.

Personally, rather than using the data = _ argument, I personally just name the first argument:

airquality |> subset(Month == 5) |> tinyplot(x = Temp ~ Wind)

Personally, I find this easy enough to use. But maybe Grant @grantmcdermott and Vincent @vincentarelbundock feel differently.

@vincentarelbundock
Copy link
Collaborator

When I first saw this I got super excited and was about to post with great enthusiasm.

But Achim's point about optionality is a very good one. I can also imagine other plots where maybe x is a data frame with multiple series we want to plot in parallel. Maybe there are also representations of maps as data frames? Not sure if those are real use-cases, but until we explore in that direction, it seems smart to hold off on closing the door altogether.

@grantmcdermott
Copy link
Owner

I won't have time to look at this until tonight. But perhaps we could implement a compromise solution that defaults to pair plots if a formula is not provided, otherwise adopts the trick proposed by @mthulin?

We would probably also need to account for the fact that some data.frames (e.g., PlantGowth iirc) have formula attributes for methods dispatch.

@mthulin
Copy link
Author

mthulin commented Mar 20, 2025

The naming-the-first-argument approach is nice! However, I guess that most users usually skip the x when working without pipes, so that they don't write:

tinyplot(x = Temp ~ Wind, data = subset(airquality, Month == 5))

Personally, I'd prefer not to have to use special syntax to make the function work well with pipes. Similarly, I suspect that users coming from the tidyverse (who of course make up non-negligible proportion of R users) would consider it "a trick you have to do", whereas my solution is more in line with how users would expect things to work.

That being said, I think that @grantmcdermott's idea of defaulting to a pairs plot unless a formula is provided is a great idea. I'd be happy to help with this if you choose to go down that route.

@zeileis
Copy link
Collaborator

zeileis commented Mar 20, 2025

Regarding the suggestion of handling the case with and without formula differently: I'm concerned that the arguments like type would have to be handled differently between these two cases. For a pairs plot, for example, it would make sense to choose different types for the diagonal and off-diagonal elements. Hence I would recommend to first work out a proper pairs plot and then see whether the formula trick would be compatible with that without creating too much confusion. (I'm not too optimistic...but probably that's just me).

@grantmcdermott
Copy link
Owner

@mthulin I think we'll need a bit more time to think through the potential implications per @zeileis's last comment. Sorry for the slow action on this. I'm juggling some impending deadlines at work, so my tinyplot dev time is currently limited.

@mthulin
Copy link
Author

mthulin commented May 26, 2025

Have you given this any more thought? Others may not agree of course, but for me, the one thing that's keeping me from migrating to tinyplot in my introductory R courses is that the syntax isn't as pipe-friendly as it could be; we use pipes a lot in my courses, and having to add x = Temp ~ Wind or data = _ just makes things confusing for beginners.

@vincentarelbundock
Copy link
Collaborator

TBC, I'm not the one who's going to make final call on this, but at this stage I think we should hold off on dedicating an important method for this little bit of syntactic convenience.

We all have different teaching philosophies, but I would argue that a pipe-heavy introduction to R should absolutely include a module on argument passing. Otherwise students will try to do things like this:

# breaks
mtcars |> lm(mpg ~ hp)

# works
mtcars |> lm(mpg ~ hp, data = _)

So that could just be a nice opportunity to introduce this (very easy) programming concept.

@mthulin
Copy link
Author

mthulin commented May 26, 2025

We all have different teaching philosophies, but I would argue that a pipe-heavy introduction to R should absolutely include a module on argument passing.

I completely agree on this. However, I don't think that the fact that legacy R functions weren't designed to work seamlessly with pipes is an argument for designing new functions that require special syntax to work with pipes.

@grantmcdermott
Copy link
Owner

Have you given this any more thought?

Sorry @mthulin, not enough to make a call. I think Vincent and Achim have raised enough good points above that we should be cautious about implementing without further testing. FWIW I hope to add a few basic methods to tinyplot in the next release (e.g., tinyplot.matrix) and I think we'll be in a better position to evaluate unintended consequences then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants