0

I am trying to loop over a df to plot some data in subplots. The columns of my data are a letter, plus an integer.

df = {'x1': [2, 4, 7, 5, 6],
     'x2': [2, 7, 2, 6, 3],
     'y1': [4, 3, 2, 8, 7],
     'y2': [2, 2, 4, 6, 4],
     'z1': [2, 2, 2, 6, 7],
     'z2': [3, 1, 4, 5, 9]}
df = pd.DataFrame(df, index=range(0,5))

letterlist=['x', 'y', 'z']
numberlist=['1', '2']
tickers = df.columns

where index of df are a set of dates in my df

I am trying to achieve subplots twofold: 1) one section of code for A, B and C, (each plot will have 2 lines in) 2) another piece of code for 1 and 2, (each plot will have 3 lines in, X Y and Z)

I was trying to loop over letterlist and numberlist, because my df is quite a lot larger:

so I attempted:

fig = plt.figure(figsize=(8,8))

for ticker, num in zip(tickers, xrange(1,len(letterlist))):
        ax = fig.add_subplot(len(letterlist),1,num)
        ax.plot(df[ticker])
        ax.set_title(ticker)

plt.tight_layout()
plt.show()

But I keep getting errors and my indexation is wrong i think.. so getting stuck. Any ideas, please?

Expected output is: fig1 1x3 subplot, with x1 and x2 plotted, y1 and y2, and z1 and z2 fig2 1x2 subplot, with x1, y1 and z1 plotted, and x2, y2, and z2

Thanks

Junaid Mohammad
  • 457
  • 1
  • 6
  • 18
  • 1
    Count your parantheses. – Stop harming Monica Aug 27 '18 at 09:56
  • Thanks Goyo, I updated the question. Sorry I wasn't clear enough - the issue I have is that I don't know how to create a new subplot as described in the desired output... my code returns a subplot for x1, x2, y1, y2, z1 and z2, which isn't desired output. Any ideas? – Junaid Mohammad Aug 27 '18 at 10:03
  • @Mr.T Its more than a typo error. (Im sorry I had a small typo in my dummy question). Please see my comment above. Can u help? Im not actually sure how to re-open questions – Junaid Mohammad Aug 27 '18 at 10:09
  • Now I do not see any errors when running your code. But there is no way you get two figures if you only create one. You do not need to re-open the question. – Stop harming Monica Aug 27 '18 at 10:20
  • @Goyo, thank you for replying. The above was a snippet of me trying to tackle 1) first. You will see that the code produces an output of x1 plotted on subplot 1, whilst x2 is plotted on subplot 2. What I wanted was 1x3 subplot, with x1 and x2 plotted on sub1, y1 and y2 on sub2, and z1 and z2 on sub3 – Junaid Mohammad Aug 27 '18 at 10:25
  • I think I can answer that but it is still unclear what errors you are getting and whether you want two figures or one. – Stop harming Monica Aug 27 '18 at 11:02

1 Answers1

1

One way to achieve your desired output is this:

from matplotlib import pyplot as plt
import pandas as pd
#define the dataframe
df = {'x1': [2, 4, 7, 5, 6],
     'x2': [2, 7, 2, 6, 3],
     'y1': [4, 3, 2, 8, 7],
     'y2': [2, 2, 4, 6, 4],
     'z1': [2, 2, 2, 6, 7],
     'z2': [3, 1, 4, 5, 9]}
df = pd.DataFrame(df, index=range(0,5))

letters = 3
numbers = 2
tickers = df.columns

#first figure letterwise presentation
fig, axes = plt.subplots(nrows = letters, ncols = 1, figsize=(8,8))

for i, pair in enumerate([tickers[i:i+numbers] for i in range(0, len(tickers), numbers)]):
    ax = axes[i]
    for item in pair:
        ax.plot(df[item], label = item)
    ax.legend()
    ax.set_title(", ".join(pair))
plt.tight_layout()

#second figure numberwise presentation
fig, axes = plt.subplots(nrows = numbers, ncols = 1, figsize=(8,8))

for i, pair in enumerate([tickers[i::numbers] for i in range(numbers)]):
    ax = axes[i]
    for item in pair:
        ax.plot(df[item], label = item)
    ax.legend()
    ax.set_title(", ".join(pair))
plt.tight_layout()

plt.show()

Sample output: enter image description here

But you still have to define manually, how many letters and numbers you have and your columns have to be in the expected order [x1, x2, x3, ..., xn, y1, y2, y3,...,yn, z1...]. You might want to look into pandas multiindex to construct a dataframe, where you can automatically extract the necessary information.

Mr. T
  • 11,960
  • 10
  • 32
  • 54