4

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?

doctorer
  • 1,672
  • 5
  • 27
  • 50
  • 1
    Can you please provide a [mcve]. From the incomplete code sniplet you show it seems you are just plotting the same dateframe 3 times (which would not make much sense, right?) – ImportanceOfBeingErnest Nov 16 '17 at 23:51
  • Yeah, my apologies. I was trying to simplify the code and over did it. df1 and df2 are `dicts` of `dataframes` so each plot is different. I will take the time to make a more complete example – doctorer Nov 16 '17 at 23:58
  • @ImportanceOfBeingErnest I have updated the question - hopefully Minimal, Complete & Verifiable – doctorer Nov 17 '17 at 00:36
  • Sorry, I now took the old example for my answer below. Now I'm too lazy to change it to the new example. The principle is the same I guess. – ImportanceOfBeingErnest Nov 17 '17 at 00:52

1 Answers1

8

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

Community
  • 1
  • 1
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712