Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotting Pandas dataframe subplots with different linestyles

I am plotting a figure with 6 sets of axes, each with a series of 3 lines from one of 2 Pandas dataframes (1 line per column). I have been using matplotlib .plot:

import pandas as pd
import matplotlib.pyplot as plt

idx = pd.DatetimeIndex(start = '2013-01-01 00:00', periods =24,freq = 'H')
df1 = pd.DataFrame(index = idx, columns = ['line1','line2','line3'])
df1['line1']=  df1.index.hour
df1['line2'] = 24 - df1['line1']
df1['line3'] = df1['line1'].mean()
df2 = df1*2
df3= df1/2
df4= df2+df3

fig, ax = plt.subplots(2,2,squeeze=False,figsize = (10,10))
ax[0,0].plot(df1.index, df1,  marker='', linewidth=1, alpha=1)
ax[0,1].plot(df2.index, df2, marker='', linewidth=1, alpha=1)
ax[1,0].plot(df3.index, df3, marker='', linewidth=1, alpha=1)
ax[1,1].plot(df4.index, df4, marker='', linewidth=1, alpha=1)
fig.show()

It's all good, and matplotlib automatically cycles through a different colour for each line, but uses the same colours for each plot, which is what i wanted.

However, now I want to specify more details for the lines: choosing specific colours for each line, and / or changing the linestyle for each line. This link shows how to pass multiple linestyles to a Pandas plot. e.g. using

 ax = df.plot(kind='line', style=['-', '--', '-.'])

So I need to either:

  1. pass lists of styles to my subplot command above, but style is not recognised and it doesn't accept a list for linestyle or color. Is there a way to do this? or
  2. Use df.plot:

    fig, ax = plt.subplots(2,2,squeeze=False,figsize = (10,10)) ax[0,0] = df1.plot(style=['-','--','-.'], marker='', linewidth=1, alpha=1) ax[0,1] = df2.plot(style=['-','--','-.'],marker='', linewidth=1, alpha=1) ax[1,0] = df3.plot( style=['-','--','-.'],marker='', linewidth=1, alpha=1) ax[1,1] = df4.plot(style=['-','--','-.'], marker='', linewidth=1, alpha=1) fig.show()

...but then each plot is plotted as a seperate figure. I can't see how to put multiple Pandas plots on the same figure.

How can I make either of these approaches work?

like image 393
doctorer Avatar asked Oct 27 '25 05:10

doctorer


1 Answers

using matplotlib

Using matplotlib, you may define a cycler for the axes to loop over color and linestyle automatically. (See this answer).

import numpy as np; np.random.seed(1)
import pandas as pd
import matplotlib.pyplot as plt

f = lambda i: pd.DataFrame(np.cumsum(np.random.randn(20,3),0))
dic1= dict(zip(range(3), [f(i) for i in range(3)]))
dic2= dict(zip(range(3), [f(i) for i in range(3)]))
dics = [dic1,dic2]
rows = range(3)

def set_cycler(ax):
    ax.set_prop_cycle(plt.cycler('color', ['limegreen', '#bc15b0', 'indigo'])+
                      plt.cycler('linestyle', ["-","--","-."]))

fig, ax = plt.subplots(3,2,squeeze=False,figsize = (8,5))
for x in rows:
    for i,dic in enumerate(dics):
        set_cycler(ax[x,i])
        ax[x,i].plot(dic[x].index, dic[x],  marker='', linewidth=1, alpha=1)
    
plt.show()

enter image description here

using pandas

Using pandas you can indeed supply a list of possible colors and linestyles to the df.plot() method. Additionally you need to tell it in which axes to plot (df.plot(ax=ax[i,j])).

import numpy as np; np.random.seed(1)
import pandas as pd
import matplotlib.pyplot as plt


f = lambda i: pd.DataFrame(np.cumsum(np.random.randn(20,3),0))
dic1= dict(zip(range(3), [f(i) for i in range(3)]))
dic2= dict(zip(range(3), [f(i) for i in range(3)]))
dics = [dic1,dic2]
rows = range(3)

color = ['limegreen', '#bc15b0', 'indigo']
linestyle = ["-","--","-."]

fig, ax = plt.subplots(3,2,squeeze=False,figsize = (8,5))
for x in rows:
    for i,dic in enumerate(dics):
        dic[x].plot(ax=ax[x,i], style=linestyle, color=color, legend=False)
        
    
plt.show()

enter image description here

like image 98
ImportanceOfBeingErnest Avatar answered Oct 29 '25 07:10

ImportanceOfBeingErnest