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)
Related
I'd like to plot curved lines of a specific arch like shape, below is how far I've gotten using specific values (these values need to be used) but it plots straight lines.
I'm also having trouble formatting the y axis the way I want. It's a log scale and I'd like it to go up to 1 (like in the ideal plot above). Some help would be great, thanks! =)
The reason why your line is not stretching on a log scale plot is because there are no points between the points that are on the top and on the bottom. log plot does not curve the lines, only place the points on a different scale, the line between them are still straight.
To change this, we add more points between dots. and the result will become curved.
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import ScalarFormatter
# Data for plotting
t = [0.0, 62.5, 125.0, 187.5, 250, 312.5, 375, 437.5, 500]
s = [0.1, 0.005, 0.1, 0.005, 0.1, 0.005, 0.1, 0.005, 0.1]
def extendlist(l):
master = []
for i in range(len(l)-1):
x = np.linspace(l[i], l[i+1], 50)
master.extend(x)
return master
t = extendlist(t)
s = extendlist(s)
fig, ax = plt.subplots()
ax.semilogy(t, s)
ax.set(xlabel='x axis', ylabel='y axis', title='Stuff')
plt.xlim((0,500))
plt.ylim((0.001, 1))
plt.show()
This will generate what you graphed on paper.
you can use interp1d
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import interp1d
t = [0.0, 62.5, 125.0, 187.5, 250, 312.5, 375, 437.5, 500]
s = [0.1, 0.005, 0.1, 0.005, 0.1, 0.005, 0.1, 0.005, 0.1]
tnew = np.linspace(0, 500, num=1001, endpoint=True)
f = interp1d(t, s)
plt.semilogy(tnew, f(tnew))
plt.ylim((0.001, 1))
plt.show()
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
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
I am trying to plot the phasors of the voltage across the resistor, capacitor, and inductor in an series R-L-C circuit. I have done all of the calculations and I can get a decent plot with just the normal ax.plot(theta,r,....).
I would like to make the phasor vectors look like arrows. I have been trying to use ax.arrow(0,0,theta,magnitude) but it looks like a line still. The gist to the code that I have written is here : GIST
My image that I create is
I tried to follow the example that I found on this list because it is very similar to what I want to accomplish, it produces the following image:
When I run their code on my computer I get
I am on Xubuntu 14.04 and running matplotlib 1.3.1. I do see that the example I am using was using matplotlib 0.99 in 2009.
Any help would be much appreciated.
Arrow sizes were too big, this:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
print "matplotlib.__version__ = ", matplotlib.__version__
print "matplotlib.get_backend() = ", matplotlib.get_backend()
# radar green, solid grid lines
plt.rc('grid', color='#316931', linewidth=1, linestyle='-')
plt.rc('xtick', labelsize=15)
plt.rc('ytick', labelsize=15)
# force square figure and square axes looks better for polar, IMO
width, height = matplotlib.rcParams['figure.figsize']
size = min(width, height)
# make a square figure
fig = plt.figure(figsize=(size, size))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, axisbg='#d5de9c')
r = np.arange(0, 3.0, 0.01)
theta = 2*np.pi*r
ax.plot(theta, r, color='#ee8d18', lw=3)
ax.set_rmax(2.0)
plt.grid(True)
ax.set_title("And there was much rejoicing!", fontsize=20)
#This is the line I added:
arr1 = plt.arrow(0, 0.5, 0, 1, alpha = 0.5, width = 0.015,
edgecolor = 'black', facecolor = 'green', lw = 2, zorder = 5)
# arrow at 45 degree
arr2 = plt.arrow(45/180.*np.pi, 0.5, 0, 1, alpha = 0.5, width = 0.015,
edgecolor = 'black', facecolor = 'green', lw = 2, zorder = 5)
plt.show()
Produces:
Better? :)
I have created a frequency time spectrogram plot seen below.
I want to edit the colour scale so that the higher frequencies shown from 20 seconds are more prominent. I think having smaller increments at the lower end of the colour scale (blues) would achieve this but am not sure how to do it. Any help would be great!
Here is what I have so far:
import numpy as np
import matplotlib.pyplot as plt
from obspy.core import read
from obspy.signal.tf_misfit import cwt
import pylab
tr = read("whole.sac")[0]
npts = tr.stats.npts
dt = tr.stats.delta
t = np.linspace(0, dt * npts, npts)
f_min = 1
f_max = 10
scalogram = cwt(tr.data, dt, 8, f_min, f_max)
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.1, 0.7, 0.60])
ax2 = fig.add_axes([0.1, 0.75, 0.75, 0.2])
ax3 = fig.add_axes([0.83, 0.1, 0.03, 0.6])
img = ax1.imshow(np.abs(scalogram)[-1::-1], extent=[t[0], t[-1], f_min, f_max],
aspect='auto', interpolation="nearest")
ax1.set_xlabel("Time after %s [s]" % tr.stats.starttime)
ax1.set_ylabel("Frequency [Hz]")
ax1.set_yscale('linear')
ax2.plot(t, tr.data, 'k')
pylab.xlim([30,72])
fig.colorbar(img, cax=ax3)
plt.show()
You could try other colormaps or make you own according to this recipe.
Or you may want to filter the data to set all values above a given threshold (e.g. 60) to the threshold value. This would use the entire range of the colormap on the range of interest. You can easily use np.clip() to do this.
So...
np.abs(scalogram)[-1::-1]
becomes
np.clip(np.abs(scalogram)[-1::-1], 0, 100)
to clip between 0 and 100.