Change axis in mapltolib figure - python

Usually matplotlib uses this axis:
Y
|
|
|_______X
But I need to plot my data using:
_________Y
|
|
|
X
How can I do it? I will prefer not modify my data (i.e. transposing). I need to be able of use the coordinates always and matplotlib changes the axis.

One of the variations:
import matplotlib.pyplot as plt
def Scatter(x, y):
ax.scatter(y, x)
#Data preparation part:
x=[1, 2, 3, 4, 5]
y=[2, 3, 4, 5, 6]
#Plotting and axis inverting part
fig, ax = plt.subplots(figsize=(10,8))
plt.ylabel('X', fontsize=15)
plt.xlabel('Y', fontsize=15)
ax.xaxis.set_label_position('top') #This send label to top
plt.gca().invert_yaxis() #This inverts y axis
ax.xaxis.tick_top() #This send xticks to top
#User defined function Scatter
Scatter(x,y)
ax.grid()
ax.axis('scaled')
plt.show()
Output:

Related

How can I add text to the same position in multiple matplotlib plots with different axis scales?

I have ~20 plots with different axes, ranging from scales of 0-1 to 0-300. I want to use plt.text(x,y) to add text to the top left corner in my automated plotting function, but the changing axis size does not allow for this to be automated and completely consistent.
Here are two example plots:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
#Plot 2
plt.plot([2, 4, 6, 8])
plt.ylabel('some numbers')
plt.show()
I want to use something like plt.text(x, y, 'text', fontsize=8) in both plots, but without specifying the x and y for each plot by hand, instead just saying that the text should go in the top left. Is this possible?
Have you tried ax.text with transform=ax.transAxes?
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4])
ax.set_ylabel('XXX')
ax.text(0.05, 0.95, 'text', transform=ax.transAxes, fontsize=8, va='top', ha='left')
plt.show()
Explanation:
The ax.text takes first the x and y coordinates of the text, then the transform argument which specifies the coordinate system to use, and the va and ha arguments which specify the vertical and horizontal alignment of the text.
Use ax.annotate with axes fraction coordinates:
fig, axs = plt.subplots(1, 2)
axs[0].plot([0, 0.8, 1, 0.5])
axs[1].plot([10, 300, 200])
for ax in axs:
ax.annotate('text', (0.05, 0.9), xycoords='axes fraction')
# ------------------------
Here (0.05, 0.9) refers to 5% and 90% of the axes lengths, regardless of the data:

How to group subplots by adjusting spaces in between

I have a subplots that look as follows:
import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [4, 5, 6]
fig_shape, axs_shape = plt.subplots(2, 6, figsize=(6, 6))
for i in range(2):
for j in range(6):
axs_shape[i, j].xaxis.set_major_locator(plt.NullLocator())
axs_shape[i, j].yaxis.set_major_locator(plt.NullLocator())
for i in range(6):
axs_shape[int(i / 3), 2 * (i % 3)].plot(x, y)
axs_shape[int(i / 3), 2 * (i % 3) + 1].plot(x, y)
What I want is, that the subplots are grouped in pairs of two. That means, in each row, I want plot 0 and 1 to be right next to each other (no space in between). Then a small space and followed by plot 2 and 3 right next to each other. Then a space and plot 4 and 5 right next to each other. I read, that you can adjust sizes with .tight_layout() and subplots_adjust, but I couldn't figure out a solution for this particular behavior. Thanks a lot for your help!
You can use nested gridspecs:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
x = [1, 2, 3]
y = [4, 5, 6]
fig = plt.figure(figsize=(12, 5))
outer = gridspec.GridSpec(nrows=2, ncols=3)
axs = []
for row in range(2):
for col in range(3):
inner = gridspec.GridSpecFromSubplotSpec(nrows=1, ncols=2, subplot_spec=outer[row, col], wspace=0)
axs += [plt.subplot(cell) for cell in inner]
for ax in axs:
ax.plot(x, y)
ax.set_yticks([])
ax.set_xticks([])
plt.tight_layout()
plt.show()
PS: As mentioned in the other answer, matplotlib has implemented subfigures as a new feature. If I understand correctly, the above example would be more or less as follows:
import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [4, 5, 6]
fig = plt.figure(figsize=(12, 5), constrained_layout=True)
subfigs = fig.subfigures(nrows=2, ncols=3, wspace=0.07)
axs = [subfig.subplots(nrows=1, ncols=2, gridspec_kw={'wspace': 0}) for subfig in subfigs.ravel()]
for subax in axs:
for ax in subax:
ax.plot(x, y)
ax.set_yticks([])
ax.set_xticks([])
plt.show()
With the current matplotlib 3.4.1, I don't seem to be able to have the inner plots without a gap. Setting constrained_layout=False even makes that the 4 rightmost subplots disappear. Now it looks like:
This is the goal of the new subfigure functionality: https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subfigures.html?highlight=subfigure

Python matplotlib y axis is not working properly [duplicate]

This question already has an answer here:
Prevent scientific notation
(1 answer)
Closed 1 year ago.
I have a problem with y axis. It works fine until I put too high number into axis function. Here's the code.
import matplotlib.pyplot as plt
plt.style.available
input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
x_values = range(1, 1001)
y_values = [x**2 for x in x_values]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=100, c=y_values, cmap=plt.cm.Blues)
ax.set_title("Kwadraty liczb", fontsize=24)
ax.set_xlabel("Wartość", fontsize=14)
ax.set_ylabel("Kwadraty wartości", fontsize=14)
ax.axis([0, 1100, 0, 1100000])
plt.show()
When i was trying to figure out why it's not working I typed different values into ymax in ax.axis and for example it works for ax.axis([0, 1100, 0 , 10000]) but when I want to get 1100000 this happens https://i.stack.imgur.com/6gSOE.png
If you mean that the y axis tick labels are automatically divided by one million (indicated by the "1e6" above the tick labels), you can configure this by creating a custom ScalarFormatter object and turning scientific notation off. For more details, see the matplotlib documentation pages on tick formatters and on ScalarFormatter.
import matplotlib.pyplot as plt
from matplotlib import ticker
plt.style.available
input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
x_values = range(1, 1001)
y_values = [x**2 for x in x_values]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=100, c=y_values, cmap=plt.cm.Blues)
ax.set_title("Kwadraty liczb", fontsize=24)
ax.set_xlabel("Wartość", fontsize=14)
ax.set_ylabel("Kwadraty wartości", fontsize=14)
ax.axis([0, 1100, 0, 1100000])
formatter = ticker.ScalarFormatter()
formatter.set_scientific(False)
ax.yaxis.set_major_formatter(formatter)
plt.show()
Note that I have added a new import statement (from matplotlib import ticker) and the three lines above plt.show(). If you want this to also apply to the x axis (in case you enlarge this axis), just add a similar line of code: ax.xaxis.set_major_formatter(formatter).
While you can go through all the extra steps of creating a custom ScalarFormatter object as luuk suggested, you could achieve the same thing by simply configuring what is already provided with ax.ticklabel_format(style='plain'):
import matplotlib.pyplot as plt
#plt.style.available
input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
x_values = range(1, 1001)
y_values = [x**2 for x in x_values]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.ticklabel_format(style='plain')
ax.scatter(x_values, y_values, s=100, c=y_values,cmap=plt.cm.Blues)
ax.set_title("Kwadraty liczb", fontsize=24)
ax.set_xlabel("Wartość", fontsize=14)
ax.set_ylabel("Kwadraty wartości", fontsize=14)
ax.axis([0, 1100, 0, 1100000])
plt.show()
Still results in the same chart desired
Also, you'll notice I commented out plt.style.available because it's useless, being overwritten by plt.style.use('seaborn').

Unable to reverse xticks inside matplotlib subplot

I have designed a subplot using matplotlib. I am trying to reverse the xticks of the plot. Please see the sample code-
import numpy as np
import matplotlib.pyplot as plt
# generate the data
n = 6
y = np.random.randint(low=0, high=10, size=n)
x = np.arange(n)
# generate the ticks and reverse it
xticks = range(n)
xticks.reverse()
# plot the data
plt.figure()
ax = plt.subplot(111)
ax.bar(x, y)
print xticks # prints [5, 4, 3, 2, 1, 0]
ax.set_xticks(xticks)
plt.show()
Please see below the generated plot-
Please pay attention to the xticks. Even though, ax.set_xticks(xticks) is used but the xticks haven't changed. Am I missing some function call to rerender the plot?
Below is the system information-
matplotlib.__version__
'2.1.1'
matplotlib.__version__numpy__
'1.7.1'
python --version
Python 2.7.15rc1
Please note that I just want to reverse the ticks and do not want to invert axis.
With ax.set_xticks, you are currently specifying tick positions which is invariant to the order of the list. Either you pass [0, 1, 2, 3, 4, 5] or you pass [5, 4, 3, 2, 1, 0]. The difference will not be noticed in the ticks. What you instead want is to have reversed ticklabels for which you should do set_xticklabels(xticks[::-1]). There are two ways to do it:
Way 1
Use plt.xticks where the first argument specifies the location of the ticks and the second arguments specifies the respective ticklabels. Specifically, xticks will provide the tick positions and xticks[::-1] will label your plot with reversed ticklabels.
xticks = range(n)
# plot the data
plt.figure()
ax = plt.subplot(111)
ax.bar(x, y)
plt.xticks(xticks, xticks[::-1])
Way 2 using ax where you need set_xticklabels to get what you want
ax.set_xticks(xticks)
ax.set_xticklabels(xticks[::-1])
Use:
# generate the data
n = 6
y = np.random.randint(low=0, high=10, size=n)
x = np.arange(n)
# generate the ticks and reverse it
xticks = range(n)
# xticks.reverse()
# plot the data
plt.figure()
ax = plt.subplot(111)
ax.bar(x, y)
# print xticks # prints [5, 4, 3, 2, 1, 0]
ax.set_xticklabels(xticks[::-1]) # <- Changed
plt.show()
You can also reverse the order of the axis ax.set_xlim([5.5, -0.5])
import numpy as np
import matplotlib.pyplot as plt
n = 6
x = np.arange(n)
y = (x+1) **(1/2)
fig, axs = plt.subplots(1, 3, constrained_layout=True)
axs[0].bar(x, y)
axs[0].set_title('Original data')
axs[1].bar(x[::-1], y)
axs[1].set_xlim(5.5, -0.5)
axs[1].set_title('x index reversed\nand axis reversed')
axs[2].bar(x, y)
axs[2].set_xlim(5.5, -0.5)
axs[2].set_title('just axis reversed')
plt.show()

How to set xlim and ylim for a subplot [duplicate]

This question already has answers here:
How to set the subplot axis range
(5 answers)
Closed 7 years ago.
I would like to limit the X and Y axis in matplotlib for a specific subplot.
The subplot figure itself doesn't have any axis property. I want for example to change only the limits for the second plot:
import matplotlib.pyplot as plt
fig=plt.subplot(131)
plt.scatter([1,2],[3,4])
fig=plt.subplot(132)
plt.scatter([10,20],[30,40])
fig=plt.subplot(133)
plt.scatter([15,23],[35,43])
plt.show()
You should use the OO interface to matplotlib, rather than the state machine interface. Almost all of the plt.* function are thin wrappers that basically do gca().*.
plt.subplot returns an axes object. Once you have a reference to the axes object you can plot directly to it, change its limits, etc.
import matplotlib.pyplot as plt
ax1 = plt.subplot(131)
ax1.scatter([1, 2], [3, 4])
ax1.set_xlim([0, 5])
ax1.set_ylim([0, 5])
ax2 = plt.subplot(132)
ax2.scatter([1, 2],[3, 4])
ax2.set_xlim([0, 5])
ax2.set_ylim([0, 5])
and so on for as many axes as you want.
or better, wrap it all up in a loop:
import matplotlib.pyplot as plt
DATA_x = ([1, 2],
[2, 3],
[3, 4])
DATA_y = DATA_x[::-1]
XLIMS = [[0, 10]] * 3
YLIMS = [[0, 10]] * 3
for j, (x, y, xlim, ylim) in enumerate(zip(DATA_x, DATA_y, XLIMS, YLIMS)):
ax = plt.subplot(1, 3, j + 1)
ax.scatter(x, y)
ax.set_xlim(xlim)
ax.set_ylim(ylim)

Categories