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

improve faceting #46

Merged
merged 8 commits into from
Jul 13, 2020
Merged

improve faceting #46

merged 8 commits into from
Jul 13, 2020

Conversation

greimel
Copy link
Collaborator

@greimel greimel commented Jul 7, 2020

Fixes #42

The case where layouting is done with multiple x and y columns (as in the tutorial) is unchanged.

iris = dataset("datasets", "iris")
cols = style([:SepalLength, :SepalWidth], [:PetalLength :PetalWidth])
grp = style(layout_x = dims(1), layout_y = dims(2), color = :Species)
geom = spec(Scatter) + linear
aog2 = data(iris) * cols * grp * geom
aog2 |> draw

layout2

The case where faceting is done with a categorical variable is improved: Note the shared x and y labels and the labels on top and to the right.

mpg = dataset("ggplot2", "mpg")
mpg[!,:grpx] .= rand.(Ref(["a", "b", "c"]))
mpg[!,:grpy] .= rand.(Ref(["aa", "bb"]))

cols = style(:Displ, :Hwy)
grp = style(color = :Cyl => categorical, layout_x = :grpx, layout_y = :grpy)
scat = spec(Scatter)
pipeline = cols * scat
aog = data(mpg) * grp * pipeline
aog |> draw

layout1

Since I don't know to internal well enough, this could probably be implemented more elegantly. Let me know what I can do to improve the code.

Edit: Things to improve

  • Should we also link all the x-axis when faceting by a categorical variable?
  • Placement of legend is not nice

@greimel
Copy link
Collaborator Author

greimel commented Jul 8, 2020

I now use protrusions for spanned x and y labels so that the legend is correctly centered.

layout3

I would like to acknowledge help by @jkrumbiegel on Slack. He suggested to use protrusions for the grey labels a while ago and showed me how to use them + clever padding for the spanned labels.

@@ -92,6 +105,72 @@ function layoutplot!(scene, layout, ts::Algebraic)
@warn "Automated legend was not possible due to $e"
end
end

ax1 = axs[end,1]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Due to my use of fake data, I didn't realize that I got the spanned x and y labels wrong. This is now fixed.

Now I take them from one ax1.

It would probably be preferable to take them directly from split(trace.value)?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you experiment with the scenario where not all pairwise group combinations exist? That is, it's not a perfect grid but some plots are missing. If we want to support that, we'd need to make sure that axs[end, 1] does the right thing there.

@@ -40,6 +45,13 @@ function set_defaults!(attrs::Attributes)
get!(attrs, :markersize, Observable(8px))
end

pkeys(aog) = aog.dict.vals[1].context.pkeys
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe better to specify the type of aog, as this seems very specific. aog.dict.vals[1] should probably be first(values(aog)). Also, it'd probably be better to introduce pkeys(c::AbstractContext), because the data context has a pkeys field, but other contexts don't, so pkeys(::AbstractContext) = nothing should probably be the general fallback.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Somehow, this feels a bit fragile, because layoutplot! accepts any Algebraic. Could you do it somewhere during the pipeline, where it is more clear what objects one is dealing with? For example, somewhere around here: https://github.com/JuliaPlots/AlgebraOfGraphics.jl/blob/master/src/makielayout_integration.jl#L49

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually never mind, this can probably stay as is, I'm working on a simplification of the system, so this will have to change in the near future anyways.

(MakieLayout.protrusionsobservable(ax) for ax in axs[:, 1])...
)

pady = Node(10.0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above on padx.

(MakieLayout.protrusionsobservable(ax) for ax in axs[end, :])...
)

padx = Node(10.0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need this here? Somehow, I imagined that the defaults of MakieLayout should also be our defaults, or is there something MakieLayout is not doing automatically?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jkrumbiegel, would you mind helping us out? I basically copied your code from slack :-D

Are similar the paddings between regular axis labels and tick labels similarly hard coded in MakieLayout? Or could extract the padding from the given plot and and use it here?

Copy link
Member

@jkrumbiegel jkrumbiegel Jul 13, 2020

Choose a reason for hiding this comment

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

well you could of course just use one of the padding attributes of one of the LAxis instances, it's the same thing but if you have a spanning label, this parameter doesn't belong to one of the spanned axes but really to the group... I just wanted to show in the example how you can correctly position the label, it's your decision how you want to expose that parameter :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

thanks!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

By default, the padding should be identical for all panels, right? (The axis labels are always nicely aligned). That is, I can just take the attribute from any panel.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if I understand what you want to know. Normally, an axis has an x and y label and there is a padding value for those against the tick labels. What you're doing here is not using those labels at all, but simply sticking another label across the outer axes and padding it so it looks good. The extra padding value that you need can come from anywhere, but why would you reuse it from one of the axes? Then the user would have to go to that axis and change the padding value there. I think it makes most sense to make these values keyword arguments of the AoG function that creates the grid. I don't know if the AoG data structure in the end has a space for storing this attribute, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, I think I misunderstood which distance the padding measures.

@@ -92,6 +105,72 @@ function layoutplot!(scene, layout, ts::Algebraic)
@warn "Automated legend was not possible due to $e"
end
end

ax1 = axs[end,1]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you experiment with the scenario where not all pairwise group combinations exist? That is, it's not a perfect grid but some plots are missing. If we want to support that, we'd need to make sure that axs[end, 1] does the right thing there.

@piever piever merged commit 66d29a3 into MakieOrg:master Jul 13, 2020
@greimel greimel deleted the faceting branch July 13, 2020 15:14
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.

Facet vs layout
4 participants