Is there a simple way to get log transformed counts when plotting a two dimensional histogram in matplotlib? Unlike the pyplot.hist method, the pyplot.hist2d method does not seem to have a log parameter.
Currently I'm doing the following:
import numpy as np
import matplotlib as mpl
import matplotlib.pylab as plt
matrix, *opt = np.histogram2d(x, y)
img = plt.imshow(matrix, norm = mpl.colors.LogNorm(), cmap = mpl.cm.gray,
interpolation="None")
Which plots the expected histogram, but the axis labels show the indices of the bins and thus not the expected value.
It's kind of embarrassing, but the answer to my question is actually in the docstring of the corresponding code:
Notes
-----
Rendering the histogram with a logarithmic color scale is
accomplished by passing a :class:`colors.LogNorm` instance to
the *norm* keyword argument. Likewise, power-law normalization
(similar in effect to gamma correction) can be accomplished with
:class:`colors.PowerNorm`.
So this works:
import matplotlib as mpl
import matplotlib.pylab as plt
par = plt.hist2d(x, y, norm=mpl.colors.LogNorm(), cmap=mpl.cm.gray)
Related
I have written following code,
import numpy as np
import matplotlib.pyplot as plt
x=np.random.randint(0,10,[1,5])
y=np.random.randint(0,10,[1,5])
x.sort(),y.sort()
fig, ax=plt.subplots(figsize=(10,10))
ax.plot(x,y)
ax.set( title="random data plot", xlabel="x",ylabel="y")
I am getting a blank figure.
Same code prints chart if I manually assign below value to x and y and not use random function.
x=[1,2,3,4]
y=[11,22,33,44]
Am I missing something or doing something wrong.
x=np.random.randint(0,10,[1,5]) returns an array if you specify the shape as [1,5]. Either you would want x=np.random.randint(0,10,[1,5])[0] or x=np.random.randint(0,10,size = 5). See: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.random.randint.html
Matplotlib doesn't plot markers by default, only a line. As per #Can comment, matplotlib then interprets your (1, 5) array as 5 different datasets each with 1 point, so there is no line as there is no second point.
If you add a marker to your plot function then you can see the data is actually being plotted, just probably not as you wish:
import matplotlib.pyplot as plt
import numpy as np
x=np.random.randint(0,10,[1,5])
y=np.random.randint(0,10,[1,5])
x.sort(),y.sort()
fig, ax=plt.subplots(figsize=(10,10))
ax.plot(x,y, marker='.') # <<< marker for each point added here
ax.set( title="random data plot", xlabel="x",ylabel="y")
I would like to visualize 2D slices in a 3D plot by means of matplotlib and Axes3D, with some transparency to have a better view, as represented by
where the 2D slices clearly overlap. These slices are produced by pcolor, which in contrast to pcolormesh, returns a matplotlib.collections.Collection object and consequently can be handled by add_collection3d.
The issue of carrying the transparency property has already been discussed there and there, although the workarounds suggested (in Python comments below) haven't had any effect with my issue. My sample code is something along the lines of
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
X, Y = np.meshgrid(x,y)
fig = plt.figure()
ax = fig.gca(projection='3d')
alpha = 0.8
for i in range(len(islices)):
im = ax.pcolor(X,Y,u[islices[i],:,:]) #,alpha=alpha)
#im.set_facecolor((0, 0, 1, alpha))
ax.add_collection3d(im,zs=xslices[i],zdir='y')
plt.show()
i am trying to construct a function which gives me interpolated values of a piecewise linear function. I tried linear spline interpolation (which should be able to do exactly this?)- but without any luck. The problem is most visible on a log scale plot. Below there is the code of a small example i prepared:
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import os
from scipy import interpolate
#Original Data
pwl_data = np.array([[0,1e3, 1e5, 1e8], [-90,-90, -90, -130]])
#spine interpolation
pwl_spline = interpolate.splrep(pwl_data[0], pwl_data[1])
spline_x = np.linspace (0,1e8, 10000)
legend = []
plt.plot(pwl_data[0],pwl_data[1])
plt.plot(spline_x,interpolate.splev(spline_x,pwl_spline ),'*')
legend.append("Data")
legend.append("Interpolated Data")
plt.xscale('log')
plt.legend(legend)
plt.grid(True)
plt.grid(b=True, which='minor', linestyle='--')
plt.show()
What am I doing wrong?
The spline fitting have to be performed on the linearized data, i.e. using log(x) instead of x:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate
#Original Data
pwl_data = np.array([[1, 1e3, 1e5, 1e8], [-90, -90, -90, -130]])
x = pwl_data[0]
y = pwl_data[1]
log_x = np.log(x)
#spine interpolation
pwl_spline = interpolate.splrep(log_x, y)
spline_log_x = np.linspace(0, 18, 30)
spline_y = interpolate.splev(spline_log_x, pwl_spline )
plt.plot(log_x, y, '-o')
plt.plot(spline_log_x, spline_y, '-*')
plt.xlabel('log(x)');
note: I remove the zero from the data. Also, spline fitting could be not the best if you want a piecewise linear function, you could have a look at this question for example: https://datascience.stackexchange.com/q/8457/53362
For plotting with matplotlib, consider matplotlibs step which internally performs a piecewise constant interpolation.
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.step.html
you can invoke it simply via:
plt.step(x,y) given your inputs x and y.
In plotly the argument line_shape='hv' for the Scatter plot achieves similar results see https://plotly.com/python/line-charts/
I am trying to plot some colorful discrete data using matplotlib.
With tab10-like colormaps I get nice results
However, I would need a combination of tab20 and tab20b parts, to have my data plotted as:
1->tab20darkblue
2->tab20lightblue
3->tab20cOrange1
4->tab20cOrange2
5->tab20cOrange3
6->tab20cOrange4
is that possible somehow?
You can create a ListedColormap from the colors of other colormaps.
E.g to get the darkorange color from the tab20c colormap, use plt.cm.tab20c(4) (as this is the 5th color in that map). Note that this works only for indexed colormaps - otherwise you need to use a value between 0 and 1.
From a list of thus obtained colors, you can create a new ListedColormap.
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
colors = [plt.cm.tab20(0),plt.cm.tab20(1),plt.cm.tab20c(4),
plt.cm.tab20c(5),plt.cm.tab20c(6),plt.cm.tab20c(7)]
cmap=matplotlib.colors.ListedColormap(colors)
x = np.arange(1,7)
plt.scatter(x,x,c=x, s=100, cmap=cmap, vmin=1, vmax=7)
plt.show()
Or, to get a nice colorbar as well,
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
colors = [plt.cm.tab20(0),plt.cm.tab20(1),plt.cm.tab20c(4),
plt.cm.tab20c(5),plt.cm.tab20c(6),plt.cm.tab20c(7)]
cmap=matplotlib.colors.ListedColormap(colors)
norm = matplotlib.colors.BoundaryNorm(np.arange(1,8)-0.5,len(colors))
x = np.arange(1,7)
sc = plt.scatter(x,x,c=x, s=100, cmap=cmap, norm=norm)
plt.colorbar(sc, ticks=x)
plt.show()
I have a figure that consists of an image displayed by imshow(), a contour and a vector field set by quiver(). I have colored the vector field based on another scalar quantity. On the right of my figure, I have made a colorbar(). This colorbar() represents the values displayed by imshow() (which can be positive and negative in my case). I'd like to know how I could setup another colorbar which would be based on the values of the scalar quantity upon which the color of the vectors is based. Does anyone know how to do that?
Here is an example of the image I've been able to make. Notice that the colors of the vectors go from blue to red. According to the current colorbar, blue means negative. However I know that the quantity represented by the color of the vector is always positive.
Simply call colorbar twice, right after each plotting call. Pylab will create a new colorbar matching to the latest plot. Note that, as in your example, the quiver values range from 0,1 while the imshow takes negative values. For clarity (not shown in this example), I would use different colormaps to distinguish the two types of plots.
import numpy as np
import pylab as plt
# Create some sample data
dx = np.linspace(0,1,20)
X,Y = np.meshgrid(dx,dx)
Z = X**2 - Y
Z2 = X
plt.imshow(Z)
plt.colorbar()
plt.quiver(X,Y,Z2,width=.01,linewidth=1)
plt.colorbar()
plt.show()
Running quiver doesn't necessarily return the type of mappable object that colorbar() requires. I think it might be because I explicitly "have colored the vector field based on another scalar quantity" like Heimdall says they did. Therefore, Hooked's answer didn't work for me.
I had to create my own mappable for the color bar to read. I did this by using Normalize from matplotlib.colors on the data that I wanted to use to color my quiver vectors (which I'll call C, which is an array of the same shape as X, Y, U, and V.)
My quiver call looks like this:
import matplotlib.pyplot as pl
import matplotlib.cm as cm
import matplotlib.colors as mcolors
import matplotlib.colorbar as mcolorbar
pl.figure()
nz = mcolors.Normalize()
nz.autoscale(C)
pl.quiver(X, Y, U, V, color=cm.jet(nz(C)))
cax,_ = mcolorbar.make_axes(pl.gca())
cb = mcolorbar.ColorbarBase(cax, cmap=cm.jet, norm=nz)
cb.set_label('color data meaning')
Giving any other arguments to the colorbar function gave me a variety of errors.