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

Specify xlim and ylim for each facet separately #187

Closed
kohske opened this Issue May 23, 2011 · 22 comments

Comments

Projects
None yet
@kohske
Collaborator

kohske commented May 23, 2011

Maybe it is fine if xlim and ylim can be specified for each facet separately, at least, for facet_wrap.
Now, panel contains the information about ranges of each facet, so e.g.,

# lims like this:
  vs am xmin xmax ymin ymax
1  0  0    8    8 10.4 19.2
2  0  1    4    8 15.0 26.0
3  1  0    4    6 17.8 24.4
4  1  1    4    4 21.4 33.9

and specify by, e.g.,

+ facet_wrap(~vs+am, limits = lims)
@hadley

This comment has been minimized.

Member

hadley commented May 23, 2011

Yes, I like this idea, and I like that basic syntax. But how do limit and free scales interact? And what happens if you specify facet_wrap(~ vs, limits = lims).

Another related idea that I've been thinking about is giving layers the ability not to affect scale limits - this is useful when you are plotting spatial data and want to add a map on top. You don't want the map to affect the limits, because it may be much bigger than you data, and using coord to zoom in is a hassle. If that idea was implemented, modifying scales on a facet-by-facet basis would amount to using train_position = F for all layers, apart from a geom_blank which specified the dummy data to expand the scales as needed - which expand_limits already does.

Implementing scale limits in that way would also mean the behaviour of free scales etc could remain as is.

@kohske

This comment has been minimized.

Collaborator

kohske commented May 23, 2011

Hi

Actually I meant the limits for coord, but yes, the limits for scale
also should be like that.

In the case of coord, probably we have nothing to worry about.
Just passing lims data drame to coord_* is sufficient, and there
is no problem about the interaction of free scale and limits.
I will try to implement it.

As for the limits for scales, as you say, things may be somewhat complicated.

But how do limit and free scales interact?

I think manual limits should have top-priority.

And what happens if you specify facet_wrap(~ vs, limits = lims).

Just an error, since the limits are indeterminable.
Or, with warning, use the first apparence of vs.

Another related idea that I've been thinking about is giving layers the ability not to affect scale limits - this is useful when you are plotting spatial data and want to add a map on top.  You don't want the map to affect the limits, because it may be much bigger than you data, and using coord to zoom in is a hassle.  If that idea was implemented, modifying scales on a facet-by-facet basis would amount to using train_position = F for all layers, apart from a geom_blank which specified the dummy data to expand the scales as needed - which expand_limits already does.

Totally the idea sounds good, although I'm not sure if explicit
null-geom is necessary.

Kohske Takahashi takahashi.kohske@gmail.com

Research Center for Advanced Science and Technology,
The University of  Tokyo, Japan.
http://www.fennel.rcast.u-tokyo.ac.jp/profilee_ktakahashi.html

On Mon, May 23, 2011 at 10:06 PM, hadley
reply@reply.github.com
wrote:

Yes, I like this idea, and I like that basic syntax.  But how do limit and free scales interact?  And what happens if you specify facet_wrap(~ vs, limits = lims).

Another related idea that I've been thinking about is giving layers the ability not to affect scale limits - this is useful when you are plotting spatial data and want to add a map on top.  You don't want the map to affect the limits, because it may be much bigger than you data, and using coord to zoom in is a hassle.  If that idea was implemented, modifying scales on a facet-by-facet basis would amount to using train_position = F for all layers, apart from a geom_blank which specified the dummy data to expand the scales as needed - which expand_limits already does.

Reply to this email directly or view it on GitHub:
#187 (comment)

@kohske

This comment has been minimized.

Collaborator

kohske commented May 23, 2011

Here is a testbed of manual limits for coord with facet_wrap.

kohske@bd71581

@hadley

This comment has been minimized.

Member

hadley commented May 24, 2011

Hmmmm, that code just looks too complicated to me. It's a lot of extra complexity for not a lot of extra gain. I think giving layers the ability to control whether or not they affect position scaling is simpler to implement, more elegant (in terms of playing nicely with existing code for free limits) and allows a number of other interesting techniques that were previously not possibly.

@kohske

This comment has been minimized.

Collaborator

kohske commented May 24, 2011

Hmmmm, that code just looks too complicated to me.  It's a lot of extra complexity for not a lot of extra gain.  I think giving layers the ability to control whether or not they affect position scaling is simpler to implement, more elegant (in terms of playing nicely with existing code for free limits) and allows a number of other interesting techniques that were previously not possibly.

Yes, exactly, yes. It may be too complicated and hard to understand.
Probably the layers will do that, but thus far I could not entirely
figure out the power of the layers.
So, I will look into the code and consider a implementation.

thanks,

kohske

@baptiste

This comment has been minimized.

Contributor

baptiste commented May 24, 2011

I would like to add another, related request. Different panels with different limits may also require fine-tuning of the breaks on a per-panel basis (I do need this, often). Currently the only way I could achieve this was to mask grid.pretty() and play some ugly tricks to have it return different breaks for different data ranges.
It sure would be nice to be able to specify manual breaks for each facet, in those few special occasions. I don't expect there will ever be a properly grammatical syntax for this, though. Failing this, perhaps it should simply be part of opts()? I could imagine a new opts() for a ggplot being similar to the way lattice handles these cosmetic details,

  • specify the panel ordering
  • specify the panel widths, and interpanel spacings (allowing visual groupings, e.g. 2 by 2)
  • specify a list of panel limits, with optional recycling
  • specify the panel x and y breaks
    (- perhaps even more options, such as per-panel background colour, ...)
@hadley

This comment has been minimized.

Member

hadley commented May 25, 2011

That's actually possible in the devel version - you can take the output of ggplot_build and modify the per-panel labels there. I'm not sure if I want to commit to a formal API yet.

ggplot2 will never handle these details like lattice does, because I really dislike how that works - you should be describing things in terms of the underlying data, not by some arbitrary panel number.

@baptiste

This comment has been minimized.

Contributor

baptiste commented May 25, 2011

It should be possible to specify all these details in terms of the facetting variables as opposed to the panel number; admittedly the syntax becomes more cumbersome. There may be a way to define a new data structure between data.frame and list to handle these options. Below is an illustration of what I have in mind, storing the values in a long format matrix.

my.panel.details <- function(){

two facetting variables

row.var <- rep(letters[1:2], 2)
col.var <- rep(LETTERS[1:2], each=2)

corresponding specifications

cbind(row.var=row.var, col.var=col.var,
limits = c(list(c(0, 10)), # per panel limits
list(c(0, Inf)), # Inf means 'use the defaults from the data'
list(c(-Inf, Inf)),
list(c(-Inf, Inf))),
breaks = c(list(seq(0,10)),
list(seq(-10,10,by=5)),
list(seq(-10,10,by=2)),
list(seq(-10,10,by=1))),
vspacing = c(5, 5), # vertical spacing between the panels, repeated by technical necessity
hspacing = c(0, 0), # horizontal spacing between the panels
width = c(1, 2), # using null units?
height = c(1, 1), # using null units?
background.color = c("grey95"))

}

my.panel.details()

opts(panel.details = my.panel.details())

@jonsedar

This comment has been minimized.

jonsedar commented Mar 1, 2013

It's two years on, but I'd really like to be able to specify ylims for each facet as described above. Any chance of getting this included?

@joey711

This comment has been minimized.

Contributor

joey711 commented Apr 25, 2013

I second that last comment by @jonsedar. Any news on this?

@gitspade

This comment has been minimized.

gitspade commented May 7, 2013

+1

2 similar comments
@ghost

This comment has been minimized.

ghost commented May 21, 2013

+1

@yasminlucero

This comment has been minimized.

yasminlucero commented Jun 15, 2013

+1

@svernede

This comment has been minimized.

svernede commented Jul 31, 2013

A possible way to implement this feature is to add a attribute to layers on how they affect scale limits.
This attribute could have three values

  • Normal: The layer have the same behavior as in the current implementation of ggplot2
  • Ignore: The layer is ignored when computing the scale limits, as already proposed by @hadley above
  • Force: The layer force the scale limits based on his own data and the data on the other layers are not considered to compute the scales limits

Then we can easily set the scale limits by creating a layer, say geom_rect with the desired size. We can then control the visibility of the layer either by the aesthetic alpha, or a new attribute on layer controlling visibility. if we want to affect only on direction, say x, we can set the dimension of the geom to Inf and -Inf in this direction.

This is not a direct implementation of the feature requested, but it will do the job with a minimum of hacks. It will also enable the possibility of ignoring some layer. This is useful for maps as mentioned by @hadley but also, for example, to plot the prediction of a model together with data while only keeping the focus on the data.

@hadley

This comment has been minimized.

Member

hadley commented Feb 24, 2014

This sounds like a great feature, but unfortunately we don't currently have the development bandwidth to support it. If you'd like to submit a pull request that implements this feature, please follow the instructions in the development vignette.

@pengchy

This comment has been minimized.

pengchy commented May 8, 2015

I think the simple way is to modify the original data, remove the unwanted values

@bshor

This comment has been minimized.

bshor commented May 21, 2015

+1

@nhamilton1980

This comment has been minimized.

nhamilton1980 commented Feb 22, 2017

"I think the simple way is to modify the original data, remove the unwanted values". This doesn't work in many cases, such as the example Hadley mentioned earlier WRT maps. Sometimes you need the data to spool beyond the plot region (but be concealed/masked by the act of applying the limits), since by removing values, this may close and/or truncate paths and create ugly (and inaccurate) rendering of the data.

@nhamilton1980

This comment has been minimized.

nhamilton1980 commented Feb 23, 2017

Frankly I think there should be a 'limiter' function (or rather the 'scales' argument to facet_wrap and/or facet_grid is able to accept a function), which is similar to the 'labeller' function. This limiter function could return 'fixed', 'free_x', 'free_y', 'free', or alternately return a list containing xlim, and ylim values for each facet given the input x and y indexes of the facet.

@mmrinconh

This comment has been minimized.

mmrinconh commented Apr 16, 2018

This can be easily done using patchwork library, you just have to add the plots customized as you required: https://github.com/thomasp85/patchwork

@map2085

This comment has been minimized.

map2085 commented Jun 12, 2018

+1

@andrewjpfeiffer

This comment has been minimized.

andrewjpfeiffer commented Nov 8, 2018

+1. Any chance of this being reopened?

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