xpt xpt - 1 month ago 7
Python Question

Multiple Pandas DataFrame Bar charts on the same chart

How to plot Multiple DataFrame Bar charts on the same chart?

I want to plot top three scores (or top five). Since I know 1st >= 2nd >= 3rd, I want to plot the top three (or five) in the chart on the same bar, instead of spreading them out in three (or five) bars.

The visual effect will be exactly like the stacked bar, but the bars are not stacking on top of each other, but measured from the bottom instead.

stacked bar

UPDATE: @DizietAsahi suggested to use stacked bar instead. I guess that's the simplest solution. Can someone provide dataframe manipulation code to get the difference of the scores below please?

The source data is in the form of

TID
, and
Score
, just like the following data in CSV format, which has been already filtered out so as only top 3 are remaining. The raw data have much more scores for the same TID. The challenge of going this way is that, I also need to plot the MEAN score as well as the top three. I.e., I personally think it is impossible to manipulation the MEAN score as well as the top three at the same time to get the differences from below. So either ways have challenges (to me).

Here is a sample data in CSV format:

TID,Score
06,510
06,472
06,441
07,630
07,619
07,574
08,617
08,589
08,560
09,610
09,595
09,553
10,593
10,550
10,542
11,442
11,404
11,381


In DataFrame format (only for Multiple DataFrame Bar charts case. For using stacked bar, generating a bunch of random numbers as
Score
for each
TID
would be fine):

Scores = [
{"TID":07,"ScoreRank":1,"Score":834,"Average":690},
{"TID":07,"ScoreRank":2,"Score":820,"Average":690},
{"TID":07,"ScoreRank":3,"Score":788,"Average":690},
{"TID":08,"ScoreRank":1,"Score":617,"Average":571},
{"TID":08,"ScoreRank":2,"Score":610,"Average":571},
{"TID":08,"ScoreRank":3,"Score":600,"Average":571},
{"TID":09,"ScoreRank":1,"Score":650,"Average":584},
{"TID":09,"ScoreRank":2,"Score":644,"Average":584},
{"TID":09,"ScoreRank":3,"Score":618,"Average":584},
{"TID":10,"ScoreRank":1,"Score":632,"Average":547},
{"TID":10,"ScoreRank":2,"Score":593,"Average":547},
{"TID":10,"ScoreRank":3,"Score":577,"Average":547},
{"TID":11,"ScoreRank":1,"Score":479,"Average":409},
{"TID":11,"ScoreRank":2,"Score":445,"Average":409},
{"TID":11,"ScoreRank":3,"Score":442,"Average":409},
{"TID":12,"ScoreRank":1,"Score":370,"Average":299},
{"TID":12,"ScoreRank":2,"Score":349,"Average":299},
{"TID":12,"ScoreRank":3,"Score":341,"Average":299},
{"TID":13,"ScoreRank":1,"Score":342,"Average":252},
{"TID":13,"ScoreRank":2,"Score":318,"Average":252},
{"TID":13,"ScoreRank":3,"Score":286,"Average":252},
{"TID":14,"ScoreRank":1,"Score":303,"Average":257},
{"TID":14,"ScoreRank":2,"Score":292,"Average":257},
{"TID":14,"ScoreRank":3,"Score":288,"Average":257},
{"TID":15,"ScoreRank":1,"Score":312,"Average":242},
{"TID":15,"ScoreRank":2,"Score":276,"Average":242},
{"TID":15,"ScoreRank":3,"Score":264,"Average":242},
{"TID":16,"ScoreRank":1,"Score":421,"Average":369},
{"TID":16,"ScoreRank":2,"Score":403,"Average":369},
{"TID":16,"ScoreRank":3,"Score":398,"Average":369},
{"TID":17,"ScoreRank":1,"Score":479,"Average":418},
{"TID":17,"ScoreRank":2,"Score":466,"Average":418},
{"TID":17,"ScoreRank":3,"Score":455,"Average":418},
{"TID":18,"ScoreRank":1,"Score":554,"Average":463},
{"TID":18,"ScoreRank":2,"Score":521,"Average":463},
{"TID":18,"ScoreRank":3,"Score":520,"Average":463}]
df = pandas.DataFrame(Scores)


Thanks

Answer

Is this what you are looking for?

import pandas
import matplotlib.pyplot as plt
import numpy as np
Scores = [
{"TID":7,"ScoreRank":1,"Score":834,"Average":690},
{"TID":7,"ScoreRank":2,"Score":820,"Average":690},
{"TID":7,"ScoreRank":3,"Score":788,"Average":690},
{"TID":8,"ScoreRank":1,"Score":617,"Average":571},
{"TID":8,"ScoreRank":2,"Score":610,"Average":571},
{"TID":8,"ScoreRank":3,"Score":600,"Average":571},
{"TID":9,"ScoreRank":1,"Score":650,"Average":584},
{"TID":9,"ScoreRank":2,"Score":644,"Average":584},
{"TID":9,"ScoreRank":3,"Score":618,"Average":584},
{"TID":10,"ScoreRank":1,"Score":632,"Average":547},
{"TID":10,"ScoreRank":2,"Score":593,"Average":547},
{"TID":10,"ScoreRank":3,"Score":577,"Average":547},
{"TID":11,"ScoreRank":1,"Score":479,"Average":409},
{"TID":11,"ScoreRank":2,"Score":445,"Average":409},
{"TID":11,"ScoreRank":3,"Score":442,"Average":409},
{"TID":12,"ScoreRank":1,"Score":370,"Average":299},
{"TID":12,"ScoreRank":2,"Score":349,"Average":299},
{"TID":12,"ScoreRank":3,"Score":341,"Average":299},
{"TID":13,"ScoreRank":1,"Score":342,"Average":252},
{"TID":13,"ScoreRank":2,"Score":318,"Average":252},
{"TID":13,"ScoreRank":3,"Score":286,"Average":252},
{"TID":14,"ScoreRank":1,"Score":303,"Average":257},
{"TID":14,"ScoreRank":2,"Score":292,"Average":257},
{"TID":14,"ScoreRank":3,"Score":288,"Average":257},
{"TID":15,"ScoreRank":1,"Score":312,"Average":242},
{"TID":15,"ScoreRank":2,"Score":276,"Average":242},
{"TID":15,"ScoreRank":3,"Score":264,"Average":242},
{"TID":16,"ScoreRank":1,"Score":421,"Average":369},
{"TID":16,"ScoreRank":2,"Score":403,"Average":369},
{"TID":16,"ScoreRank":3,"Score":398,"Average":369},
{"TID":17,"ScoreRank":1,"Score":479,"Average":418},
{"TID":17,"ScoreRank":2,"Score":466,"Average":418},
{"TID":17,"ScoreRank":3,"Score":455,"Average":418},
{"TID":18,"ScoreRank":1,"Score":554,"Average":463},
{"TID":18,"ScoreRank":2,"Score":521,"Average":463},
{"TID":18,"ScoreRank":3,"Score":520,"Average":463}]

df = pandas.DataFrame(Scores)
f, ax1 = plt.subplots(1, figsize=(10,5))
bar_width = 0.75
bar_l = [i+1 for i in range(len(np.unique(df['TID'])))]
tick_pos = [i+(bar_width/2) for i in bar_l]
ax1.bar(bar_l,
        df['Score'][df['ScoreRank'] == 1],
        width=bar_width,
        label='Rank1',
        alpha=0.5,
        color='#eaff0a')

ax1.bar(bar_l,

        df['Score'][df['ScoreRank'] == 2],
        width=bar_width,
        label='Rank2',
        alpha=0.5,
        color='#939393')

ax1.bar(bar_l,
        df['Score'][df['ScoreRank'] == 3],
        width=bar_width,
        label='Rank3',
        alpha=0.5,
        color='#e29024')

ax1.bar(bar_l,
        df['Average'][df['ScoreRank'] == 3],
        width=bar_width,
        label='Average',
        alpha=0.5,
        color='#FF0000')

plt.xticks(tick_pos, np.unique(df['TID']))
ax1.set_ylabel("Score")
ax1.set_xlabel("TID")
plt.legend(loc='upper right')
plt.xlim([min(tick_pos)-bar_width, max(tick_pos)+bar_width])
plt.show()

result:

enter image description here

Comments