Seaborn: how to make a Log base 2 axis in a small multiples plot? - matplotlib

I'm doing a small multiples plot with seaborn using relplot:
g = sns.relplot(data=df,
kind='scatter',
col='mycol', row='arow',
x='a', y='b',
hue='c',
legend=False,
alpha=.5)
I can easily tranform the axis for a log scale in base 10:
g.set(xscale="log")
g.set(yscale="log")
If I were ploting a simple plot with matplotlib I'd be able to use a log scale in base 2:
ax.set_xscale('log', basex=2)
ax.set_yscale('log', basey=2)
But how do I make a Log2 plot in Seaborn?

Just discovered how to do it using a global function:
plt.xscale('log', basex=2)
plt.yscale('log', basey=2)

Related

How to avoid matplotlib to simplify my Y axis in figure?

the image of what I mean in my question
I'm using BMP280 to measure Temperature and Pressure using Raspberry.
I'm using matplotlib to make a graph, but the matplotlib simplify my Y axis bi adding +9.967e2.
is there any way to avoid matplotlib simplify my Y axis. Sorry I'm new to this so I don't know much.
I tried to search in google but I don't find anything. Maybe I'm using the wrong keyword as I don't know what should I search.
You can turn off the offset as shown in the examples here. For example, if you've made you plot with:
from matplotlib import pyplot as plt
plt.plot(x, y)
then you can turn off the offset with
ax = plt.gca() # get the axes object
# turn off the offset (on the y-axis only)
ax.ticklabel_format(axis="y", useOffset=False)
plt.show()
See the ticklabel_format docs for more info.

Plotting fuzzy data with matplotlib

I don't know where to start, as I think it is a new approach for me. Using matplotlib with python, I would like to plot a set of fuzzy numbers (for instance a set of triangular or bell curve fuzzy numbers) as in the picture below:
You can plot the curves recurrently. My try at reproducing your example (including the superposition of labels 1 and 6):
import matplotlib.pyplot as plt
import numpy as np
# creating the figure and axis
fig, ax = plt.subplots(1,1,constrained_layout=True)
# generic gaussian
y = np.linspace(-1,1,100)
x = np.exp(-5*y**2)
center_x = (0,2,4,1,3,0,5)
center_y = (6,2,3,4,5,6,7)
# loop for all the values
for i in range(len(center_x)):
x_c, y_c = center_x[i], center_y[i]
# plotting the several bells, relocated to (x_c, y_c)
ax.plot(x + x_c,y + y_c,
color='red',linewidth=2.0)
ax.plot(x_c,y_c,
'o',color='blue',markersize=3)
# adding label
ax.annotate(
str(i+1),
(x_c - 0.1,y_c), # slight shift in x
horizontalalignment='right',
verticalalignment='center',
color='blue',
)
ax.grid()
Every call to ax.plot() is adding points or curves (to be more precise, Artists) to the same axis. The same for ax.annotate() to create the labels.

How do you plot an upside down histogram in matplotlib?

Can you plot a histogram in matplotlib so that it appears upside down, i.e. the base of the histogram is along the top axis and it "hangs" down? Or, alternatively, if plotting with orientation='horizontal', so that the base of the histogram is on the right hand axis?
Yes, use invert_yaxis:
df = pd.DataFrame({'a':[1,2,3,1,2,2,2],
'b':[1,1,1,3,2,2,2]})
ax = df.plot.hist()
ax.invert_yaxis()
Output:

Second Matplotlib figure doesn't save to file

I've drawn a plot that looks something like the following:
It was created using the following code:
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
# 1. Plot a figure consisting of 3 separate axes
# ==============================================
plotNames = ['Plot1','Plot2','Plot3']
figure, axisList = plt.subplots(len(plotNames), sharex=True, sharey=True)
tempDF = pd.DataFrame()
tempDF['date'] = pd.date_range('2015-01-01','2015-12-31',freq='D')
tempDF['value'] = np.random.randn(tempDF['date'].size)
tempDF['value2'] = np.random.randn(tempDF['date'].size)
for i in range(len(plotNames)):
axisList[i].plot_date(tempDF['date'],tempDF['value'],'b-',xdate=True)
# 2. Create a new single axis in the figure. This new axis sits over
# the top of the axes drawn previously. Make all the components of
# the new single axis invisibe except for the x and y labels.
big_ax = figure.add_subplot(111)
big_ax.set_axis_bgcolor('none')
big_ax.set_xlabel('Date',fontweight='bold')
big_ax.set_ylabel('Random normal',fontweight='bold')
big_ax.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')
big_ax.spines['right'].set_visible(False)
big_ax.spines['top'].set_visible(False)
big_ax.spines['left'].set_visible(False)
big_ax.spines['bottom'].set_visible(False)
# 3. Plot a separate figure
# =========================
figure2,ax2 = plt.subplots()
ax2.plot_date(tempDF['date'],tempDF['value2'],'-',xdate=True,color='green')
ax2.set_xlabel('Date',fontweight='bold')
ax2.set_ylabel('Random normal',fontweight='bold')
# Save plot
# =========
plt.savefig('tempPlot.png',dpi=300)
Basically, the rationale for plotting the whole picture is as follows:
Create the first figure and plot 3 separate axes using a loop
Plot a single axis in the same figure to sit on top of the graphs
drawn previously. Label the x and y axes. Make all other aspects of
this axis invisible.
Create a second figure and plot data on a single axis.
The plot displays just as I want when using jupyter-notebook but when the plot is saved, the file contains only the second figure.
I was under the impression that plots could have multiple figures and that figures could have multiple axes. However, I suspect I have a fundamental misunderstanding of the differences between plots, subplots, figures and axes. Can someone please explain what I'm doing wrong and explain how to get the whole image to save to a single file.
Matplotlib does not have "plots". In that sense,
plots are figures
subplots are axes
During runtime of a script you can have as many figures as you wish. Calling plt.save() will save the currently active figure, i.e. the figure you would get by calling plt.gcf().
You can save any other figure either by providing a figure number num:
plt.figure(num)
plt.savefig("output.png")
or by having a refence to the figure object fig1
fig1.savefig("output.png")
In order to save several figures into one file, one could go the way detailed here: Python saving multiple figures into one PDF file.
Another option would be not to create several figures, but a single one, using subplots,
fig = plt.figure()
ax = plt.add_subplot(611)
ax2 = plt.add_subplot(612)
ax3 = plt.add_subplot(613)
ax4 = plt.add_subplot(212)
and then plot the respective graphs to those axes using
ax.plot(x,y)
or in the case of a pandas dataframe df
df.plot(x="column1", y="column2", ax=ax)
This second option can of course be generalized to arbitrary axes positions using subplots on grids. This is detailed in the matplotlib user's guide Customizing Location of Subplot Using GridSpec
Furthermore, it is possible to position an axes (a subplot so to speak) at any position in the figure using fig.add_axes([left, bottom, width, height]) (where left, bottom, width, height are in figure coordinates, ranging from 0 to 1).

Copying axis limits from one subplot ('equal' aspect) to another

In a figure with 2x2 subplots, I need both the subplots on the right to share the x-axis, but the ones on the left not to share their axis. In addition, I need the subplot that is determining the x-axis limits to have 'equal' aspect ratio. I tried this:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 2, figsize=(12, 9))
# Subplot [0,1]
ax[0,1].axis('equal')
ax[0,1].plot(...)
[xmin01, xmax01, ymin01, ymax01] = self.ax[0,1].axis()
# Subplot [1,1]
ax[1,1].plot(...)
ax[1,1].set_xlim(left=xmin01, right=xmax01)
This is not working: the limits of the x-axis returned by axis() are near the data limits and are not the real limits shown in the graphed subplot. Changing the position of ax[0,1].axis('equal') after the plot command has no effect. Any idea?
Looking into the pyplot source code I discovered that axis('equal') is calling the method set_aspect(). This latter method is modifying the variable self._aspect but it is not further updating anything related! Then, I looked for and found the method that is really updating the aspect ratio: it is named apply_aspect(). So, it doesn't seem very elegant, but at least my problem is solved as shown:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 2, figsize=(12, 9))
# Subplot [0,1]
ax[0,1].axis('equal')
ax[0,1].plot(...)
ax[0,1].apply_aspect()
[xmin01, xmax01, ymin01, ymax01] = self.ax[0,1].axis()
# Subplot [1,1]
ax[1,1].plot(...)
ax[1,1].set_xlim(left=xmin01, right=xmax01)