Plotting graph using pylab - python-2.7

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:

Related

How to represent the data in x and y axis using matplotlib

Here in my program i want to create the month wise dates on x axis label and and another rs data i want to represent on the y axis.can you please help me how to mention my data in matplotlib.
Given below is my sample program:
import matplotlib.pyplot as plt
from matplotlib import style
# line 1 points
x1 = [1,2,3]
y1 = [2,4,1]
# plotting the line 1 points
plt.plot(x1, y1, 'g', label = "line 1",linewidth=10)
plt.title('Two lines on same graph!')
plt.xlabel('x - axis')
plt.ylabel('y - axis')
plt.legend()
plt.grid(True,color="k")
plt.show()
# xticks(np.arange(12), calendar.month_name[1:13], rotation=20)
i don't want to mention in between the values it is tacking the x and y values i want to mention like in given diagram.
After few edits and your comments. Is this more closer what you are looking for?
import matplotlib.pyplot as plt
import datetime
# line 1 points
val = [1,2,3,2,6]
cust = [2,4,1,6,2]
orders = [3,5,2,7,3]
col = [1,3,4,2,6]
# plotting the line 1 points
fig, ax = plt.subplots()
start_date = datetime.datetime(2019, 07, 01)
dates = []
# Dates based on the measurement count
# See: https://stackoverflow.com/questions/1060279/iterating-through-a-range-of-dates-in-python
for single_date in (start_date + datetime.timedelta(n) for n in range(len(val))):
dates.append(single_date.strftime('%Y-%m-%d'))
# Values
plt.plot(dates, val, '.',color='g', markersize=12)
plt.plot(dates, val, label='Values', color='g')
# Customers
plt.plot(dates, cust, '.',color='b', markersize=12)
plt.plot(dates, cust, label='Customers',color='b')
# Orders
plt.plot(dates, orders, '.',color='r', markersize=12)
plt.plot(dates, orders, label='Orders',color='r')
# Collection
plt.plot(dates, col, '.',color='black', markersize=12)
plt.plot(dates, col, label='Collection',color='black')
plt.title('Four lines on same graph!')
plt.tick_params(axis='x', rotation=20)
plt.xlabel('x - axis')
plt.ylabel('y - axis')
plt.grid(True,color="k")
plt.legend()
plt.show()

How to fit and plot a linear regression line in python?

I have a file contains x, y, and y-err and I simply want to fit a straight line to these data.
This is my original code which I'm plotting the data. based n this I want to fit the straight line:
import numpy as np
import matplotlib.pyplot as plt
#read the data file
Data = np.loadtxt('dmvals.dat')
MJD = Data[:,0]
DM = Data[:,1]
DM_err = Data[:,2]
font = {'family': 'serif',
'color': 'blue',
'weight': 'normal',
'size': 14,
}
plt.figure()
plt.xlabel('time[MJD]', fontdict=font)
plt.ylabel('DM[pc/cm^3]', fontdict=font)
plt.title('DM values', fontdict=font)
plt.errorbar(MJD, DM, DM_err,color='magenta')
plt.subplots_adjust(left=0.15 , hspace = 0.5)
plt.savefig('dm_variations_plot.png')
The easiest way is to use numpy.polyfit to fit a 1st degree polinomial:
p = numpy.polyfit(MJD, DM, deg=1)
p will be a list containing the intercept and the slope of the fit line
You can then plot the line on your data using
x = MJD
y = p[1] + p[0] * MJD
plt.plot(x, y, '--')

Iterate Pandas Series to create a new chart legend

After grouping etc. I get a Series like in the example below. I would like to show the average numbers for each bar. The code below shows only one entry (of course, as I have only one "legend"). Could anyone one suggest a smart way of showing these numbers?
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
import pandas
# create Series
dict_ = {"Business" : 104.04,"Economy":67.04, "Markets":58.56, "Companies":38.48}
s = pandas.Series(data=dict_)
# plot it
ax = s.plot(kind='bar', color='#43C6DB', stacked=True, figsize=(20, 10), legend=False)
plt.tick_params(axis='both', which='major', labelsize=14)
plt.xticks(rotation=30) #rotate labels
# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
#create new legend
legend = ['%s (%.1f a day)' %(i, row/7) for i, row in s.iteritems()]
# Put the legend to the right of the current axis
L = ax.legend(legend, loc='center left', bbox_to_anchor=(1, 0.5), fontsize=18)
plt.show()
The legend only has a single entry. This is a handle of a blue bar. Therefore even if you set the labels to a longer list, only the first element of that list is used as label for the existing handle.
The idea can be to duplicate the legend handle to have the same size as the labels
legend = ['%s (%.1f a day)' %(i, row/7) for i, row in s.iteritems()]
h,l = ax.get_legend_handles_labels()
L = ax.legend(handles = h*len(legend), labels=legend, loc='center left',
bbox_to_anchor=(1, 0.5), fontsize=18)

Make colorbar compatible with gradient bar plot values

I want to make the values I plot to be compatible with the colorbar values. How can I do this? See more details below.
y1, y2, y3 values are : [-1.7 -1.62 -1.53 -1.43 -1.32 -1.2 -1.09 -0.97 -0.85],
[-1.43 -1.28 -1.09 -0.88 -0.66 -0.44 -0.21 0.03 0.27], [-3.65 -3.58 -3.48 -3.38 -3.27 -3.16 -3.04 -2.92 -2.8 ]
import matplotlib.pyplot as plt
import numpy as np
#plot
fig = plt.figure(figsize=(9.6,6), dpi=300, linewidth=3.0)
ax = fig.add_subplot(311)
y1 = y.transpose() #y should be the first data I gave out in the beginning
gradient = [ y1,y1 ]
plt.imshow(gradient, aspect='auto', cmap=plt.get_cmap('hot'))
ax.set_xticklabels(data[list[1]])
ax2 = fig.add_subplot(312)
y2 = y.transpose() #y should be the second data I gave out in the beginning
gradient = [ y2,y2 ]
plt.imshow(gradient, aspect='auto', cmap=plt.get_cmap('hot'))
ax2.set_xticklabels(data[list[5]])
ax3 = fig.add_subplot(313)
y3 = y.transpose() #y should be the third data I gave out in the beginning
gradient = [ y3,y3 ]
plt.imshow(gradient, aspect='auto', cmap=plt.get_cmap('hot'))
ax3.set_xticklabels(data[list[9]])
sm = plt.cm.ScalarMappable(cmap=plt.get_cmap('hot'),norm=plt.Normalize(-6.39,9.29))
sm._A = []
plt.colorbar(sm,ax=[ax,ax2,ax3])
#fig.set_tight_layout(True) #how can I use this? If I use this it generates a warning and the plot overlaps
plt.savefig('CuxOxi.png',dpi=300,format='png', orientation='landscape')
As you can see from the graph, the colorbar ranges from -6.39 to 9.29. Each subplot ranges only a fraction of the complete colorbar range. How can I make for example -1.62 to -1.2 to have the color range as defined in the colorbar (which is mostly red)
In each plot, you can add the vmin and vmax options to the plt.imshow function in order to set the color scale min and max for that plot. You can define these to be the same for each plot so that they all have the same scale.
vmin = -6
vmax = 9
plt.imshow(gradient, aspect='auto', cmap=plt.get_cmap('hot'),vmin=vmin,vmax=vmax)

python, xlrd: Maniplulate spreadsheet data with xlrd function then graph the manipulated data

I am trying to extract data from an excel spreadsheet, then find a percent change between adjacent rows. The columns that I would like to do this manipulation on is column 1 and 4. I would like to then graph these percent changes in two different bar charts using subplots using column 0 as the x axis.
I am able to do everything except extract the data and formulate a percent change between adjacent rows. The formula for the percent change is Current/previous-1 or (r,0)/(r-1,0)-1. Below is my current script:
import xlrd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr
import matplotlib.dates as mdates
import datetime
from matplotlib import rc
rc('mathtext', default='regular')
file_location = "/Users/adampatel/Desktop/psw01.xls"
workbook = xlrd.open_workbook(file_location, on_demand = False)
worksheet = workbook.sheet_by_name('Data 1')
x = [worksheet.cell_value(i+1699, 0) for i in range(worksheet.nrows-1699)]
y1 = [worksheet.cell_value(i+1699, 1) for i in range(worksheet.nrows-1699)]
y2 = [worksheet.cell_value(i+1699, 4) for i in range(worksheet.nrows-1699)]
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212, sharex = ax1)
start_date = datetime.date(1899, 12, 30)
dates=[start_date + datetime.timedelta(xval) for xval in x]
ax1.xaxis.set_major_locator(mdates.MonthLocator((), bymonthday=1, interval=2))
ax1.xaxis.set_minor_locator(mdates.MonthLocator((), bymonthday=1, interval=1))
ax1.xaxis.set_major_formatter(mdates.DateFormatter("%b'%y"))
ly1 = ax1.bar(dates, y1, 0.9)
ly2 = ax2.bar(dates, y2, 0.9)
ax1.grid()
ax2.grid()
ax1.set_ylim(-3,3)
ax2.set_ylim(-3,3)
fig.text(0.5, 0.04, 'Inventory Weekly Percent Change', ha='center', va='center', size = '14')
fig.text(0.06, 0.5, 'Weekly Percent Change', ha='center', va='center', size = '14', rotation='vertical')
ax1.set_title('Oil', size = '12')
ax2.set_title('Gasoline', size = '12')
plt.savefig('Gasoline Inventories Weekly Percent Change.png', bbox_inches='tight', dpi=300)
plt.show()
Given list of values:
y1 = [1000,1010,950,1050,1100,1030]
Pure python solution:
Use the zip function to create tuples of the numerator and denominator. Then use list comprehension to get a list of the percent changes.
pct_chg = [1.0*num / den - 1 for num, den in zip(y1[1:], y1)]
Numpy solution:
Convert list to numpy array, then perform computation using array slices.
a1 = np.array(y1)
pct_chg = np.divide(a1[1:],a1[:-1])-1
Pandas package solution:
Convert list to Pandas series and use the built-in percent change function
s1 = pd.Series(y1)
pct_chg = s1.pct_change()
Now, pct_chg is a series too. You can get its values in a numpy array via pct_chg.values. Matplotlib should accept numpy arrays as containers in most cases.