matplotlib subplot with dates: cannot change xlim - python
I am trying to produce a subplot, plotting 3 time series over 2 different axes.
My time series go from Jan-2007 till Sep-2017 (one data point per month).
My problem is that I cannot change the limits of the x axis.
I have tried both xlim and set_xlim, but they have no effect whatsoever.
What am I doing wrong?
An example of my code is below.
import numpy as np
import pandas as pd
import datetime as dt
import dateutil
import matplotlib.pyplot as plt
import matplotlib
import matplotlib.ticker as mtick
mystart = dt.date(2007,1,1)
mydates =[mystart]
for i in np.arange(1,130):
mydates.append( mystart +dateutil.relativedelta.relativedelta(months=i))
df=pd.DataFrame()
df['month']=mydates
df['a']= np.arange(1,131)
df['b']=df['a']/2
df['c']=0.25
fig,ax=plt.subplots(2)
ax[0].set_title('My title')
l1 = ax[0].plot_date( df['month'],df['a'], label= 'a (left axis)', color='blue', ls='solid', marker ='')
l2 = ax[0].plot_date( df['month'],df['b'], label= 'b (left axis)',color='red', ls='solid', marker ='')
# THESE BELOW ARE THE TWO LINES I CANNOT GET TO WORK!!!
#plt.xlim(xmin= dt.date(2012,1,31),xmax=dt.date(2017,9,30))
ax[0].set_xlim([dt.date(2012,1,31),dt.date(2017,9,30)], auto=True)
ax[0].grid()
ax2=ax[0].twinx()
l3 = ax2.plot_date( df['month'],df['c']*100 , label= 'some % (right axis)', color='green', ls='solid', marker ='')
fmt = '%.2f%%' # Format you want the ticks, e.g. '40%'
yticks = mtick.FormatStrFormatter(fmt)
ax2.yaxis.set_major_formatter(yticks)
ls=l1+l2+l3
labs=[l.get_label() for l in ls]
ax[0].legend(ls, labs, loc='upper left')
ax[1].set_title('Something else will go here...')
plt.show()
Set the limits of the axes after you have created the twin axes and plotted to it.
ax2=ax[0].twinx()
l3 = ax2.plot_date( ... )
ax[0].set_xlim( ... )
I got it: the issue is the secondary axis.
I must repeat set_xlim for ax2, as well:
ax2.set_xlim([dt.datetime(2012,1,31),dt.datetime(2017,9,30)], auto=True)
I am not sure if this is a bug, TBH. I would have expected that creating a twin axis would have replicated the same xlim.
Related
How to add multiple custom ticks to seaborn boxplot
I generated a boxplot using seaborn. On the x axis, I would like to have, both the number of days (20, 25, 32) and the actual dates they refer to (2022-05-08, 2022-05-13, 2022-05-20). I found a potential solution at the following link add custom tick with matplotlib. I'm trying to adapt it to my problem but I could only get the number of days or the dates, not both. I really would appreciate any help. Thank you in advance for your time. Please, find below my code and the desired output. import pandas as pd import matplotlib.pyplot as plt import seaborn as sns df = pd.DataFrame({'nb_days':[20,20,20,25,25,20,32,32,25,32,32], 'Dates':['2022-05-08','2022-05-08','2022-05-08','2022-05-13','2022-05-13','2022-05-08','2022-05-20','2022-05-20','2022-05-13','2022-05-20','2022-05-20'], 'score':[3,3.5,3.4,2,2.2,3,5,5.2,4,4.3,5]}) df['Dates'] = df['Dates'].apply(pd.to_datetime) tick_label = dict(zip(df['nb_days'],df['Dates'].apply(lambda x: x.strftime('%Y-%m-%d')))) #My custom xtick label #Plot fig,ax = plt.subplots(figsize=(6,6)) ax = sns.boxplot(x='nb_days',y='score',data=df,color=None) # iterate over boxes to change color for i,box in enumerate(ax.artists): box.set_edgecolor('red') box.set_facecolor('white') sns.stripplot(x='nb_days',y='score',data=df,color='black') ticks = sorted(df['nb_days'].unique()) labels = [tick_label.get(t, ticks[i]) for i,t in enumerate(ticks)] ax.set_xticklabels(labels) plt.tight_layout() plt.show() plt.close() Here is the desired output.
You can do that by adding these lines in place of ax.set_xticklabels(labels) new_labels=["{}\n{}".format(a_, b_) for a_, b_ in zip(ticks, labels)] ax.set_xticklabels(new_labels) Output
Try this: import pandas as pd import matplotlib.pyplot as plt import seaborn as sns df = pd.DataFrame({'nb_days':[20,20,20,25,25,20,32,32,25,32,32], 'Dates':['2022-05-08','2022-05-08','2022-05-08','2022-05-13','2022-05-13','2022-05-08','2022-05-20','2022-05-20','2022-05-13','2022-05-20','2022-05-20'], 'score':[3,3.5,3.4,2,2.2,3,5,5.2,4,4.3,5]}) df['Dates'] = df['Dates'].apply(pd.to_datetime) tick_label = dict(zip(df['nb_days'],df['Dates'].apply(lambda x: x.strftime('%Y-%m-%d')))) #My custom xtick label #Plot fig,ax = plt.subplots(figsize=(6,6)) ax = sns.boxplot(x='nb_days',y='score',data=df,color=None) # iterate over boxes to change color for i,box in enumerate(ax.artists): box.set_edgecolor('red') box.set_facecolor('white') sns.stripplot(x='nb_days',y='score',data=df,color='black') ticks = sorted(df['nb_days'].unique()) labels = ["{}\n".format(t)+tick_label.get(t, ticks[i]) for i, t in enumerate(ticks)] ax.set_xticklabels(labels) plt.tight_layout() plt.show() plt.close()
How to force grid to fit data range [duplicate]
So currently learning how to import data and work with it in matplotlib and I am having trouble even tho I have the exact code from the book. This is what the plot looks like, but my question is how can I get it where there is no white space between the start and the end of the x-axis. Here is the code: import csv from matplotlib import pyplot as plt from datetime import datetime # Get dates and high temperatures from file. filename = 'sitka_weather_07-2014.csv' with open(filename) as f: reader = csv.reader(f) header_row = next(reader) #for index, column_header in enumerate(header_row): #print(index, column_header) dates, highs = [], [] for row in reader: current_date = datetime.strptime(row[0], "%Y-%m-%d") dates.append(current_date) high = int(row[1]) highs.append(high) # Plot data. fig = plt.figure(dpi=128, figsize=(10,6)) plt.plot(dates, highs, c='red') # Format plot. plt.title("Daily high temperatures, July 2014", fontsize=24) plt.xlabel('', fontsize=16) fig.autofmt_xdate() plt.ylabel("Temperature (F)", fontsize=16) plt.tick_params(axis='both', which='major', labelsize=16) plt.show()
There is an automatic margin set at the edges, which ensures the data to be nicely fitting within the axis spines. In this case such a margin is probably desired on the y axis. By default it is set to 0.05 in units of axis span. To set the margin to 0 on the x axis, use plt.margins(x=0) or ax.margins(x=0) depending on the context. Also see the documentation. In case you want to get rid of the margin in the whole script, you can use plt.rcParams['axes.xmargin'] = 0 at the beginning of your script (same for y of course). If you want to get rid of the margin entirely and forever, you might want to change the according line in the matplotlib rc file: axes.xmargin : 0 axes.ymargin : 0 Example import seaborn as sns import matplotlib.pyplot as plt tips = sns.load_dataset('tips') fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) tips.plot(ax=ax1, title='Default Margin') tips.plot(ax=ax2, title='Margins: x=0') ax2.margins(x=0) Alternatively, use plt.xlim(..) or ax.set_xlim(..) to manually set the limits of the axes such that there is no white space left.
If you only want to remove the margin on one side but not the other, e.g. remove the margin from the right but not from the left, you can use set_xlim() on a matplotlib axes object. import seaborn as sns import matplotlib.pyplot as plt import math max_x_value = 100 x_values = [i for i in range (1, max_x_value + 1)] y_values = [math.log(i) for i in x_values] fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) sn.lineplot(ax=ax1, x=x_values, y=y_values) sn.lineplot(ax=ax2, x=x_values, y=y_values) ax2.set_xlim(-5, max_x_value) # tune the -5 to your needs
How to change seaborn/python default x label position, 0 and 0 in exact bottom corner [duplicate]
So currently learning how to import data and work with it in matplotlib and I am having trouble even tho I have the exact code from the book. This is what the plot looks like, but my question is how can I get it where there is no white space between the start and the end of the x-axis. Here is the code: import csv from matplotlib import pyplot as plt from datetime import datetime # Get dates and high temperatures from file. filename = 'sitka_weather_07-2014.csv' with open(filename) as f: reader = csv.reader(f) header_row = next(reader) #for index, column_header in enumerate(header_row): #print(index, column_header) dates, highs = [], [] for row in reader: current_date = datetime.strptime(row[0], "%Y-%m-%d") dates.append(current_date) high = int(row[1]) highs.append(high) # Plot data. fig = plt.figure(dpi=128, figsize=(10,6)) plt.plot(dates, highs, c='red') # Format plot. plt.title("Daily high temperatures, July 2014", fontsize=24) plt.xlabel('', fontsize=16) fig.autofmt_xdate() plt.ylabel("Temperature (F)", fontsize=16) plt.tick_params(axis='both', which='major', labelsize=16) plt.show()
There is an automatic margin set at the edges, which ensures the data to be nicely fitting within the axis spines. In this case such a margin is probably desired on the y axis. By default it is set to 0.05 in units of axis span. To set the margin to 0 on the x axis, use plt.margins(x=0) or ax.margins(x=0) depending on the context. Also see the documentation. In case you want to get rid of the margin in the whole script, you can use plt.rcParams['axes.xmargin'] = 0 at the beginning of your script (same for y of course). If you want to get rid of the margin entirely and forever, you might want to change the according line in the matplotlib rc file: axes.xmargin : 0 axes.ymargin : 0 Example import seaborn as sns import matplotlib.pyplot as plt tips = sns.load_dataset('tips') fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) tips.plot(ax=ax1, title='Default Margin') tips.plot(ax=ax2, title='Margins: x=0') ax2.margins(x=0) Alternatively, use plt.xlim(..) or ax.set_xlim(..) to manually set the limits of the axes such that there is no white space left.
If you only want to remove the margin on one side but not the other, e.g. remove the margin from the right but not from the left, you can use set_xlim() on a matplotlib axes object. import seaborn as sns import matplotlib.pyplot as plt import math max_x_value = 100 x_values = [i for i in range (1, max_x_value + 1)] y_values = [math.log(i) for i in x_values] fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) sn.lineplot(ax=ax1, x=x_values, y=y_values) sn.lineplot(ax=ax2, x=x_values, y=y_values) ax2.set_xlim(-5, max_x_value) # tune the -5 to your needs
Matplotlib Plot time series with different periodicity
I have 2 dfs. One of them has data for a month. Another one, averages for the past quarters. I wanna plot the averages in front of the monthly data. How can I do it? Please note that I am trying to plot averages as dots and monthly as line chart. So far my best result was achieved by ax1=ax.twiny(), but still not ideal result as data point appear in throughout the chart, rather than just in front. import pandas as pd import numpy as np import matplotlib.dates as mdates from matplotlib.ticker import ScalarFormatter, FormatStrFormatter, FuncFormatter import matplotlib.ticker as ticker import matplotlib.pyplot as plt date_base = pd.date_range(start='1/1/2018', end='1/30/2018') df_base = pd.DataFrame(np.random.randn(30,4), columns=list("ABCD"), index=date_base) date_ext = pd.date_range(start='1/1/2017', end='1/1/2018', freq="Q") df_ext = pd.DataFrame(np.random.randn(4,4), columns=list("ABCD"), index=date_ext) def drawChartsPlt(df_base, df_ext): fig = plt.figure(figsize=(10,5)) ax = fig.add_subplot(111) number_of_plots = len(df_base.columns) LINE_STYLES = ['-', '--', '-.', 'dotted'] colormap = plt.cm.nipy_spectral ax.set_prop_cycle("color", [colormap(i) for i in np.linspace(0,1,number_of_plots)]) date_base = df_base.index date_base = [i.strftime("%Y-%m-%d") for i in date_base] q_ends = df_ext.index q_ends = [i.strftime("%Y-%m-%d") for i in q_ends] date_base.insert(0, "") #to shift xticks so they match chart date_base += q_ends for i in range(number_of_plots): df_base.ix[:-3, df_base.columns[i]].plot(kind="line", linestyle=LINE_STYLES[i%2], subplots=False, ax=ax) #ax.set_xticks(date_base) #ax.set_xticklabels(date_base) # ax.xaxis.set_major_locator(ticker.MultipleLocator(20)) ax.xaxis.set_major_locator(ticker.LinearLocator(len(date_base))) ax.xaxis.set_major_formatter(plt.FixedFormatter(date_base)) fig.autofmt_xdate() # ax1=ax.twinx() ax1=ax.twiny() ax1.set_prop_cycle("color", [colormap(i) for i in np.linspace(0,1,number_of_plots)]) for i in range(len(df_ext.columns)): ax1.scatter(x=df_ext.index, y=df_ext[df_ext.columns[i]]) ax.set_title("Test") #plt.minorticks_off()) ax.minorticks_off() #ax1.minorticks_off() #ax1.set_xticklabels(date_base) #ax1.set_xticklabels(q_ends) ax.legend(loc="center left", bbox_to_anchor=(1,0.5)) ax.xaxis.label.set_size(12) plt.xlabel("TEST X Label") plt.ylabel("TEST Y Label") ax1.set_xlabel("Quarters") plt.show() drawChartsPlt(df_base, df_ext)
The way I ended up coding it is by saving quarterly index of df_ext to a temp variable, overwriting it with dates that are close to df_base.index using pd.date_range(start=df_base.index[-1], periods=len(df_ext), freq='D'), and the finally setting the dates that I need with ax.set_xticklabels(list(date_base)+list(date_ext)). It looks like it could be achieved using broken axes as indicated Break // in x axis of matplotlib and Python/Matplotlib - Is there a way to make a discontinuous axis?, but I haven't tried that solution.
Fix x-axis scale seaborn factorplot
I'm attempting to make a figure that shows two plots, with each plot separated based on a set of categorical data. However, although I can make the graph, I cant figure out how to get the x-axis to be properly spaced. I want the x-axis to start before the first value (want axis to start at 60 [first value = 63]) and end after the last (want axis to end at 95 [last value = 92.1]), with xticks going up in 5's. Any help is much appreciated! Thanks in advance! import pandas as pd import matplotlib.pyplot as plt import matplotlib.axes import seaborn as sns Temperature = [63.0,63.3,63.6,63.9,64.2,64.5,64.8,65.2,65.5,65.8,66.1,66.4,66.7,67.0,67.3,67.7,68.0,68.3,68.6,68.9,69.2,69.5,69.9,70.2,70.5,70.8,71.1,71.4,71.8,72.1,72.4,72.7,73.0,73.4,73.7,74.0,74.3,74.6,74.9,75.2,75.6,75.9,76.2,76.5,76.9,77.2,77.5,77.8,78.1,78.5,78.8,79.1,79.4,79.7,80.1,80.4,80.7,81.0,81.3,81.6,81.9,82.3,82.6,82.9,83.2,83.5,83.8,84.1,84.4,84.8,85.1,85.4,85.7,86.0,86.3,86.6,86.9,87.2,87.5,87.8,88.1,88.4,88.7,89.0,89.3,89.6,89.8,90.1,90.4,90.7,91.0,91.2,91.5,91.8,92.1,63.0,63.3,63.6,63.9,64.2,64.5,64.8,65.2,65.5,65.8,66.1,66.4,66.7,67.0,67.3,67.7,68.0,68.3,68.6,68.9,69.2,69.5,69.9,70.2,70.5,70.8,71.1,71.4,71.8,72.1,72.4,72.7,73.0,73.4,73.7,74.0,74.3,74.6,74.9,75.2,75.6,75.9,76.2,76.5,76.9,77.2,77.5,77.8,78.1,78.5,78.8,79.1,79.4,79.7,80.1,80.4,80.7,81.0,81.3,81.6,81.9,82.3,82.6,82.9,83.2,83.5,83.8,84.1,84.4,84.8,85.1,85.4,85.7,86.0,86.3,86.6,86.9,87.2,87.5,87.8,88.1,88.4,88.7,89.0,89.3,89.6,89.8,90.1,90.4,90.7,91.0,91.2,91.5,91.8,92.1] Derivative = [0.0495,0.0507,0.0525,0.0548,0.0570,0.0579,0.0579,0.0574,0.0574,0.0576,0.0581,0.0587,0.0593,0.0592,0.0584,0.0580,0.0579,0.0580,0.0582,0.0588,0.0592,0.0594,0.0588,0.0581,0.0578,0.0579,0.0580,0.0579,0.0582,0.0581,0.0579,0.0574,0.0571,0.0563,0.0548,0.0538,0.0536,0.0540,0.0544,0.0551,0.0556,0.0551,0.0542,0.0535,0.0536,0.0542,0.0564,0.0623,0.0748,0.0982,0.1360,0.1897,0.2550,0.3228,0.3807,0.4177,0.4248,0.3966,0.3365,0.2558,0.1713,0.0971,0.0438,0.0140,0.0034,0.0028,0.0048,0.0058,0.0057,0.0050,0.0042,0.0038,0.0039,0.0041,0.0038,0.0031,0.0023,0.0017,0.0014,0.0012,0.0015,0.0019,0.0020,0.0018,0.0017,0.0015,0.0014,0.0014,0.0015,0.0014,0.0013,0.0011,0.0007,0.0004,0.0011,0.0105,0.0100,0.0096,0.0090,0.0084,0.0081,0.0077,0.0071,0.0066,0.0063,0.0064,0.0060,0.0057,0.0055,0.0054,0.0051,0.0047,0.0046,0.0042,0.0037,0.0035,0.0040,0.0043,0.0039,0.0032,0.0028,0.0028,0.0027,0.0029,0.0034,0.0038,0.0034,0.0027,0.0024,0.0021,0.0017,0.0015,0.0016,0.0015,0.0011,0.0008,0.0012,0.0019,0.0025,0.0027,0.0026,0.0019,0.0012,0.0010,0.0014,0.0016,0.0014,0.0010,0.0007,0.0007,0.0010,0.0017,0.0021,0.0020,0.0013,0.0012,0.0013,0.0014,0.0015,0.0018,0.0017,0.0012,0.0013,0.0018,0.0028,0.0031,0.0033,0.0027,0.0022,0.0015,0.0016,0.0022,0.0026,0.0026,0.0019,0.0012,0.0006,0.0007,0.0011,0.0016,0.0014,0.0010,0.0009,0.0012,0.0015,0.0014,0.0008,0.0001,-0.0003,0.0002] Category = ["a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b"] df = pd.DataFrame({"Temperature": Temperature, "Derivative": Derivative, "Category" : Category}) g = sns.factorplot(x="Temperature", y="Derivative", data=df, col="Category") g.set_xticklabels(step=10)
All the desired feature you describe suggest that using a factorplot here is absolutely the wrong choice. Instead use a normal matplotlib plot and then set the limits as usual, plt.xlim(60,95). import pandas as pd import matplotlib.pyplot as plt Temperature = [63.0,63.3,63.6,63.9,64.2,64.5,64.8,65.2,65.5,65.8,66.1,66.4,66.7,67.0,67.3,67.7,68.0,68.3,68.6,68.9,69.2,69.5,69.9,70.2,70.5,70.8,71.1,71.4,71.8,72.1,72.4,72.7,73.0,73.4,73.7,74.0,74.3,74.6,74.9,75.2,75.6,75.9,76.2,76.5,76.9,77.2,77.5,77.8,78.1,78.5,78.8,79.1,79.4,79.7,80.1,80.4,80.7,81.0,81.3,81.6,81.9,82.3,82.6,82.9,83.2,83.5,83.8,84.1,84.4,84.8,85.1,85.4,85.7,86.0,86.3,86.6,86.9,87.2,87.5,87.8,88.1,88.4,88.7,89.0,89.3,89.6,89.8,90.1,90.4,90.7,91.0,91.2,91.5,91.8,92.1,63.0,63.3,63.6,63.9,64.2,64.5,64.8,65.2,65.5,65.8,66.1,66.4,66.7,67.0,67.3,67.7,68.0,68.3,68.6,68.9,69.2,69.5,69.9,70.2,70.5,70.8,71.1,71.4,71.8,72.1,72.4,72.7,73.0,73.4,73.7,74.0,74.3,74.6,74.9,75.2,75.6,75.9,76.2,76.5,76.9,77.2,77.5,77.8,78.1,78.5,78.8,79.1,79.4,79.7,80.1,80.4,80.7,81.0,81.3,81.6,81.9,82.3,82.6,82.9,83.2,83.5,83.8,84.1,84.4,84.8,85.1,85.4,85.7,86.0,86.3,86.6,86.9,87.2,87.5,87.8,88.1,88.4,88.7,89.0,89.3,89.6,89.8,90.1,90.4,90.7,91.0,91.2,91.5,91.8,92.1] Derivative = [0.0495,0.0507,0.0525,0.0548,0.0570,0.0579,0.0579,0.0574,0.0574,0.0576,0.0581,0.0587,0.0593,0.0592,0.0584,0.0580,0.0579,0.0580,0.0582,0.0588,0.0592,0.0594,0.0588,0.0581,0.0578,0.0579,0.0580,0.0579,0.0582,0.0581,0.0579,0.0574,0.0571,0.0563,0.0548,0.0538,0.0536,0.0540,0.0544,0.0551,0.0556,0.0551,0.0542,0.0535,0.0536,0.0542,0.0564,0.0623,0.0748,0.0982,0.1360,0.1897,0.2550,0.3228,0.3807,0.4177,0.4248,0.3966,0.3365,0.2558,0.1713,0.0971,0.0438,0.0140,0.0034,0.0028,0.0048,0.0058,0.0057,0.0050,0.0042,0.0038,0.0039,0.0041,0.0038,0.0031,0.0023,0.0017,0.0014,0.0012,0.0015,0.0019,0.0020,0.0018,0.0017,0.0015,0.0014,0.0014,0.0015,0.0014,0.0013,0.0011,0.0007,0.0004,0.0011,0.0105,0.0100,0.0096,0.0090,0.0084,0.0081,0.0077,0.0071,0.0066,0.0063,0.0064,0.0060,0.0057,0.0055,0.0054,0.0051,0.0047,0.0046,0.0042,0.0037,0.0035,0.0040,0.0043,0.0039,0.0032,0.0028,0.0028,0.0027,0.0029,0.0034,0.0038,0.0034,0.0027,0.0024,0.0021,0.0017,0.0015,0.0016,0.0015,0.0011,0.0008,0.0012,0.0019,0.0025,0.0027,0.0026,0.0019,0.0012,0.0010,0.0014,0.0016,0.0014,0.0010,0.0007,0.0007,0.0010,0.0017,0.0021,0.0020,0.0013,0.0012,0.0013,0.0014,0.0015,0.0018,0.0017,0.0012,0.0013,0.0018,0.0028,0.0031,0.0033,0.0027,0.0022,0.0015,0.0016,0.0022,0.0026,0.0026,0.0019,0.0012,0.0006,0.0007,0.0011,0.0016,0.0014,0.0010,0.0009,0.0012,0.0015,0.0014,0.0008,0.0001,-0.0003,0.0002] Category = ["a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b"] df = pd.DataFrame({"Temperature": Temperature, "Derivative": Derivative, "Category" : Category}) for n, data in df.groupby("Category"): plt.plot(data["Temperature"],data["Derivative"] , marker="o", label=n) plt.xlim(60,95) plt.legend() plt.show() Or if subplots are desired, fig,axes = plt.subplots(ncols=len(df["Category"].unique()), sharey=True) for ax,(n, data) in zip(axes,df.groupby("Category")): ax.plot(data["Temperature"],data["Derivative"] , marker="o", label=n) ax.set_title("Category {}".format(n)) ax.set_xlim(60,95) plt.show() Finally, you may use a seaborn FacetGrid onto which you plot your data with a plot: g = sns.FacetGrid(df, col="Category") g.map(plt.plot, "Temperature", "Derivative",marker="o",) for ax in g.axes.flat: ax.set_xlim(60,95) plt.show()