DICT() and MATPLOTLIB? - python-2.7

I created a dictionary to match the feature importance of a Decision Tree in sklearn with the corresponding name of the feature in my df. Here the code below:
importances = clf.feature_importances_
feature_names = ['age','BP','chol','maxh',
'oldpeak','slope','vessels',
'sex_0.0','sex_1.0',
'pain_1.0','pain_2.0','pain_3.0','pain_4.0',
'bs_0.0','bs_1.0',
'ecg_0.0','ecg_1.0','ecg_2.0',
'ang_0.0','ang_1.0',
'thal_3.0','thal_6.0','thal_7.0']
CLF_sorted = dict(zip(feature_names, importances))
in output I obtained this:
{'BP': 0.053673644739136502,
'age': 0.014904980747733202,
'ang_0.0': 0.0,
'ang_1.0': 0.0,
'bs_0.0': 0.0,
'bs_1.0': 0.0,
'chol': 0.11125922817930389, ...}
as I expected. I have two question for you:
how could I create a bar plot where the x-axis represents the feature_names and the y-axis the corresponding importances?
if it is possible, how could I sort the bar plot in a descending way?

try this:
import pandas as pd
df = pd.DataFrame({'feature': feature_names , 'importance': importances})
df.sort_values('importance', ascending=False).set_index('feature').plot.bar(rot=0)
demo:
d ={'BP': 0.053673644739136502,
'age': 0.014904980747733202,
'ang_0.0': 0.0,
'ang_1.0': 0.0,
'bs_0.0': 0.0,
'bs_1.0': 0.0,
'chol': 0.11125922817930389}
df = pd.DataFrame({'feature': [x for x in d.keys()], 'importance': [x for x in d.values()]})
In [63]: import matplotlib as mpl
In [64]: mpl.style.use('ggplot')
In [65]: df.sort_values('importance', ascending=False).set_index('feature').plot.bar(rot=0)
Out[65]: <matplotlib.axes._subplots.AxesSubplot at 0x8c83748>

Related

Plotting graph using pylab

I am trying to plot a graph. It has a list contains action name (text) and another list which contains action's frequency (int).
I want to plot a connected graph. This is the code I've written:
xTicks=np.array(action)
x=np.array(count)
y=np.array(freq)
pl.xticks(x,xTicks)
pl.xticks(rotation=90)
pl.plot(x,y)
pl.show()
In the list xTicks, I have actions and in the list y, I have their frequencies .
With the above code, I am getting this graph:
Why am I getting extra spaces on x axis? It should be symmetric and the size of lists are 130-135 so how can I scroll it?
You need to set x to an evenly spaced list in order to get your x ticks to be evenly spaced. The following is an example with some made up data:
import matplotlib.pyplot as plt
import numpy as np
action = ["test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9"]
freq = [5,3,7,4,8,3,5,1,12]
y=np.array(freq)
xTicks=np.array(action)
x = np.arange(0,len(action),1) # evenly spaced list with the same length as "freq"
plt.plot(x,y)
plt.xticks(x, xTicks, rotation=90)
plt.show()
This produces the following plot:
Update:
A simple example of a slider is shown below. You will have to make changes to this in order to get it exactly how you want but it will be a start:
from matplotlib.widgets import Slider
freq = [5,3,7,4,8,3,5,1,12,5,3,7,4,8,3,5,1,12,5,3,7,4,8,3,5,1,12,4,9,1]
y=np.array(freq)
x = np.arange(0,len(freq),1) # evenly spaced list with the same length as "action"
fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)
l, = plt.plot(x, y, lw=2, color='red')
axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor="lightblue")
sfreq = Slider(axfreq, 'Slider', 0.1, 10, valinit=3)
def update(val):
l.set_xdata(val* x)
fig.canvas.draw_idle()
sfreq.on_changed(update)
plt.show()
This produces the following graph which has a slider:

Scipy to make the graph smoother

I try to make my graph smoother with scipy but result is a horizontal line.
Code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import spline
dd = [1.0, 0.7071067811865476, 0.5, 0.3535533905932738, 0.25, 0.1767766952966369]
y = range(0,6)
dd1 = np.array(dd)
y1 = np.array(y)
xsmooth = np.linspace (dd1.max(),dd1.min(),5)
ysmooth = spline (dd1,y1,xsmooth)
plt.plot(xsmooth ,ysmooth)
plt.show()
Thanks in advance
I think you may be mixing up x and y in your code.
If dd are your y-values and y are your x-values, you could perform a spline interpolation like so:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import spline
y = [1.0, 0.7071067811865476, 0.5, 0.3535533905932738, 0.25, 0.1767766952966369]
x = range(0,6)
y = np.array(y)
x = np.array(x)
xsmooth = np.linspace (x.min(),x.max(),20) # an x vector with more intermediate values
ysmooth = spline(x,y,xsmooth)
plt.plot(xsmooth ,ysmooth)
plt.plot(x,y,'o')
plt.show()

matplotlib subplot2grid doesn't display correctly

I'm using subplot2grid to display graphs. However, not all subplots are being displayed. Obviously it has to do with the if statement.
However, in my complete code I need those if statements because depending on some conditions plots have diffent formats. I want all 3 subplots to be displayed (one for each i). However, the first one is missing. How to display it correctly?
Here is the simplified code:
import matplotlib.pyplot as plt
fig=plt.figure()
for i in xrange(0,3):
if i==1:
ax=plt.subplot2grid((3,1),(i,0))
ax.plot([1,2],[1,2])
fig.autofmt_xdate()
else:
ax=plt.subplot2grid((3,1),(i,0), rowspan=2)
ax.plot([1,2],[1,2])
fig.autofmt_xdate()
plt.show()
I would just use the gridspec module from matplotlib. Then you can set the width/height ratios directly.
Then you can do something like this:
import numpy
from matplotlib import gridspec
import matplotlib.pyplot as plt
def do_plot_1(ax):
ax.plot([0.25, 0.5, 0.75], [0.25, 0.5, 0.75], 'k-')
def do_plot_2(ax):
ax.plot([0.25, 0.5, 0.75], [0.25, 0.5, 0.75], 'g--')
fig = plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(nrows=3, ncols=1, height_ratios=[2, 1, 2])
for n in range(3):
ax = fig.add_subplot(gs[n])
if n == 1:
do_plot_1(ax)
else:
do_plot_2(ax)
fig.tight_layout()
To use plt.subplot2grid, you'd need to effectively do something like this:
fig = plt.figure(figsize=(6, 4))
ax1 = plt.subplot2grid((5,1), (0, 0), rowspan=2)
ax2 = plt.subplot2grid((5,1), (2, 0), rowspan=1)
ax3 = plt.subplot2grid((5,1), (3, 0), rowspan=2)
Since you have two axes with a rowspan=2, your grid needs to be 2+1+2 = 5 blocks tall.

How to add a time control panel to a FuncAnimation from matplotlib

I am currently using matplotlib.animation.FuncAnimation() to display an animation of my work, on a figure.
It is working very well, and I understand the arguments I am using ( interval, time range , ...) However, I was wondering if there was a way to implement (maybe directly to the figure) a panel containing the animation, a scroll-bar or whatever, which allows me to :
Move forward or backwards quickly to the time zone of interest.
Show at what point of the animation I am ( 10%, then 20%,...).
Basically, is a way to control the animation in python on the figure like the way I would control it as a video file played by a video player?
If needed, this is what looks like the code for this animation :
def init():
im1.set_data(XYslice[0, :, :])
im2.set_data(XZslice[0, Nplans/2:, :])
return([im1, im2])
def animate(t):
im1.set_data(XYslice[t, :, :])
im2.set_data(XZslice[t, Nplans/2:, :])
return [im1, im2]
anim = animation.FuncAnimation(fig, animate, np.arange(Ntime), interval=200,
blit=True, init_func=init, repeat=True)
What you are talking about is a GUI. The simplest example uses the matplotlib inbuilt widgets:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from matplotlib.widgets import Slider, Button
#Setup figure and data
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
delta = 0.5
t = np.arange(0.0, 100.0, 0.1)
x = np.arange(-3.0, 4.001, delta)
y = np.arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = (Z1 - Z2) * 5.
cmap = plt.cm.rainbow
im = ax.pcolormesh(X, Y, Z, cmap=cmap)
fig.colorbar(im)
axcolor = 'lightgoldenrodyellow'
axtime = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
stime = Slider(axtime, 'Time', 0.0, 100.0, valinit=50.0)
#Routines to reset and update sliding bar
def reset(event):
stime.reset()
def update(val):
time = stime.val/10.
Z = (Z1 - Z2) * time
im.set_array(Z.ravel())
fig.canvas.draw()
#Bind sliding bar and reset button
stime.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
button.on_clicked(reset)
plt.show()
This should be a start. If you want it to look better (and add more functionality) then you need to go to a GUI framework like wxpython, check out this example.
An example which is more inline with your data-structure would go as follows:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from matplotlib.widgets import Slider, Button
#Setup figure and data
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
delta = 0.5
t = np.linspace(0.0, 100.0, 256)
x = np.linspace(-4.0, 4.001, 512)
y = np.linspace(-4.0, 4.001, 512)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
XZslice = np.zeros((256,512,512))
for i in range(t.shape[0]):
XZslice[i,:,:] = (Z1 - Z2) * t[i]/10.
cmap = plt.cm.rainbow
im = ax.pcolormesh(XZslice[128,:,:], cmap=cmap)
fig.colorbar(im)
axcolor = 'lightgoldenrodyellow'
axtime = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
stime = Slider(axtime, 'Time', 0.0, 100.0, valinit=50.0)
#Routines to reset and update sliding bar
def reset(event):
stime.reset()
def update(val):
time = int(stime.val/100.* 256)
im.set_array(XZslice[time,:,:].ravel())
fig.canvas.draw()
#Bind sliding bar and reset button
stime.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
button.on_clicked(reset)
plt.show()

print all the values of a group of objects without iterating through it

I want to print the values of the group of objects that return from the database.
I have tried like the following,
Products = productBll.listProduct(params)
print Products.__dict__
it will display like the following,
{'_result_cache': [Product: Product object, Product: Product object]}
But when i am doing like this ,
for prd in Products:
print prd.__dict__
it showing all the contents in the Products objects
{'product_price': 0.0, 'right_side_min_depth': 0.0, 'short_description': u'', 'left_side_min_depth': 0.0, 'max_depth': 0.0, 'height_scale': 2.0, 'left_side_max_depth': 0.0, 'is_hinges': u'No', 'max_height': 1.04}
{'product_price': 0.0, 'right_side_min_depth': 0.0, 'short_description': u'', 'left_side_min_depth': 0.0, 'max_depth': 1000.0, 'height_scale': 1000.0, 'left_side_max_depth': 0.0, 'is_hinges': u'No', 'max_height': 1000.0}
But i want the above result without using the for loop.
Is there any way to do it by one line of code?
If all you're looking for is a one-liner, here it is:
Products = productBll.listProduct(params)
print [prd.__dict__ for prd in Products]
You can try using values(). Assuming your model is Products you can do
Product.objects.filter(your_filter_criteria).values()
this will give you list of dict per item selected.