Related
I'm plotting a graph and the x-axis label is not visible in the graph.
I have tried to solve it by adding the
ax.xaxis.labelpad = -10 # Adjust x-axis label position
Instead the x-label will overlap the ticker label
How can this be adjusted to show both x-axis label and x-ticker labels within the plot figure?
Full Code to replicate graph:
#################################
### Modules imported used ###
#################################
import pandas as pd
import numpy as np
from datetime import datetime
from datetime import date
import time
import matplotlib.pyplot as plt
import matplotlib
import matplotlib.dates as mdates
# file_path_setup = 'G:/Stocks/PowerPivotApps/Price download/'
# Performance_History = pd.read_csv(file_path_setup + 'Performance.txt', dtype=str, sep=',')
# Portfolio = Performance_History.loc[Performance_History['ExecutionType'] == 'All Portfolios']
# Portfolio = Performance_History.loc[Performance_History['ExecutionType'] == 'Selected Portfolios'] # remove "# set minimum level for performance time"
#Portfolios_Nr_of_Stocks = Portfolio['NrOfStocks']
#Portfolio_Performance_Time = Portfolio['PerformanceTime']
#Portfolio_Date = Portfolio['Date']
Portfolio_Date = ['2020-08-31','2020-09-01','2020-09-02','2020-09-02','2020-09-03','2020-09-04','2020-09-07','2020-09-08','2020-09-09','2020-09-09','2020-09-10','2020-09-11','2020-09-14','2020-09-15','2020-09-16','2020-09-17','2020-09-18','2020-09-21','2020-09-22','2020-09-22','2020-09-23','2020-09-24','2020-09-25','2020-09-28','2020-09-29','2020-09-30','2020-10-01','2020-10-02','2020-10-05','2020-10-06','2020-10-07','2020-10-08','2020-10-08','2020-10-09','2020-10-12','2020-10-13','2020-10-14','2020-10-15','2020-10-16']
Portfolio_Performance_Time =['00:11:11','00:11:07','00:11:16','00:10:42','00:10:54','00:10:46','00:10:27','00:11:23','00:11:35','00:10:23','00:10:51','00:41:22','00:11:05','00:11:15','00:10:50','00:10:41','00:19:47','00:10:43','00:10:48','00:11:12','00:11:05','00:10:45','00:11:02','00:10:57','00:11:01','00:15:17','00:14:33','00:18:49','00:14:28','00:20:45','00:14:29','00:14:45','00:17:52','00:14:37','00:14:08','00:15:05','00:14:46','00:14:39','00:14:40']
Portfolios_Nr_of_Stocks = ['621','619','617','619','622','622','622','621','622','622','622','613','622','621','621','607','621','622','621','622','620','620','622','620','620','680','679','680','681','488','681','681','680','678','678','676','678','676','676']
# Convert To integer
numberofstocks = [int(stock) for stock in Portfolios_Nr_of_Stocks]
# Convert to time
def get_sec(time_str):
"""Get Seconds from time."""
h, m, s = time_str.split(':')
return int(h) * 3600 + int(m) * 60 + int(s)
PerformanceTime = [get_sec(t) for t in Portfolio_Performance_Time]
# print(type(numberofstocks)) # print type
# convert to date series
date_portfolio = [datetime.strptime(d, '%Y-%m-%d') for d in Portfolio_Date]
# https://matplotlib.org/gallery/api/two_scales.html
# https://cmdlinetips.com/2019/10/how-to-make-a-plot-with-two-different-y-axis-in-python-with-matplotlib/
# create figure and axis objects with subplots()
fig,ax = plt.subplots(figsize=(12, 8)) # figsize -> size of the plot window
# make a plot
ax.plot(date_portfolio, PerformanceTime, color="red", marker="x")
# set x-axis label
ax.set_xlabel("Date", fontsize=14)
# set y-axis label
ax.set_ylabel("Performance Time",color="red",fontsize=14)
# set title
ax.set_title("Execution History",fontsize=20, loc="center", pad=10)
# format y-axis label to hh:mm:ss
formatter_yx1 = matplotlib.ticker.FuncFormatter(lambda s, x: time.strftime('%H:%M:%S', time.gmtime(s)))
ax.yaxis.set_major_formatter(formatter_yx1)
# rotate x-axis lables and adjust size
plt.xticks(rotation=90, ha='right')
# plt.xticks(rotation=90, ha='right', fontsize='x-small') # Small font text
# set minimum level for performance time, y-axis 1
ax.set_ylim([min(PerformanceTime)-100,25*60]) # -100 -> set minimum. 25*60 -> Set maximum
# twin object for two different y-axis on the sample plot
ax2=ax.twinx()
# make a plot with different y-axis using second axis object
ax2.plot(date_portfolio, numberofstocks,color="blue",marker="o")
# ax2.set_ylim([620, 680])
ax2.set_ylabel("Nr Of Stocks",color="blue",fontsize=14)
# set minimum level for performance time, y-axis 2
ax2.set_ylim([600, max(numberofstocks)+10]) # -100 -> set minimum. 25*60 -> Set maximum
# set date interval
ax.xaxis.set_major_locator(mdates.DayLocator(interval=7)) # max interval
ax.xaxis.set_minor_locator(mdates.DayLocator(interval=1)) # minimum interval
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) # set date format
ax.xaxis.labelpad = -10 # Adjust x-axis label position
# Plot graph
plt.show()
You could use "Tight Layout" function in matplotlib to solve the issue.
Add the line before you plot the graph, where h_pad will adjust the height, w_pad will adjust the width.
# Adjust x-axis margins
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=5.0)
And remove this part:
ax.xaxis.labelpad = -10 # Adjust x-axis label position
Result:
I have date in one column and time in another which I retrieved from database through pandas read_sql. The dataframe looks like below (there are 30 -40 rows in my daaframe). I want to plot them in a time series graph. If I want I should be in a position to convert that to Histogram as well.
COB CALV14
1 2019-10-04 07:04
2 2019-10-04 05:03
3 2019-10-03 16:03
4 2019-10-03 05:15
First I got different errors - like not numeric field to plot etc. After searching a lot,the closest post I could find is : Matplotlib date on y axis
I followed and got some result - However the problem is:
I have to follow number of steps (convert to str then list and then to matplot lib datetime format) before I can plot them. (Please refer the code I am using) There must be a smarter and more precise way to do this.
This does not show the time beside the axis the way they exactly appear in the data frame. (eg it should show 07:03, 05:04 etc)
New to python - will appreciate any help on this.
Code
ob_frame['COB'] = ob_frame.COB.astype(str)
ob_frame['CALV14'] = ob_frame.CALV14.astype(str)
date = ob_frame.COB.tolist()
time = ob_frame.CALV14.tolist()
y = mdates.datestr2num(date)
x = mdates.datestr2num(time)
fig, ax = plt.subplots(figsize=(9,9))
ax.plot(x, y)
ax.yaxis_date()
ax.xaxis_date()
fig.autofmt_xdate()
plt.show()
I found the answer to it.I did not need to convert the data retrieved from DB to string type. Rest of the issue I was thought to be getting for not using the right formatting for the tick labels. Here goes the complete code - Posting in case this will help anyone.
In this code I have altered Y and X axis : i:e I plotted dates in x axis and time in Y axis as it looked better.
###### Import all the libraries and modules needed ######
import IN_OUT_SQL as IS ## IN_OUT_SQL.py is the file where the SQL is stored
import cx_Oracle as co
import numpy as np
import Credential as cd # Credentia.py is the File Where you store the DB credentials
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib import dates as mdates
%matplotlib inline
###### Connect to DB, make the dataframe and prepare the x and y values to be plotted ######
def extract_data(query):
'''
This function takes the given query as input, Connects to the Databse, executes the SQL and
returns the result in a dataframe.
'''
cred = cd.POLN_CONSTR #POLN_CONSTR in the credential file stores the credential in '''USERNAME/PASSWORD#DB_NAME''' format
conn = co.connect(cred)
frame = pd.read_sql(query, con = conn)
return frame
query = IS.OUT_SQL
ob_frame = extract_data(query)
ob_frame.dropna(inplace = True) # Drop the rows with NaN values for all the columns
x = mdates.datestr2num(ob_frame['COB']) #COB is date in "01-MAR-2020" format- convert it to madates type
y = mdates.datestr2num(ob_frame['CALV14']) #CALV14 is time in "21:04" Format- convert it to madates type
###### Make the Timeseries plot of delivery time in y axis vs delivery date in x axis ######
fig, ax = plt.subplots(figsize=(15,8))
ax.clear() # Clear the axes
ax.plot(x, y, 'bo-', color = 'dodgerblue') #Plot the data
##Below two lines are to draw a horizontal line for 05 AM and 07 AM position
plt.axhline(y = mdates.date2num (pd.to_datetime('07:00')), color = 'red', linestyle = '--', linewidth = 0.75)
plt.axhline(y = mdates.date2num (pd.to_datetime('05:00')), color = 'green', linestyle = '--', linewidth = 0.75)
plt.xticks(x,rotation = '75')
ax.yaxis_date()
ax.xaxis_date()
#Below 6 lines are about setting the format with which I want my xor y ticks and their labels to be displayed
yfmt = mdates.DateFormatter('%H:%M')
xfmt = mdates.DateFormatter('%d-%b-%y')
ax.yaxis.set_major_formatter(yfmt)
ax.xaxis.set_major_formatter(xfmt)
ax.yaxis.set_major_locator(mdates.HourLocator(interval=1)) # Every 1 Hour
ax.xaxis.set_major_locator(mdates.DayLocator(interval=1)) # Every 1 Day
####### Name the x,y labels, titles and beautify the plot #######
plt.style.use('bmh')
plt.xlabel('\nCOB Dates')
plt.ylabel('Time of Delivery (GMT/BST as applicable)\n')
plt.title(" Data readiness time against COBs (Last 3 months)\n")
plt.rcParams["font.size"] = "12" #Change the font
# plt.rcParams["font.family"] = "Times New Roman" # Set the font type if needed
plt.tick_params(left = False, bottom = False, labelsize = 10) #Remove ticks, make tick labelsize 10
plt.box(False)
plt.show()
Output:
I'm trying to make this plot, similar to the example figure attached. I also attached the example data.
Example data
I want to plot one column (BLC 73.61, FCC 68.5, BSL 40.69) versus time, that are in the index of the data frame, and together with the datetime xticks and want to show the correspondent MLT (Magnetic local time) value, that are in the fourth column of the database.
Here is an code that I'm trying to do:
The picture show an example of I want to do. The x ticks labels showing in one line the value of uT hour in datetime format and in a second or third line show the correspondent value of the MLT
# read the data
data = pd.read_csv('dados.csv', index_col=[0])
#plotting
fig = plt.figure(figsize=(10, 5)) #
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny() # second x-axis
ax1.plot(data.index,data['BLC 73.61'])
ax2.xaxis.set_ticks_position("bottom")
ax2.xaxis.set_label_position("bottom")
ax2.spines["bottom"].set_position(("axes", -0.2))
ax2.spines['bottom'].set_color('none')
majorLocator = MultipleLocator(1)
minorLocator = MultipleLocator(1)
ax1.xaxis.set_major_locator(majorLocator)
ax1.xaxis.set_minor_locator(minorLocator)
ax1.xaxis.set_major_locator(majorLocator)
ax1.xaxis.set_minor_locator(minorLocator)
ax1.xaxis.set_minor_formatter(dates.DateFormatter('%H:%M'))
ax1.xaxis.set_minor_locator(mdates.MinuteLocator(interval=30))
ax1.xaxis.set_major_formatter(dates.DateFormatter('%H:%M\n%b %d, %Y'))
ax1.xaxis.set_major_locator(mdates.HourLocator(interval=30))
ax2.set_xticklabels(data['MLT'].values)
# ax2.xaxis.set_minor_formatter(dates.DateFormatter('%H:%M'))
# ax2.xaxis.set_minor_locator(mdates.MinuteLocator(interval=30))
# ax2.xaxis.set_major_formatter(dates.DateFormatter('%H:%M\n%b %d, %Y'))
# ax2.xaxis.set_major_locator(mdates.HourLocator(interval=30))
a=ax2.get_xticks().tolist()
And here is what i'm getting as result:
Result
I just found one solution for this.
I've created a function defining how I wanted the ticks and used the FuncFormatter module.
def format_func(value, tick_number):
hora = mdates.num2date(value)
teste = mlt['BLC 73.61'][hora]
return ('%d:%d \n %0.1f' % (hora.hour, hora.minute,teste))
def format_func2(value, tick_number):
# find the first value
if tick_number == 0:
return ('hh:mm \n MLT ')
else:
return (' ')
First convert the timestamp values to numbers:
xx = [mdates.date2num(i) for i in ada[ini:end].index]
and plot
fig = plt.figure(figsize=(10, 5)) #
ax1 = fig.add_subplot(111)
ax1.plot(xx,ada['BLC 73.61'][ini:end])
# set the major locator ion the month values
ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=5))
# use the format difeined in format_func2
ax1.xaxis.set_major_formatter(plt.FuncFormatter(format_func2))
ax1.xaxis.set_minor_locator(mdates.HourLocator(interval=2))
ax1.xaxis.set_minor_formatter(plt.FuncFormatter(format_func))
I wanted to plot a data which has datetime values for the x axis and another set of values as y. As an example, I will use the example from matplotlib where y in this case are stock prices. Here is the code for that.
import matplotlib.pyplot as plt
from matplotlib.finance import quotes_historical_yahoo_ochl
from matplotlib.dates import YearLocator, MonthLocator, DateFormatter
import datetime
date1 = datetime.date(1995, 1, 1)
date2 = datetime.date(2004, 4, 12)
years = YearLocator() # every year
months = MonthLocator() # every month
yearsFmt = DateFormatter('%Y')
quotes = quotes_historical_yahoo_ochl('INTC', date1, date2)
if len(quotes) == 0:
raise SystemExit
dates = [q[0] for q in quotes]
opens = [q[1] for q in quotes]
fig, ax = plt.subplots()
ax.plot_date(dates, opens, '-')
# format the ticks
ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yearsFmt)
ax.xaxis.set_minor_locator(months)
ax.autoscale_view()
# format the coords message box
def price(x):
return '$%1.2f' % x
ax.fmt_xdata = DateFormatter('%Y-%m-%d')
ax.fmt_ydata = price
ax.grid(True)
fig.autofmt_xdate()
plt.show()
Now, what I want to do is color each value in the graph based on some criterion. For simplicity's sake, let's say that the criterion in the case of the example is based on the year. That is, prices belonging to the same year will be colored the same. How would I do that? Thanks!
You can use numpy arrays with masks over the range you want (in this case a year). In order to use the inbuilt YearLocator function from your example, you need to plot the graph first and set the ticks, then remove and replace with the range per year, from your example,
import matplotlib.pyplot as plt
from matplotlib.finance import quotes_historical_yahoo_ochl
from matplotlib.dates import YearLocator, MonthLocator, DateFormatter
import datetime
import numpy
date1 = datetime.date(1995, 1, 1)
date2 = datetime.date(2004, 4, 12)
years = YearLocator() # every year
months = MonthLocator() # every month
yearsFmt = DateFormatter('%Y')
quotes = quotes_historical_yahoo_ochl('INTC', date1, date2)
if len(quotes) == 0:
raise SystemExit
dates = np.array([q[0] for q in quotes])
opens = np.array([q[1] for q in quotes])
fig, ax = plt.subplots()
l = ax.plot_date(dates, opens, '-')
# format the ticks
ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yearsFmt)
ax.xaxis.set_minor_locator(months)
ax.autoscale_view()
l[0].remove()
py = years()[0]
for year in years()[1:]:
mask = (py < dates) & (dates < year)
ax.plot_date(dates[mask], opens[mask], '-')
py = year
# format the coords message box
def price(x):
return '$%1.2f' % x
ax.fmt_xdata = DateFormatter('%Y-%m-%d')
ax.fmt_ydata = price
ax.grid(True)
fig.autofmt_xdate()
plt.show()
which gives,
The way I typically do this is by using a for loop to plot different sections of the data, coloring each section as I go. In your example, this section:
fig, ax = plt.subplots()
ax.plot_date(dates, opens, '-')
becomes:
# import the colormaps
from maplotlib import cm
fig, ax = plt.subplots()
for y in years:
y_indices = [i for i in range(len(dates)) if dates[i].year==y]
# subset the data, there are better ways to do this
sub_dates = [dates[i] for i in y_indices]
sub_opens = [opens[i] for i in y_indices]
# plot each section of data, using a colormap to change the color for
# each iteration.
ax.plot_date(sub_dates, sub_opens, '-', linecolor=cm.spring((y-2000)/10.0)
This is my first attempt using Matplotlib and I am in need of some guidance. I am trying to generate plot with 4 y-axes, two on the left and two on the right with shared x axis. Here's my dataset on shared dropbox folder
import pandas as pd
%matplotlib inline
url ='http://dropproxy.com/f/D34'
df= pd.read_csv(url, index_col=0, parse_dates=[0])
df.plot()
This is what the simple pandas plot looks like:
I would like to plot this similar to the example below, with TMAX and TMIN on primary y-axis (on same scale).
My attempt:
There's one example I found on the the matplotlib listserv..I am trying to adapt it to my data but something is not working right...Here's the script.
# multiple_yaxes_with_spines.py
# This is a template Python program for creating plots (line graphs) with 2, 3,
# or 4 y-axes. (A template program is one that you can readily modify to meet
# your needs). Almost all user-modifiable code is in Section 2. For most
# purposes, it should not be necessary to modify anything else.
# Dr. Phillip M. Feldman, 27 Oct, 2009
# Acknowledgment: This program is based on code written by Jae-Joon Lee,
# URL= http://matplotlib.svn.sourceforge.net/viewvc/matplotlib/trunk/matplotlib/
# examples/pylab_examples/multiple_yaxis_with_spines.py?revision=7908&view=markup
# Section 1: Import modules, define functions, and allocate storage.
import matplotlib.pyplot as plt
from numpy import *
def make_patch_spines_invisible(ax):
ax.set_frame_on(True)
ax.patch.set_visible(False)
for sp in ax.spines.itervalues():
sp.set_visible(False)
def make_spine_invisible(ax, direction):
if direction in ["right", "left"]:
ax.yaxis.set_ticks_position(direction)
ax.yaxis.set_label_position(direction)
elif direction in ["top", "bottom"]:
ax.xaxis.set_ticks_position(direction)
ax.xaxis.set_label_position(direction)
else:
raise ValueError("Unknown Direction : %s" % (direction,))
ax.spines[direction].set_visible(True)
# Create list to store dependent variable data:
y= [0, 0, 0, 0, 0]
# Section 2: Define names of variables and the data to be plotted.
# `labels` stores the names of the independent and dependent variables). The
# first (zeroth) item in the list is the x-axis label; remaining labels are the
# first y-axis label, second y-axis label, and so on. There must be at least
# two dependent variables and not more than four.
labels= ['Date', 'Maximum Temperature', 'Solar Radiation',
'Rainfall', 'Minimum Temperature']
# Plug in your data here, or code equations to generate the data if you wish to
# plot mathematical functions. x stores values of the independent variable;
# y[1], y[2], ... store values of the dependent variable. (y[0] is not used).
# All of these objects should be NumPy arrays.
# If you are plotting mathematical functions, you will probably want an array of
# uniformly spaced values of x; such an array can be created using the
# `linspace` function. For example, to define x as an array of 51 values
# uniformly spaced between 0 and 2, use the following command:
# x= linspace(0., 2., 51)
# Here is an example of 6 experimentally measured y1-values:
# y[1]= array( [3, 2.5, 7.3e4, 4, 8, 3] )
# Note that the above statement requires both parentheses and square brackets.
# With a bit of work, one could make this program read the data from a text file
# or Excel worksheet.
# Independent variable:
x = df.index
# First dependent variable:
y[1]= df['TMAX']
# Second dependent variable:
y[2]= df['RAD']
y[3]= df['RAIN']
y[4]= df['TMIN']
# Set line colors here; each color can be specified using a single-letter color
# identifier ('b'= blue, 'r'= red, 'g'= green, 'k'= black, 'y'= yellow,
# 'm'= magenta, 'y'= yellow), an RGB tuple, or almost any standard English color
# name written without spaces, e.g., 'darkred'. The first element of this list
# is not used.
colors= [' ', '#C82121', '#E48E3C', '#4F88BE', '#CF5ADC']
# Set the line width here. linewidth=2 is recommended.
linewidth= 2
# Section 3: Generate the plot.
N_dependents= len(labels) - 1
if N_dependents > 4: raise Exception, \
'This code currently handles a maximum of four independent variables.'
# Open a new figure window, setting the size to 10-by-7 inches and the facecolor
# to white:
fig= plt.figure(figsize=(16,9), dpi=120, facecolor=[1,1,1])
host= fig.add_subplot(111)
host.set_xlabel(labels[0])
# Use twinx() to create extra axes for all dependent variables except the first
# (we get the first as part of the host axes). The first element of y_axis is
# not used.
y_axis= (N_dependents+2) * [0]
y_axis[1]= host
for i in range(2,len(labels)+1): y_axis[i]= host.twinx()
if N_dependents >= 3:
# The following statement positions the third y-axis to the right of the
# frame, with the space between the frame and the axis controlled by the
# numerical argument to set_position; this value should be between 1.10 and
# 1.2.
y_axis[3].spines["right"].set_position(("axes", 1.15))
make_patch_spines_invisible(y_axis[3])
make_spine_invisible(y_axis[3], "right")
plt.subplots_adjust(left=0.0, right=0.8)
if N_dependents >= 4:
# The following statement positions the fourth y-axis to the left of the
# frame, with the space between the frame and the axis controlled by the
# numerical argument to set_position; this value should be between 1.10 and
# 1.2.
y_axis[4].spines["left"].set_position(("axes", -0.15))
make_patch_spines_invisible(y_axis[4])
make_spine_invisible(y_axis[4], "left")
plt.subplots_adjust(left=0.2, right=0.8)
p= (N_dependents+1) * [0]
# Plot the curves:
for i in range(1,N_dependents+1):
p[i], = y_axis[i].plot(x, y[i], colors[i],
linewidth=linewidth, label=labels[i])
# Set axis limits. Use ceil() to force upper y-axis limits to be round numbers.
host.set_xlim(x.min(), x.max())
host.set_xlabel(labels[0], size=16)
for i in range(1,N_dependents+1):
y_axis[i].set_ylim(0.0, ceil(y[i].max()))
y_axis[i].set_ylabel(labels[i], size=16)
y_axis[i].yaxis.label.set_color(colors[i])
for sp in y_axis[i].spines.itervalues():
sp.set_color(colors[i])
for obj in y_axis[i].yaxis.get_ticklines():
# `obj` is a matplotlib.lines.Line2D instance
obj.set_color(colors[i])
obj.set_markeredgewidth(3)
for obj in y_axis[i].yaxis.get_ticklabels():
obj.set_color(colors[i])
obj.set_size(12)
obj.set_weight(600)
# To enable the legend, uncomment the following two lines:
lines= p[1:]
host.legend(lines, [l.get_label() for l in lines])
plt.draw(); plt.show()
And the output
How can I put the scale on max and min temp on a same scale? Also, how can I get rid of second y-axis with black color, scaled from 0 to 10?
Is there a simpler way to achieve this?
How can I put the scale on max and min temp on a same scale?
Plot them in the same axes.
Also, how can I get rid of second y-axis with black color, scaled from 0 to 10?
Do not create that axes.
You want to plot four variables, two of them can go in the same subplot so you only need three subplots. But you are creating five of them?
Step by step
Keep in mind: different y scales <-> different subplots sharing x-axis.
Two variables with a common scale (left), two variables with independent scales (right).
Create the primary subplot, let's call it ax1. Plot everything you want in it, in this case TMIN and TMAX as stated in your question.
Create a twin subplot sharing x axis twinx(ax=ax1). Plot the third variable, say RAIN.
Create another twin subplot twinx(ax=ax1). Plot the fourth variable 'RAD'.
Adjust colors, labels, spine positions... to your heart's content.
Unsolicited advice: do not try to fix code you don't understand.
Variation of the original plot showing how you can plot variables on multiple axes
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
url ='http://dropproxy.com/f/D34'
df= pd.read_csv(url, index_col=0, parse_dates=[0])
fig = plt.figure()
ax = fig.add_subplot(111) # Primary y
ax2 = ax.twinx() # Secondary y
# Plot variables
ax.plot(df.index, df['TMAX'], color='red')
ax.plot(df.index, df['TMIN'], color='green')
ax2.plot(df.index, df['RAIN'], color='orange')
ax2.plot(df.index, df['RAD'], color='yellow')
# Custom ylimit
ax.set_ylim(0,50)
# Custom x axis date formats
import matplotlib.dates as mdates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
I modified #bishopo's suggestions to generate what I wanted, however, the plot still needs some tweaking with font sizes for axes label.
Here's what I have done so far.
import pandas as pd
%matplotlib inline
url ='http://dropproxy.com/f/D34'
df= pd.read_csv(url, index_col=0, parse_dates=[0])
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt
if 1:
# Set the figure size, dpi, and background color
fig = plt.figure(1, (16,9),dpi =300, facecolor = 'W',edgecolor ='k')
# Update the tick label size to 12
plt.rcParams.update({'font.size': 12})
host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)
par1 = host.twinx()
par2 = host.twinx()
par3 = host.twinx()
offset = 60
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
new_fixed_axis1 = host.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
axes=par2,
offset=(offset, 0))
par3.axis["left"] = new_fixed_axis1(loc="left",
axes=par3,
offset=(-offset, 0))
par2.axis["right"].toggle(all=True)
par3.axis["left"].toggle(all=True)
par3.axis["right"].set_visible(False)
# Set limit on both y-axes
host.set_ylim(-30, 50)
par3.set_ylim(-30,50)
host.set_xlabel("Date")
host.set_ylabel("Minimum Temperature ($^\circ$C)")
par1.set_ylabel("Solar Radiation (W$m^{-2}$)")
par2.set_ylabel("Rainfall (mm)")
par3.set_ylabel('Maximum Temperature ($^\circ$C)')
p1, = host.plot(df.index,df['TMIN'], 'm,')
p2, = par1.plot(df.index, df.RAD, color ='#EF9600', linestyle ='--')
p3, = par2.plot(df.index, df.RAIN, '#09BEEF')
p4, = par3.plot(df.index, df['TMAX'], '#FF8284')
par1.set_ylim(0, 36)
par2.set_ylim(0, 360)
host.legend()
host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color(p2.get_color())
par2.axis["right"].label.set_color(p3.get_color())
par3.axis["left"].label.set_color(p4.get_color())
tkw = dict(size=5, width=1.5)
host.tick_params(axis='y', colors=p1.get_color(), **tkw)
par1.tick_params(axis='y', colors=p2.get_color(), **tkw)
par2.tick_params(axis='y', colors=p3.get_color(), **tkw)
par3.tick_params(axis='y', colors=p4.get_color(), **tkw)
host.tick_params(axis='x', **tkw)
par1.axis["right"].label.set_fontsize(16)
par2.axis["right"].label.set_fontsize(16)
par3.axis["left"].label.set_fontsize(16)
host.axis["bottom"].label.set_fontsize(16)
host.axis["left"].label.set_fontsize(16)
plt.figtext(.5,.92,'Weather Data', fontsize=22, ha='center')
plt.draw()
plt.show()
fig.savefig("Test1.png")
The output