Changing Symbol/Marker Outline Width in Julia Using PyPlot - matplotlib

I'm trying to change the outline of the symbol (marker) inside a scatter plot in Julia using the PyPlot backend. I've tried edgecolor, edgewidth, edgelinewidth, markercolor, markerwidth, markerlinewidth and a variety of other key/values from various sources, but Julia/PyPlot recognizes none of these. How do I change the outline of the symbol/marker in a scatter plot executed in Julia using the PyPlot backend?

In Julia using the PyPlot backend, the correct key to manipulate the symbol/marker outline is markerstroke.... For example, markerstrokewidth=1 sets the outline of the marker to 1px, while markerstrokecolor="red" sets the outline color of the marker to red. I hope this helps.

For anyone reading this in 2022, PyPlot in Julia has completely changed. To change the edge size, the keyword is linewidths. In general, the repl is the best way to get up to date info. Just type ? (to get the help prompt), then PyPlot.scatter.

Related

save pyplot figure "as figure" (not as image)

How can I save a figure using PyPlot in Julia, so that the figure can be reloaded as a figure later in Julia? (not as an image)
You can use serialize to store any Julia object. This beautifully works for plots as well.
Let us start by generating a plot:
using Plots
pyplot()
p = plot(rand(10));
using Serialization
Serialization.serialize("myfile.jld", p);
Note that you need a semicolon after plot command so it does not appear on the screen.
Let us now read the plot (to have a full test I ended the previous Julia session and started a new one):
using Plots
pyplot();
using Serialization
p2 = Serialization.deserialize("myfile.jld");
In order to display it now it is enough to type in REPL:
julia> p2
You might want also want to use plain PyPlot (I strongly recommend Plots for flexibility). In that case your best bet is to follow rules described in object-oriented API of Matplotlib:
using PyPlot
ioff()
fig = subplot()
fig.plot(rand(10))
fig.set_title("Hello world")
using Serialization
serialize("pp.jld", fig)
In order to plot de-serialize back the object:
using PyPlot
ioff()
using Serialization
fig = deserialize("pp.jld")
show()
Finally, note that the serialization is good only for short term storage. If anything changes (e.g. you update Julia packages) you might not be able to de-serialize the plot.
Hence another good alternative for processable plots are saving them to LaTeX or SVG format - both is possible in Julia.

How to remove marker edges in seaborn.pairplot()?

Seaborn has a handy function pairplot to create a matrix of scatter plots. Unfortunately, some standard matplotlib commands don't work with it.
sns.pairplot(matrix[cols[:4]].head(100), plot_kws=dict(alpha=.5, mew=0))
The markers get some ugly white edges. I tried mew for markeredgewidth keyword to remove them as it would be used in matplotlib, but that is an unknown property for seaborn. How can I remove these edges?
A scatter does not have a mew keyword. It is edgecolor instead. Hence
sns.pairplot(data, plot_kws=dict(edgecolor="none"))
would remove the white edge around the scatterpoints.
ImportanceOfBeingErnest's answer is much more precise. Alternatively, you can also use a workaround: Set the color of choice for both the face and the edges of the markers as (example from the docs)
import seaborn as sns
sns.set(style="ticks", color_codes=True)
iris = sns.load_dataset("iris")
g = sns.pairplot(iris, plot_kws=dict(facecolor='b', edgecolor="b"))
EDIT based on comments below IOBE's answer: Just specifying the linewidth=0 also works the same way on markers as specifying edgecolor="none".
g = sns.pairplot(iris, plot_kws=dict(linewidth=0))

Accessing backend specific functionality with Julia Plots

Plots is simple and powerful but sometimes I would like to have a little bit more control over individual elements of the plot to fine-tune its appearance.
Is it possible to update the plot object of the backend directly?
E.g., for the default pyplot backend, I tried
using Plots
p = plot(sin)
p.o[:axes][1][:xaxis][:set_ticks_position]("top")
but the plot does not change. Calling p.o[:show]() afterwards does not help, either.
In other words: Is there a way to use the PyPlot interface for a plot that was initially created with Plots?
Edit:
The changes to the PyPlot object become visible (also in the gui) when saving the figure:
using Plots
using PyPlot
p = Plots.plot(sin, top_margin=1cm)
gui() # not needed when using the REPL
gca()[:xaxis][:set_ticks_position]("top")
PyPlot.savefig("test.png")
Here, I used p.o[:axes][1] == gca(). One has to set top_margin=1cm because the plot area is not adjusted automatically (for my actual fine-tuning, this doesn't matter).
This also works for subsequent updates as long as only the PyPlot interface is used. E.g., after the following commands, the plot will have a red right border in addition to labels at the top:
gca()[:spines]["right"][:set_color]("red")
PyPlot.savefig("test.png")
However, when a Plots command like plot!(xlabel="foo") is used, all previous changes made with PyPlot are overwritten (which is not suprising).
The remaining question is how to update the gui interactively without having to call PyPlot.savefig explicitly.
No - the plot is a Plots object, not a PyPlot object. In your specific example you can do plot(sin, xmirror = true).
I'm trying to do the same but didn't find a solution to update an existing plot. But here is a partial answer: you can query information from the PyPlot axes object
julia> Plots.plot(sin, 1:4)
julia> Plots.PyPlot.plt[:xlim]()
(1.0,4.0)
julia> Plots.plot(sin, 20:24)
julia> ax = Plots.PyPlot.plt[:xlim]()
(20.0,24.0)
and it gets updated.

Style of error bar in pandas plot

I'd like to plot line chart with error bar with the following style.
However, pandas plot draws error bars with only vertical line.
pd.DataFrame([1,2,3]).plot(yerr=[0.3,.3,.3])
How do I change style of error bar for pandas plot?
The versions are:
pandas '0.18.0'
matplotlib '1.5.1'
Update
One of the reason seems using the seaborn style. The following code give the nice style plot.
# plt.style.use('seaborn-paper')
pd.DataFrame([1,2,3]).plot(yerr=[0.3,.3,.3],capsize=4)
But, I have a reason to keep using seaborn style... Please help.
You can change the capsize inline when you call plot on your DataFrame, using the capsize kwarg (which gets passed on to plt.errorbar):
pd.DataFrame([1,2,3]).plot(yerr=[0.3,.3,.3],capsize=4)
Alternatively, you can change this setting using rcParams
You can find out what your default errorbar cap size is by printing plt.rcParams['errorbar.capsize']. If that is 0 (which is why I suspect you are currently getting no errorbar caps), you can set the default size of the errorbar caps to something nonzero, using:
plt.rcParams['errorbar.capsize']=4
Make sure to have that at the beginning of any plotting script.
Update:
It seems using the seaborn-paper style sets the cap thickness to 0. You can override this with the capthick kwarg:
plt.style.use('seaborn-paper')
pd.DataFrame([1,2,3]).plot(yerr=[0.3,.3,.3],capsize=4,capthick=1)

How to make a custom colormap using PyPlot (not matplotlib proper)

Working in IJulia. Desperately trying to make a custom colormap.
Tried the line:
matplotlib.colors.ListedColormap([(1,0,0),(0,1,0),(0,0,1)],"A")
which resulted in the following error
type PyObject has no field colors while loading In[16], in expression starting on line 1
which apparently means that I cannot use matplotlib directly, but only the functions which are in PyPlot.
I cannot involve matplotlib with an import (as this is invalid in IJulia).
I have noted that others have had help on similar problems, but that doesn't solve mine.
By using the PyCall package which PyPlot is using to wrap matplotlib you can obtain a colormap like this:
using PyCall
#pyimport matplotlib.colors as matcolors
cmap = matcolors.ListedColormap([(1,0,0),(0,1,0),(0,0,1)],"A")
In order to access fields in a PyObject you need to index the object with a symbol like:
cmap[:set_over]((0,0,0))
This is equivalent to: cmap.set_over((0,0,0)) in python. For other good examples of how to plot different kinds of plots using PyPlot, see these examples: https://gist.github.com/gizmaa/7214002
You don't need to use PyCall to call Python directly (although this is, of course, an option). You can also just use the PyPlot constructors for ColorMap to construct a colormap from (r,g,b) arrays or an array of colors as defined in the Julia Color package. See the PyPlot ColorMap documentation. For example:
using PyPlot, Color
ColorMap("A", [RGB(1,0,0),RGB(0,1,0),RGB(0,0,1)])