I want to plot my data as a heatmap which has the following structure:
X = [1,1,1,1,1,1,1,1,1,1],
Y = [1,2,3,4,5,6,7,8,9,10]
Z = [0.2, 0.33, 0.1, 0.25, 0.0, 0.9, 0.75, 0.88, 0.44, 0.95]
The x and y-axis shall be represented by X and Y, while the 'heat' is represented by the values of Z.
E.g. at coordinate (x,y) = (1,2) the intensity shall be 0.33
How can this be achieved by using matplotlib?
Looking at posts which relate to the keyword heatmap or even to those related to the term contour map, I could not transfer it to this problem yet.
Thank you in advance for any hints
Dan
I hope your data is just an example because it will look funny (it's more a sequence of strips; the x-dimension is constant).
I would recommend the usage of pandas (general data-analysis) and seaborn (matplotlib-extensions) which makes it a bit nicer.
Code
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
X = [1,1,1,1,1,1,1,1,1,1]
Y = [1,2,3,4,5,6,7,8,9,10]
Z = [0.2, 0.33, 0.1, 0.25, 0.0, 0.9, 0.75, 0.88, 0.44, 0.95]
data = pd.DataFrame({'X': X, 'Y': Y, 'Z': Z})
data_pivoted = data.pivot("X", "Y", "Z")
ax = sns.heatmap(data_pivoted)
plt.show()
Output
Related
I am trying to write a program that reads data from a NumPy file, and then uses that data to plot a Lorenz curve, but I'm not exactly sure how to make the Lorenz curve. I tried using the cumsum() function, but I was not able to plot the Lorenz curve. Here's what I have so far:
import numpy as np
import matplotlib.pyplot as plt
data = np.load('pop2010.npy')
print(data)
plt.plot(data[0]) # display all the points
plt.show()
plot_x = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
plot_y = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
plt.plot(plot_x, plot_y)
# set the labels for x, y, and title
plt.xlabel("Countries")
plt.ylabel("Wealth")
plt.title("Population-Lorenz Curve")
# save plot as png file
plt.savefig('population-lorenz.png', dpi = 200)
plt.show()
Any advice would be appreciated, thanks!
Adapting from https://zhiyzuo.github.io/Plot-Lorenz/, combining with your code.
Not quite clear from the context you provide, but I think data is what you want to plot as a Lorenz curve, and the plot_x, plot_y variables are your way of plotting the x-y line?
Note that I am using the object-oriented API instead of the pyplot API since this is what the docs now recommend--I think you'll find it's easier to work with in the long run. See https://matplotlib.org/stable/api/index.html#usage-patterns for detail.
import numpy as np
import matplotlib.pyplot as plt
data = np.load('pop2010.npy')
X_lorenz = data.cumsum() / data.sum()
X_lorenz = np.insert(X_lorenz, 0, 0)
fig, ax = plt.subplots(figsize=[6,6])
## scatter plot of Lorenz curve
ax.scatter(np.arange(X_lorenz.size)/(X_lorenz.size-1), X_lorenz,
marker='x', color='darkgreen', s=100)
## line plot of equality
ax.plot([0,1], [0,1], color='k')
# set the labels for x, y, and title
ax.set_xlabel("Countries")
ax.set_ylabel("Wealth")
ax.set_title("Population-Lorenz Curve")
plt.show()
# save plot as png file
plt.savefig('population-lorenz.png', dpi = 200)
I am plotting several y values for one x value at a time using this method:
x = [0.3, 0.1, 0.4, 0.65, 0.85, 0.9, 0.125]
y = [1,2,3,4,5,6,7]
plt.figure()
for xe, ye in zip(x, y):
plt.scatter([xe] * len(ye), ye)
and i obtain:
However, I want to label each plot I obtain but i can't figure out how. Any help would be much appreciated.
Create a list containing the labels as strings:
labels = ["label1", "label2", ...]
and then rewrite the for loop to
for i in range(len(x)):
plt.scatter(x[i]*len(y), y[i], label=labels[i])
I am new to matplotlib and I am asking for your help to solve my little problem. I am sharing the graph below, here are the questions:
1- I want x-axis and y-axis replace
2- And most important for me is that errorbars should be horizontal (in graph below these are vertical).
Some errorbars in the graph is overlapping and I tried to avoid this problem using transform command. As I said before if I can manage the replacement of X and Y axis I would be happy.
Below I am sharing the code I wrote:
import ax as ax
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.transforms import Affine2D
y_values = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
p1 = [1, 0.77, 0.67, 0.85, 0.78, 1.05, 0.63]
p2 = [3, 2, 1.5, 1.20, 1.10, 1.40, 1.10]
x_err = [0.1, 0.2, 0.4, 0.5, 0.3, 0.2, 0.3]
y_err = [0.6, 0.2, 0.4, 0.5, 0.3, 0.2, 0.3]
fig, ax = plt.subplots()
trans1 = Affine2D().translate(-0.1, 0.0) + ax.transData
trans2 = Affine2D().translate(+0.1, 0.0) + ax.transData
er1 = ax.errorbar(y_values, p1, x_err, marker="o", linestyle="none", transform=trans1)
er2 = ax.errorbar(y_values, p2, y_err, marker="o", linestyle="none", transform=trans2)
errorbar plot
I'm having two lists x, y representing coordinates in 2D. For example x = [1,4,0.5,2,5,10,33,0.04] and y = [2,5,44,0.33,2,14,20,0.03]. x[i] and y[i] represent one point in 2D. Now I also have a list representing "heat" values for each (x,y) point, for example z = [0.77, 0.88, 0.65, 0.55, 0.89, 0.9, 0.8,0.95]. Of course x,y and z are much higher dimensional than the example.
Now I would like to plot a heat map in 2D where x and y represents the axis coordinates and z represents the color. How can this be done in python?
This code produces a heat map. With a few more data points, the plot starts looking pretty nice and I've found it to be very quick in general even for >100k points.
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
import math
x = [1,4,0.5,2,5,10,33,0.04]
y = [2,5,44,0.33,2,14,20,0.03]
z = [0.77, 0.88, 0.65, 0.55, 0.89, 0.9, 0.8, 0.95]
levels = [0.7, 0.75, 0.8, 0.85, 0.9]
plt.figure()
ax = plt.gca()
ax.set_aspect('equal')
CS = ax.tricontourf(x, y, z, levels, cmap=plt.get_cmap('jet'))
cbar = plt.colorbar(CS, ticks=np.sort(np.array(levels)),ax=ax, orientation='horizontal', shrink=.75, pad=.09, aspect=40,fraction=0.05)
cbar.ax.set_xticklabels(list(map(str,np.sort(np.array(levels))))) # horizontal colorbar
cbar.ax.tick_params(labelsize=8)
plt.title('Heat Map')
plt.xlabel('X Label')
plt.ylabel('Y Label')
plt.show()
Produces this image:
or if you're looking for a more gradual color change, change the tricontourf line to this:
CS = ax.tricontourf(x, y, z, np.linspace(min(levels),max(levels),256), cmap=cmap)
and then the plot will change to:
Based on this answer, you might want to do something like:
import numpy as np
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
xs0 = [1,4,0.5,2,5,10,33,0.04]
ys0 = [2,5,44,0.33,2,14,20,0.03]
zs0 = [0.77, 0.88, 0.65, 0.55, 0.89, 0.9, 0.8,0.95]
N = 30j
extent = (np.min(xs0),np.max(xs0),np.min(ys0),np.max(ys0))
xs,ys = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:N]
resampled = griddata(xs0, ys0, zs0, xs, ys, interp='linear')
plt.imshow(np.fliplr(resampled).T, extent=extent,interpolation='none')
plt.colorbar()
The example here might also help: http://matplotlib.org/examples/pylab_examples/griddata_demo.html
Stacked plotting in matplotlib with equal x data is as easy as
from matplotlib import pyplot as plt
x0 = [0.0, 0.5, 2.0]
y0 = [1.0, 1.5, 1.0]
# x1 = [0.0, 1.5, 2.0]
y1 = [1.0, 1.5, 1.0]
plt.stackplot(x0, (y0, y1))
plt.show()
Is it possible to stack two plots with different x data too?
It does not seem to be possible. If you look at the code for Matplotlib's stackplot, then this is the part that draws the stacked plot itself:
# Color between array i-1 and array i
for i in xrange(len(y) - 1):
color = axes._get_lines.get_next_color()
r.append(axes.fill_between(x, stack[i, :], stack[i + 1, :],
facecolor=color,
label= six.next(labels, None),
**kwargs))
So it will always use the same x for all stacks.
You could on the other hand create a new x array for the stacked plot, and include all values from all the different x arrays you have, and then calculate the missing y stack values using linear interpolation.
A possible solution using interpolation could look like this:
from matplotlib import pyplot as plt
def interp_nans(x, y):
is_nan = np.isnan(y)
res = y * 1.0
res[is_nan] = np.interp(x[is_nan], x[-is_nan], y[-is_nan])
return res
x = np.array([0.0, 0.5, 1.5, 2.0])
y0 = np.array([1.0, 1.5, np.nan, 1.0])
y1 = np.array([1.0, np.nan, 1.5, 1.0])
plt.stackplot(x, (interp_nans(x, y0), interp_nans(x, y1)))
plt.show()
But if interpolation can not be used in this case, then it would not work.