Custom scale from simple list or dict? - python

I need to make a custom scale for an axis. Before diving into http://matplotlib.org/examples/api/custom_scale_example.html, I'm wondering if there is an easier way for my special case.
A picture is worth a thousand words, so here we go:
See the value in each row next to the filename ? I would like the row height to be relative to the difference between it and the previous one. I'd start from 0 and would have to define a top limit so I see the last row.

Try matplotlib's pcolormesh with which you can create irregularly shaped grids.
from matplotlib import pyplot as plt
import numpy as np
y1D = np.hstack([0, np.random.random(9)])
y1D = np.sort(y1D)/np.max(y1D)
x, y = np.meshgrid(np.arange(0,1.1,0.1),y1D)
plt.pcolormesh(x,y, np.random.random((10,10)))
plt.show()

You can use this recipe and adapt to your needs:
import numpy as np
import matplotlib.pyplot as plt
grid = np.zeros((20,20))
for i in range(grid.shape[0]):
r = np.random.randint(1,19)
grid[i,:r] = np.random.randint(10,30,size=(r,))
plt.imshow(grid,origin='lower',cmap='Reds',interpolation='nearest')
plt.yticks(list(range(20)),['File '+str(i) for i in range(20)])
plt.colorbar()
plt.show()
, the result is this:

Related

Scaling down a plot when using matplotlib

I've been trying to plot a graph of Epoch vs Accuracy and val_accuracy from a train log I have generated. Whenever I try to plot it, the y-axis starts from 0.93 rather than it being in 0, 0.1 ,0.2... intervals. I'm new at using matplotlib or any plot function.
Here's the code for it:
import pandas as pd
import matplotlib.pyplot as plt
acc = pd.read_csv("train_log", sep = ',')
acc.plot("epoch", ["accuracy","val_accuracy"])
plt.savefig('acc' , dpi = 300)
I'm open to suggestion in complete different ways to do this.
Picture of plot :
[1]: https://i.stack.imgur.com/lgg0W.png
This has already been discussed here. There are a couple of different ways you can do this (using plt.ylim() or making a new variable like axes and then axes.set_ylim()), but the easiest is to use the set_ylim function as it gives you heaps of other handles to manipulate the plot. You can also handle the x axis values using the set_xlim function.
You can use the set_ylim([ymin, ymax]) as follows:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0,5)
y = np.arange(5,10)
axes = plt.gca()
axes.plot(x,y)
axes.set_ylim([0,10])
You can use the plt.ylim() like this:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0,5)
y = np.arange(5,10)
plt.plot(x,y)
plt.ylim([0,10])
This will produce the same plot.
You need to set the lower/bottom limit using ylim().
For details please refer:
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.ylim.html

Python matplotlib: how to let matrixplot have variable column widths

I have a simple need but cannot find its simple solution. I have a matrix to plot, but I wish the row/columns to have given widths.
Something looking like a blocked matrix where you tell block sizes.
Any workaround with the same visual result is accepted.
import matplotlib.pyplot as plt
import numpy as np
samplemat = np.random.rand(3,3)
widths = np.array([.7, .2, .1])
# Display matrix
plt.matshow(samplemat)
plt.show()
matshow or imshow work with equal sized cells. They hence cannot be used here. Instead you may use pcolor or pcolormesh. This would require to supply the coordinates of the cell edges.
Hence you first need to calculate those from the given width. Assuming you want them to start at 0, you may just sum them up.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(43)
samplemat = np.random.rand(3,3)
widths = np.array([.7, .2, .1])
coords = np.cumsum(np.append([0], widths))
X,Y = np.meshgrid(coords,coords)
# Display matrix
plt.pcolormesh(X,Y,samplemat)
plt.show()

How to update 3D arrow animation in matplotlib

I am trying to reproduce the left plot of this animation in python using matplotlib.
I am able to generate the vector arrows using the 3D quiver function, but as I read here, it does not seem possible to set the lengths of the arrows. So, my plot does not look quite right:
So, the question is: how do I generate a number of 3D arrows with different lengths? Importantly, can I generate them in such a way so that I can easily modify for each frame of the animation?
Here's my code so far, with the not-so-promising 3D quiver approach:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d
ax1 = plt.subplot(111,projection='3d')
t = np.linspace(0,10,40)
y = np.sin(t)
z = np.sin(t)
line, = ax1.plot(t,y,z,color='r',lw=2)
ax1.quiver(t,y,z, t*0,y,z)
plt.show()
As Azad suggests, an inelegant, but effective, solution is to simply edit the mpl_toolkits/mplot3d/axes3d.py to remove the normalization. Since I didn't want to mess with my actual matplotlib installation, I simply copied the axes3d.py file to the same directory as my other script and modified the line
norm = math.sqrt(u ** 2 + v ** 2 + w ** 2)
to
norm = 1
(Be sure to change the correct line. There is another use of "norm" a few lines higher.) Also, to get axes3d.py to function correctly when it's outside of the mpl directory, I changed
from . import art3d
from . import proj3d
from . import axis3d
to
from mpl_toolkits.mplot3d import art3d
from mpl_toolkits.mplot3d import proj3d
from mpl_toolkits.mplot3d import axis3d
And here is the nice animation that I was able to generate (not sure what's going wrong with the colors, it looks fine before I uploaded to SO).
And the code to generate the animation:
import numpy as np
import matplotlib.pyplot as plt
import axes3d_hacked
ax1 = plt.subplot(111,projection='3d')
plt.ion()
plt.show()
t = np.linspace(0,10,40)
for index,delay in enumerate(np.linspace(0,1,20)):
y = np.sin(t+delay)
z = np.sin(t+delay)
if delay > 0:
line.remove()
ax1.collections.remove(linecol)
line, = ax1.plot(t,y,z,color='r',lw=2)
linecol = ax1.quiver(t,y,z, t*0,y,z)
plt.savefig('images/Frame%03i.gif'%index)
plt.draw()
plt.ioff()
plt.show()
Now, if I could only get those arrows to look prettier, with nice filled heads. But that's a separate question...
EDIT: In the future, matplotlib will not automatically normalize the arrow lengths in the 3D quiver per this pull request.
Another solution is to call ax.quiever on each arrow, individually - with each call having an own length attribute. This is not very efficient but it will get you going.
And there's no need to change MPL-code

Plotting random point on Function - Pandas

I want to graph a function 2D or 3D
for example a f(x) = sin(x)
Then randomly plot a certain amount of points
I am using IPython and I think this might be possible using Pandas
You can use np.random.uniform to generate a few random points along x-axis and calculate corresponding f(x) values.
import numpy as np
import matplotlib.pyplot as plt
# generate 20 points from uniform (-3,3)
x = np.random.uniform(-3, 3, size=20)
y = np.sin(x)
fig, ax = plt.subplots()
ax.scatter(x,y)
You should post example code so people can demonstrate it more easily.
(numpy.random.random(10)*x_scale)**2
Generate an array of random numbers between 0 and 1, scale as appropriate (so for (-10,0);
10*numpy.random.random(100) -10
then pass this to any function that can calculate the value of f(x) for each element of the array.
Use shape() if you need to play around with layout of the array.
If you want to use Pandas...
import pandas as pd
import matplotlib.pyplot as plt
x=linspace(0,8)
y=sin(x)
DF=pd.DataFrame({'x':x,'y':y})
plot values:
DF.plot(x='x',y='y')
make a random index:
RandIndex=randint(0,len(DF),size=20)
use it to select from original DF and plot:
DF.iloc[RandIndex].plot(x='x',y='y',kind='scatter',s=120,ax=plt.gca())

Python / PyPlot- How can I specify the x/y-axis on plt.imshow?

Often when I want to visualise 3D data I do the following
import numpy as np
import matplotlib.pyplot as plt
X, Y = np.mgrid[:10, :20]
z = x**2 + y
plt.imshow(z)
plt.show()
The problem with this is that often I want to set the x and y variables instead of being "pixels". I know plt.contourf does what I want but the problem with that is the quality is no where near as good as plt.imshow
The solution I'm trying to work towards is getting the plt.contourf syntax to work for plt.imshow.
Any ideas?
EDIT:
The solution should also work on the following use case:
import numpy as np
import matplotlib.pyplot as plt
R, P = np.mgrid[:10, :2*np.pi:np.pi/50]
plt.contourf(R*np.cos(P), R*np.sin(P), R) # <--- need better function
# plt.imshow(R*np.cos(P), R*np.sin(P), R) # something like this
plt.show()
The best way I found to do what I want is to use the plt.contourf
so the following would do what I want.
import numpy as np
import matplotlib.pyplot as plt
R, P = np.mgrid[:10, :2*np.pi:np.pi/50]
N = 50
plt.contourf(R*np.cos(P), R*np.sin(P), R, N) # <--- need better function
plt.pcolormesh(R*np.cos(P), R*np.sin(P), R) # <--- exactly what I want
# plt.imshow(R*np.cos(P), R*np.sin(P), R) # something like this
plt.show()
Tweaking N gets you a good enough image in contourf. The only thing I don't like about this is the very fact you might need to tweak the N value.

Categories