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

Is there an easy way to pass aesthetics? #818

Open
idmitrievsky opened this issue Mar 31, 2016 · 12 comments
Open

Is there an easy way to pass aesthetics? #818

idmitrievsky opened this issue Mar 31, 2016 · 12 comments

Comments

@idmitrievsky
Copy link

Hi! I have code like this:

using Gadfly
using RDatasets

iris = dataset("datasets", "iris")

plot(iris, x = :SepalLength, y = :PetalLength, Geom.point, Geom.smooth)

I'd like to color points with blue and line with red. I know that this code does what I want:

plot(iris, 
layer(x = :SepalLength, y = :PetalLength, Geom.point, Theme(default_color = colorant"blue")), 
layer(x = :SepalLength, y = :PetalLength, Geom.smooth, Theme(default_color = colorant"red"))
)

But here is a list of things I tried intuitively before coming to this.
1.

plot(iris, x = :SepalLength, y = :PetalLength, Geom.point, color = colorant"blue", 
Geom.smooth, color = colorant"red")
plot(iris, x = :SepalLength, y = :PetalLength, Geom.point(aes(color = colorant"blue")), 
Geom.smooth(aes(color = colorant"red")))
plot(iris, x = :SepalLength, y = :PetalLength,
layer(Geom.point, color = colorant"blue"), 
layer(Geom.smooth, color = colorant"red")
)

I think that the second one feels like the most reasonable approach. It strongly resembles ggplot2 way of doing things. Does Gadfly have DataType for Aesthetics?

@tlnagy
Copy link
Member

tlnagy commented Apr 2, 2016

I agree that the Theme(default_color=colorant"blue") isn't very intuitive, personally I think the 3rd option makes the most sense and feels the most "Gadfly"esque.

@tlnagy
Copy link
Member

tlnagy commented Sep 1, 2016

I'm interested in implementing this since this makes Gadfly more intuitive and easier to pick up.

@shashi
Copy link
Collaborator

shashi commented Sep 1, 2016

I agree that layer(x = :SepalLength, y = :PetalLength, Geom.point, Theme(default_color = colorant"blue")) is verbose for each different thing you want to plot. The awkwardness seems to come from the fact that you have to specify x and y again.

It looks like there is a pattern we can build around option 3. However, I don't know how to nicely get rid of Theme. But we can reduce its unfriendliness by 1) creating an alias called Style which seems to be a more well-known name for this sort of thing, while "Theme" usually means a ready-made set of styles 2) choosing a different color for each layer automatically. That said, here's the pattern I see coming from option 3:

plot(iris, x = :SepalWidth, y = :PetalLength, layer(Geom.point),  layer(Geom.smooth))

would pick distinct colors for the layers automatically. One can imagine a short-hand to this as

plot(iris, x = :SepalWidth, y = :PetalLength, Geom.point,  Geom.smooth)

Although the automatically changed colors will be a breaking change.

plot(iris, x = :SepalWidth, y = :PetalLength, layer(Geom.point, Style(color=colorant"black")),  layer(Geom.smooth))

would set black as the color for layer 1, overriding the automatically chosen one.

plot(iris, x = :SepalWidth, y = :PetalLength, layer(Style(color=colorant"black")),  layer(y=:SomeOtherField), Geom.line)

The second layer plots different data, both layers use Geom.line. In general, options set outside the layer(...) definitions are taken as common for each layer, so x remains the same in both, but you can change it if you want to in one or both of them.

One of the things lacking right now is a way to create a legend manually. It seems the (only?) way to create it is now using a DataFrames input and setting which column the color comes from. While this is useful, I've wanted to set my own legend many times. How about introducing Guide.legend which sets the legend label for the layer?

plot(iris, x = :SepalWidth, y = :PetalLength, layer(Style(color=colorant"black"), Guide.legend("Petal length")),  layer(y=:SomeOtherField, Guide.legend("Second line")), Geom.line)

@shashi
Copy link
Collaborator

shashi commented Sep 1, 2016

I'd love for

y=rand(10,2)
plot(x = 1:10,  y=y, Geom.line)

to become a short hand for

plot(x = 1:10,  layer(y=y[:,1], Geom.legend("col 1")), layer(y=y[:,2], Geom.legend("col 2")), Geom.line)

and just draw the lines.

@shashi
Copy link
Collaborator

shashi commented Sep 1, 2016

One way to get rid of the Theme/Style thing, which I don't know if is safe is by assuming all kwargs to layer other than x and y are arguments to Theme. It seems awkward to reserve all keyword arguments from being used in the future though, that's what I meant when I said Theme is not easy to get rid of.

@Mattriks
Copy link
Member

Mattriks commented Sep 1, 2016

Here is the current fast way of doing the initial example, just for the record.

iris = dataset("datasets", "iris")
theme(x) = Theme(default_color=parse(Colors.Colorant,x))
colv = ["deepskyblue","red"]

p = plot(iris, x=:SepalLength, y=:PetalLength, 
    layer( Geom.point, theme(colv[1]) ), 
    layer( Geom.smooth, theme(colv[2]), order=2 ),
    Guide.manual_color_key("Key", ["Points", "Smooth"], colv)
)

iris1

@Mattriks
Copy link
Member

Mattriks commented Sep 2, 2016

And here is the same in R (I don't know if this can be further condensed):

colv = c("deepskyblue","red")

p = ggplot(iris, aes(x=Sepal.Length, y=Petal.Length))+
  geom_point(aes(color="Points"))+
  geom_smooth(aes(color="Smooth"))+
  scale_color_manual(name="Key",values=colv)

@tlnagy
Copy link
Member

tlnagy commented Sep 2, 2016

Do either of you know why manual_color_key doesn't change the plotting colors too? Only the legend colors? That doesn't make sense to me. That's the primary difference between the ggplot2 and Gadfly code you have there @Mattriks

@robsmith11
Copy link

Is there a reason this hasn't moved forward?

A simple way to explicitly set the color like is possible in ggplot2 seems like a pretty important feature..

@Mattriks
Copy link
Member

Mattriks commented Apr 5, 2019

Currently, there are several ways in Gadfly to specify color:

using Colors
plot(iris, x=:SepalLength, y=:PetalLength,  Geom.point, color=[RGB(0,0,1)])
plot(iris, x=:SepalLength, y=:PetalLength,  Geom.point, color=[colorant"red"])
plot(iris, x=:SepalLength, y=:PetalLength,  Geom.point, Theme(default_color="red"))
plot(iris, x=:SepalLength, y=:PetalLength,  Geom.point, color=:Species)

In your post, are you referring to the manual_color_key issue mentioned above, or some change to the color syntax? If the latter, what changes would you like to see?

@robsmith11
Copy link

That's still a bit verbose.. color='red' compared to color=[colorant"red"] but better than I had thought. However, it doesn't seem to work with Geom.line:

julia> plot(DataFrame(x=1:100, y=rand(100)), x=:x, y=:y, Geom.line, color=[colorant"red"])
Error showing value of type Plot:
ERROR: The following aesthetics are required by Geom.line to be of equal length: x, y, color

@Mattriks Mattriks mentioned this issue Jun 21, 2020
6 tasks
@Mattriks
Copy link
Member

Mattriks commented Jul 8, 2020

Following #1463, the initial example can be done like this now:

plot(iris, x=:SepalLength, y=:PetalLength,
    layer(Geom.smooth, color=["Smooth"]),
    layer(Geom.point, color=["Points"]),
    Scale.color_discrete_manual("red","deepskyblue"))

iris_points_smooth

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

No branches or pull requests

5 participants