# Plotting from a Pandas dataframe

I want to improve my code. Is it possible to get the plot without repeating the same instructions multiple lines?

The data comes from a Pandas' dataframe, but I am only plotting the last column (Total Acc.)

e=df['Total Acc'].round(4)*100

#The repetitions start:
row_awa = e.loc['AWA']
row_rem = e.loc['REM']
row_s1 = e.loc['S1']
row_s2 = e.loc['S2']
row_sws = e.loc['SWS']

#More repetitions
row_awa.plot()
row_rem.plot()
row_s1.plot()
row_s2.plot()
row_sws.plot()

myLegend=plt.legend(bbox_to_anchor=(0., 1.2, 1., .102), prop ={'size':10}, loc=10, ncol=4,  #left, bottom, width, height
title=r'TOTAL ACCURACY FOR MANY K-FOLD')                    #loc='center'
myLegend.get_title().set_fontsize('20')


To reduce the repetitions you could make use of lists by doing something like:

labels = ['AWA', 'REM', 'S1', 'S2', 'SWS', 'stades']

rows = []
for label in labels:
rows.append(e.loc[label])

# or even shorter with list comprehension
rows = [e.loc[label] for label in labels]

for row in rows:
row.plot()


Edit: The labels list can also be used as first argument of the legend function to show the correct labels.

• Only Option 2 works. But that is fine. Also, how can I add the labels in the legend? So that instead of "Total Acc" I get the correct labels? – Aizzaac Oct 17 '16 at 19:31
• You could use a dictionary instead of a list and use the iteritems method of a dictionary but even more simple, probably you can use labels as the first argument of plt.legend. – Jan Kuiken Oct 17 '16 at 19:47
• You might want to add that part to the answer, comments are not permanent and this did answer a part of OP's question. – Graipher Oct 18 '16 at 7:34

You simply need to slice your frame using the list of the zero level index of the data you're interested in. Drop the zero level index of that selection

import matplotlib.pyplot as plt
import pandas as pd

level0indexes = ['AWA', 'REM', 'S1', 'S2', 'SWS', 'stades']
cols = ['Total Acc']
slicedf = df.loc[level0indexes, cols].reset_index(level = 0,drop=True).round(4)*100
x = list(range(len(slicedf)))
plt.xticks(x,  slicedf.index.tolist())
plt.plot(slicedf.values.flatten(),label=cols[0])
plt.legend()

plt.show()


or even simpler, use pandas plot

import matplotlib.pyplot as plt
import pandas as pd

level0indexes = ['AWA', 'REM', 'S1', 'S2', 'SWS', 'stades']
cols = ['Total Acc']
slicedf = df.loc[level0indexes, cols].reset_index(level = 0,drop=True).round(4)*100
plt.figure();
slicedf.plot();
plt.show();


The second method will allow you to choose to plot more than one column, just add the extra column names to the cols list

You can simply use loc After unstacking.
no need for forloops.

e=df['Total Acc'].round(4)*100
e.unstack().loc[['AWA', 'REM', 'S1', 'S2', 'SWS', 'stades']].T.plot()


PS. Some code I made to reproduce the concept:

import numpy as np
import pandas as pd
# generate multiindex
idx = []
for letter in 'abcdefghij':
for num in range(10):
idx.append((letter,num))
# build dataframe
data = pd.DataFrame(np.random.rand(100,10),
index=pd.Index(idx))
# select 1 column, unstack, choose rows and plot.
data[0].unstack().loc['a b d e g h'.split()].T.plot()