The following code will create a plot that appears to have invisible data on several if the subplots.
Why do I then need to include ax[i].autoscale_view(True,True,True)?
Why does print ax[i].lines show [] ?
Code
from matplotlib.collections import LineCollection
import matplotlib.pyplot as plt
import numpy as np
# example data with properties:
# len(lines) == 4 and len(lines[0]) == 10
# len(x) == 10
lines = [(1.2310957583605482, 1.283772297331087, 1.61856069891319, 2.1602226857314735, 1.0277068564151643, 1.1715166081037471, 1.463648931121718, 1.2329321041327499, 1.4080120164965291, 1.2225064185740224), (0.33323810593968223, 0.32582779060567746, 0.32836534361310366, 0.51831090602571572, 0.29791484909192673, 0.35713207695246518, 0.29463171650130665, 0.34633265872428215, 0.39298012050485071, 0.410877623134692), (10, 11, 13, 17, 8, 10, 12, 10, 11, 10), (0.9911659269366481, 0.989291500800633, 0.9880005820749531, 0.9820511801663299, 0.978444258093041, 0.9737543029212308, 0.9711834357704919, 0.9632772617693266, 0.95740331184712, 0.9523058427743931)]
x = [0.0, 0.00101010101010101, 0.00202020202020202, 0.0030303030303030303, 0.00404040404040404, 0.00505050505050505, 0.006060606060606061, 0.007070707070707071, 0.00808080808080808, 0.00909090909090909]
n=len(lines) # copy in lines and x data from below
fig, ax = plt.subplots(n, sharex=True, figsize = (8, 8))
for i, y in enumerate(lines):
xy = zip(x, y)
lc = LineCollection([xy], linewidth = 2)
ax[i].add_collection(lc)
plt.show()
Related
I want to customize the number of rows in each column of the matplotlib legend text.
The code is:
import matplotlib.pyplot as plt
import numpy as np
for i in range(10):
plt.plot(np.linspace(0, 5, 5), np.random.randint(0, 10, 5), label=str(i))
plt.legend(ncol = 3, loc = 1)
plt.show()
What I get: the numbers of rows in each column are 4, 3, 3
What I want: the numbers of rows in each column are 4, 4, 2
I've tried adding plt.plot([], [], label='') before plt.show(), but it doesn't help
I solved this problem by adding an invisible line as 11th element like this:
import matplotlib.pyplot as plt
import numpy as np
lines = []
for i in range(10):
l, = plt.plot(np.linspace(0, 5, 5), np.random.randint(0, 10, 5), label=str(i))
lines.append(l)
l, = plt.plot(0, alpha=0, label=' ')
# alpha=0 will make the line and element in the legend invisible
lines.append(l)
plt.legend(handles=[l for l in lines], ncol = 3, loc = 1)
plt.show()
This will yield the following result:
I want to change text in matplotlib's plot with loop. I am able to print text with loop, but unable to delete the previous text and they got printed on top of each other.
import numpy as np
import matplotlib.pyplot as plt
x = np.array([1,2,3,4,5])
y = np.array([1,2,3,4,5])
fig, ax = plt.subplots()
ax.set_xlim([0,5])
ax.set_ylim([0,5])
for i in x:
pt = ax.plot(i, i, 'o')
tx = ax.text(1, 2, str(i), fontsize = 12)
plt.pause(1)
removePt = pt.pop()
removePt.remove()
I tried to delete text by
removeTx = tx.pop()
removeTx.remove()
but it has not worked.
Kindly suggest how can I remove the previous text from plot.
Just add tx.remove() after the pause:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([1, 2, 3, 4, 5])
y = np.array([1, 2, 3, 4, 5])
fig, ax = plt.subplots()
ax.set_xlim([0, 5])
ax.set_ylim([0, 5])
for i in x:
pt = ax.plot(i, i, 'o')
tx = ax.text(1, 2, str(i), fontsize = 12)
plt.pause(1)
tx.remove()
plt.show()
as you can see, I want to make the dash connect to the x and y axes.
There is always a small gap.
I use matplotlib
the vline function, and I don't know how to use the transform parameters.
Using vlines and hlines from matplotlib.pyplot, you can specify your axes and your line limits:
from matplotlib import pyplot as plt
# Drawing example diagram
plt.scatter(x=11,y=0.891)
plt.xlim(5,20)
plt.xticks([5,8,11,14,17,20])
plt.ylim(0.780,0.9)
# Specifying lines, notice how despite setting xmin and ymin lower than your axes,
# the lines stop at each boundary
plt.vlines(x=11, ymin=0.7, ymax=0.891, colors='r',linestyles='dashed')
plt.hlines(y=0.891, xmin=4, xmax=11, colors='k',linestyles='dashed')
plt.show()
The result is beautiful, but the code not so good.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as ticker
x = [i for i in range(5, 21, 3)]
# [5, 8, 11, 14, 17, 20]
y = [0.780, 0.865, 0.891, 0.875, 0.884, 0.870]
y_max_index = np.argmax(y)
# print(y_max_index)
# get the max point
x_max = x[y_max_index]
y_max = y[y_max_index]
fig, ax = plt.subplots()
ax.plot(x, y, marker='o', color='r')
# set x ticks as [5, 8, 11, 14, 17, 20]
my_x_ticks = x
plt.xticks(my_x_ticks)
# set x and y lim
axe_y_min, axe_y_max = ax.get_ylim()
axe_x_min, axe_x_max = ax.get_xlim()
ax.set_ylim(axe_y_min, axe_y_max)
ax.set_xlim(axe_x_min, axe_x_max)
plt.gca().yaxis.set_major_formatter(ticker.FormatStrFormatter('%.3f')) # set y axe format
anno_text = "(11, 0.891)"
plt.annotate(anno_text, xy=(x_max, y_max), xytext=(x_max+0.5, y_max)) # annotate
y_scale_trans = (y_max - axe_y_min) / (axe_y_max - axe_y_min)
x_scale_trans = (x_max - axe_x_min) / (axe_x_max - axe_x_min)
ax.vlines(x_max, 0, y_scale_trans, transform=ax.get_xaxis_transform(), colors='black', linestyles="dashed")
ax.hlines(y_max, 0, x_scale_trans, transform=ax.get_yaxis_transform(), colors='black', linestyles="dashed")
plt.ylabel("准确率")
plt.xlabel("滑动窗口大小")
plt.savefig("滑动窗口.pdf", dpi=100)
plt.show()
Here is a solution using plt.plot to draw the lines.
import matplotlib.pyplot as plt
import numpy as np
y = np.random.randint(1, 10, 10)
x = np.arange(len(y))
point = [x[2], y[2]]
plt.plot(x,y)
plt.plot((point[0], point[0]), (0, point[1]), '--')
plt.plot((0, point[0]), (point[1], point[1]), '--')
plt.xlim(0,10)
plt.ylim(0,10)
I am drawing a 3d bar chart. The x and y plate is 10 * 10. However, it only displays 6 ticks in the x and y axis:
%matplotlib notebook
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
# setup the figure and axes
fig = plt.figure(figsize=(10,10))
ax1 = fig.add_subplot( projection='3d')
_x = np.arange(10)
_y = np.arange(10)
_xx, _yy = np.meshgrid(_x, _y)
x, y = _xx.ravel(), _yy.ravel()
bottom = np.zeros_like(top)
width = depth = 1
ax1.bar3d(x,y, bottom, width, depth, top, shade=True)
ax1.set_xlabel('Left cluster ID')
x_ticks =[str(i) for i in left_cluster_id]
ax1.set_xticklabels(labels=['c1','c2','c3','c4','c5','c6','c7','c8','c9','c10'])
ax1.set_ylabel('Right cluster ID')
ax1.set_yticklabels(labels = [0, 2, 3, 5, 9, 12, 13, 14, 15, 19])
ax1.set_zlabel('# of overlapping peaks')
plt.show()
How to let it display all the 10 ticks?
When I plot data using matplotlib I always have 5-9 ticks on my x-axis independent of the range I plot, and if I zoom on the x-axis the tick spacing decreases, so I still see 5-9 ticks.
however, I would like 20-30 ticks on my x-axis!
I can achieve this with the following:
from matplotlib import pyplot as plt
import numpy as np
x = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
y = [1, 4, 3, 2, 7, 6, 9, 8, 10, 5]
number_of_ticks_on_x_axis = 20
plt.plot(x, y)
plt.xticks(np.arange(min(x), max(x)+1, (max(x) - min(x))/number_of_ticks_on_x_axis))
plt.show()
If I now zoom on the x-axis, no new ticks appear between the existing ones. I would like to still have ~20 ticks however much I zoom.
Assuming that you want to fix the no. of ticks on the X axis
...
from matplotlib.ticker import MaxNLocator
...
fig, ax = plt.subplots()
ax.xaxis.set_major_locator(MaxNLocator(15, min_n_ticks=15))
...
Please look at the docs for MaxNLocator
Example
In [36]: import numpy as np
...: import matplotlib.pyplot as plt
In [37]: from matplotlib.ticker import MaxNLocator
In [38]: fig, ax = plt.subplots(figsize=(10,4))
In [39]: ax.grid()
In [40]: ax.xaxis.set_major_locator(MaxNLocator(min_n_ticks=15))
In [41]: x = np.linspace(0, 1, 51)
In [42]: y = x*(1-x)
In [43]: plt.plot(x, y)
Out[43]: [<matplotlib.lines.Line2D at 0x7f9eab409e10>]
gives
and when I zoom into the maximum of the curve I get
You can link a callback function to an event in the canvas. In you case you can trigger a function that updates the axis when a redraw occurs.
from matplotlib import pyplot as plt
import numpy as np
x = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
y = [1, 4, 3, 2, 7, 6, 9, 8, 10, 5]
n = 20
plt.plot(x, y)
plt.xticks(np.arange(min(x), max(x)+1, (max(x) - min(x))/n), rotation=90)
def on_zoom(event):
ax = plt.gca()
fig = plt.gcf()
x_min, x_max = ax.get_xlim()
ax.set_xticks(np.linspace(x_min, x_max, n))
# had to add flush_events to get the ticks to redraw on the last update.
fig.canvas.flush_events()
fig = plt.gcf()
fig.canvas.mpl_disconnect(cid)
cid = fig.canvas.mpl_connect('draw_event', on_zoom)