How to hide subplot labels in facet graph? - altair

This code:
import altair as alt
from vega_datasets import data
alt.Chart(data.iris()).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
facet=alt.Facet('species:N', header=alt.Header(labels=False, title=None), columns=3)
).properties(
width=250,
height=250
)
produces this chart:
I have added red lines beneath what I believe are called subplot "labels". How can I remove them? This question asked how to change them, and #jakevdp said that is impossible. This question asked how to remove them (same as me), and #jakevdp hasn't answered yet. They used a column parameter to eliminate the labels, but when I try that, it complains about the columns parameter I'm using. I want to both (a) eliminate the labels and (b) limit the number of subplots per row, with automatic row wrapping.

What you did should have worked (i.e. alt.Header(title=None, labels=False)); the fact that it doesn't is probably a bug (I think it's the same issue reported here: https://github.com/altair-viz/altair/issues/2252)
As a workaround for the issue, you can use labelExpr to hide them:
alt.Chart(data.iris()).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
facet=alt.Facet('species:N', header=alt.Header(labelExpr="''", title=None), columns=3)
).properties(
width=250,
height=250
)

Related

How to add two different labels to legend for an overlap plot using matplotlib in python?

Okay this might be easy even I search on web but could not get it. Basically i want to add the two different labels to my plot and this is my line of code for that
plt.plot(x[:,1],y,'ro',x[:,1],Line_fit,'b',linewidth=0.5,markersize=4,label="training data") # plot the data
plt.legend(loc="upper left")
but I am getting following result in which has same labels for both the plot.as following
Even I tried this
plt.plot(x[:,1],y,'ro',x[:,1],Line_fit,'b',linewidth=0.5,markersize=4,label="training data",label="Linear Regression") # plot the data
but give the error:
SyntaxError: keyword argument repeated
This link guide for the simple way but here plt.plot()had used twice in the accepted answer.My question is how can i do it the same thing in single line code as I did in my code ?
You need two lines. One for the plot, one for the legend.
plt.plot(x[:,1], y, 'ro', x[:,1], Line_fit, 'b', linewidth=0.5, markersize=4)
plt.legend(["training data", "Linear Regression"], loc="upper left")

Display seaborn plots at some point later in code

Let's say at some point in my code, I have following two graphs: i.e. graph_p_changes and graph_p_contrib
line_grapgh_p_changes = df_p_change[['year','interest accrued', 'trade debts', 'other financial assets']].melt('year', var_name='variables', value_name='p_changes')
graph_p_changes = sns.factorplot(x="year", y="p_changes", hue='variables', data=line_grapgh_p_changes, height=5, aspect=2)
graph_p_changes.set(xlabel='year', ylabel='percentage change in self value across the years')
line_grapgh_p_contrib = df_p_contrib[['year','interest accrued', 'trade debts', 'other financial assets']].melt('year', var_name='variables', value_name='p_changes')
graph_p_contrib = sns.factorplot(x="year", y="p_changes", hue='variables', data=line_grapgh_p_contrib, height=5, aspect=2)
graph_p_contrib.set(xlabel='year', ylabel='percentage chnage in contribution to total value')
Now at some point later in my code, I just want to display one of the above two graphs. But when I do plt.show(), it displays both of the above graphs in my jupyter notebook. How can I display only one graph at any point in my code.
You'll want to refer to the assigned variable for each plot and then add .fig after that to redisplay it in a Jupyter notebook cell.
Specifically, in your case you'd reference graph_p_changes.fig or graph_p_contrib.fig in a cell and execute that cell to see an individual plot again.
This is similar to how you can show Seaborn's ClusterGrids again, see here. Because the title of your question said 'seaborn plots', I'll add for sake of completeness, this doesn't hold for plots like Seaborn's line plot (lineplot) or bar plot (barplot) , that produce AxesSubplot objects. There you use .figure, for example ax.figure to recall most of the examples listed on Seaborn's lineplot documentation.
Example catplots with code
This is using example code from here and seaborn's catplot documentation (see below) to make two plots. If this code was in one cell and then that cell was run, you'd see two plots in the output below it.
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
titanic = sns.load_dataset("titanic")
exercise = sns.load_dataset("exercise")
g = sns.catplot("alive", col="deck",
col_wrap=3, data=titanic[titanic.deck.notnull()],
kind="count", height=2.5, aspect=.8)
another_plot = sns.catplot(x="time", y="pulse", hue="kind", data=exercise)
Later, each can be displayed again individually as output of other cells with g.fig or another_plot.fig, depending on which plot you want to show.
Additionaly, I'll suggest to improve your long-term code viability, you may want to move on to using catplot in your plotting calls as that is what factorplot is now called in seaborn. See here where it says "factorplot still exists and will pass its arguments through to catplot() with a warning. It may be removed eventually, but the transition will be as gradual as possible."
UPDATE:
OP commented that what was desired was code allowing interspersed stdout/stderr output with plots at precise points among that stream and not just at the end.
For some reason, Seaborn plots (even simple line plots) don't seem to get 'captured' correctly with io.capture_output(), and so I had to use the %%capture cell magic command in the producing cell and combine the output in a separate cell. However, Plotly plots I tried based on example code are captured by io.capture_output() and allow facile intermixing all in the same cell. This is all illustrated in an example notebook available here; it is best viewed in static form here at nbviewer because nbviewer renders the Plotly plots while GitHub doesn't. The top of that notebook includes a link where you can launch an active Jupyter session where it will run.
Update related to this UPDATE:
In an insightful answer to 'seaborn stop figure from being visualized', ffrosch suggests you "can temporarily disable/enable the inline creation with plt.ioff() and plt.ion()." This may offer yet another way to fine-tune when Seabor plots show among the output and/or offer another way to constrain ouput since %%capture cell magic worked yet io.capture_output() did not. (I have yet to try this.)

How to retrieve the bounding box of a scalebar from a AnchoredSizeBar from Matplotlib

I am facing serious difficulties in retrieving the bounding box of a mpl_toolkits.axes_grid1.anchored_artists "AnchoredSizeBar" object.
So far, all I found was how to insert (create) an AnchoredSizeBar into my figure. But I can't retrieve its position. A relative position in respect to its given axes would also be welcome.
Ultimately, I would like to make a AnchoredSizeBar as Behnam asks in1. But in order to do so, I would need to create a series of AnchoredSizeBars all contiguous one to another in the figure. In order to do so, I would need a function to retrieve their relative positions and apply those into the creation of the other AnchoredSizeBars, creating finally a full scalebar.
This subject is related to other links presented below:
1) How to insert scale bar in a map in matplotlib
2) Add fill_bar argument to AnchoredSizeBar
Here is a snippet code of a desired API for AnchoredSizeBar object extent retrieval.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar
fig, ax = plt.subplots(figsize=(3, 3))
bar0 = AnchoredSizeBar(ax.transData, 0.3, 'unfilled', loc=3, frameon=False,
size_vertical=0.05, fill_bar=False)
ax.add_artist(bar0)
bar0_extent = bar0.get_extent()
fig.show()
I thank you for your time, sincerely yours,
Philipe Leal
To get the extent you can pass in ax.figure.canvas.renderer where ax is the axes to which the object has been added to:
bar0_extent = bar0.get_extent(ax.figure.canvas.renderer)
But I second #ImportanceOfBeingErnest's suggestion for your particular use case. The doc-string for AnchoredSizeBar suggests that methods:
Docstring: An offset box placed according to the legend location
loc. AnchoredOffsetbox has a single child. When multiple children is
needed, use other OffsetBox class to enclose them. By default, the
offset box is anchored against its parent axes. You may explicitly
specify the bbox_to_anchor.
Hope this helps.

Main figure legend outside of subplots

I have a number of subplots within a single figure. Each figure plots multiple lines that represent the same thing (represented by color) but in different situations (different subplots). I would like to create a legend at the base of the figure showing what the color of the line means. However, I running into a problem with getting the legend to not overlap the subplots and if I can adjust the axes, getting the legend to save.
I have tried a few different solutions with some help here but have been unable to adapt to subplots. Below is an example code that I am working with.
import numpy as np
import matplotlib.pyplot as plt
m1=1
m2=10
x=np.linspace(0,100,num=101,endpoint=True)
y1m1=m1*x**2
y2m1=m1*x**0.5
y1m2=m2*x**2
y2m2=m2*x**0.5
fig=plt.figure(figsize=(4,4))
ax1=fig.add_subplot(211)
ax1.plot(x,y1m1,'b',label=r'$x^2$')
ax1.plot(x,y2m1,'r',label=r'$\sqrt{x}$')
ax2=fig.add_subplot(212)
ax2.plot(x,y1m2,'b')
ax2.plot(x,y2m2,'r')
fig.legend(loc='lower center',ncol=2)
fig.tight_layout()
fig.savefig('examplefig.png',dpi=300)
plt.show()
My goal is to save the output to a png for a good figure.
This is one way of doing it using the suggestion provided here. The idea is to add the legend at position with respect to a given axis object. In your case, since you want to add the legend at the base, it is preferred you specify the position relative to ax2. Using ncol=2 is a matter of personal choice.
fig=plt.figure(figsize=(4,4))
ax1=fig.add_subplot(211)
l1, = ax1.plot(x,y1m1,'b')
l2, = ax1.plot(x,y2m1,'r')
ax2=fig.add_subplot(212)
ax2.plot(x,y1m2, 'b')
ax2.plot(x,y2m2, 'r')
ax2.legend(handles = [l1,l2] , labels=[r'$x^2$', r'$\sqrt{x}$'],
bbox_to_anchor=(0.7, -0.2), ncol=2)
fig.tight_layout()

Matplotlib legend was not displayed properly

I am trying to plot the same geospatial data reading this tutorial:
https://www.datacamp.com/community/tutorials/geospatial-data-python
But the legend of her final graph has shwown wind speed in ranges. But when I used the same code mentioned on her tutorial, I could not produce the same legend. Any thing missing in her code? or What is wrong?
The categorical legend entries are provided via PySAL, and seem to need the scheme=<> and legend=True arguments. Perhaps these were set by default in previous versions of the libraries. For me, the following works ok:
fig, ax = plt.subplots(1, figsize=(20, 20))
base = country[country['NAME'].isin(['Alaska','Hawaii']) == False].plot(
ax=ax, color='#3B3C6E')
florence.plot(
ax=ax, column='Wind', marker="<", markersize=10,
cmap='cool', scheme="Quantiles", legend=True)
plt.axis('off')
Unfortunately the markers do not seem to be inherited into the legend, but the colors are the more salient difference anyway.
The geopandas.plot docs indicate 3 supported schemes: Quantiles, Equal_interval, fisher_jenks -- the first one seems to correspond to the datacamp example chart. See also the parameter k which defines the number of classes (5 is default as this example).

Resources