1

I have the following dataframes:

      import pandas as pd
      import numpy as np
      import matplotlib.pyplot as plt

      df_One = pd.DataFrame({'Category': ['1024Sen', '1024Act', '2089Eng', '2089Sen'], 
                             'Qtd_Instrumentation': [18, 5, 25, 10]})


     df_Two = pd.DataFrame({'Category': ['1024Sen', '1024Act', '2089Eng', '2089Sen'], 
                   'Qtd_Instrumentation': [14, 1, 22, 10]})

I would like to build a bar graph that contains the information from the two data frames, that is, the blue bars indicate the datadrame_One and the vertical red bars indicate the information of the dataframe_Two.

I tried to implement it as follows:

       fig, ax = plt.subplots()
       n_group = len(df_One['Category'])
       index = np.arange(n_group)
       bar_width = 0.35
       opacity = 0.8


       rects1 = df_One.plot.bar(x='Category', y='Qtd_Instrumentation', color='r', label = 'Station 
                                One')
       rects2 = df_Two.plot.bar(x='Category', y='Qtd_Instrumentation', color='b', label = 'Station 
                                Two')


       plt.xlabel('Category Instrumentation')
       plt.ylabel('Qtd Instrumentation')

       plt.show()

However, this code is wrong, as it designs two bar graphs instead of building just one graph with the two representations.

Does anyone know how I can build this described chart? Tks

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Jane Borges
  • 552
  • 5
  • 14

2 Answers2

1

This is one way to do it by choosing the align='edge' option and then using positive width for one bar and negative width for another. This will make them aligned next to each other. Also, you have to call plt.legend() to display the legends

fig, ax = plt.subplots()

index = np.arange(len(df_One['Category']))
bar_width = 0.35
opacity = 0.8

ax.bar(index, df_One['Qtd_Instrumentation'], color='r', align='edge', width=bar_width, label = 'Station One')
ax.bar(index, df_Two['Qtd_Instrumentation'], color='b', align='edge', width=-bar_width,label = 'Station Two')

# Assign the tick labels
ax.set_xticks(index)
ax.set_xticklabels(df_One['Category'], rotation=90)

plt.xlabel('Category Instrumentation')
plt.ylabel('Qtd Instrumentation')
plt.legend()
plt.show()

enter image description here

Alternative method is the following by using the keyword position to place the bars next to each other as shown here

df_One.Qtd_Instrumentation.plot(kind='bar', color='red', ax=ax, width=bar_width, position=1)
df_Two.Qtd_Instrumentation.plot(kind='bar', color='blue', ax=ax, width=bar_width, position=0)

ax.set_xlim(-0.5, 3.5)
ax.set_xticks(index)
ax.set_xticklabels(df_One['Category'])
Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • Worked perfectly. I have just one more question: on the complete dataframe I have 15 different Category. When I design the chart, the names overlap. Do you know how to solve this problem? – Jane Borges Jun 01 '20 at 14:20
  • 1
    @JaneBorges : Use `rotation = 90` while setting the tick labels – Sheldore Jun 01 '20 at 14:20
  • Good idea! In this way the categories are vertical. Just one more question: I tried to increase the graph with: ax.plot (kind = 'bar', figsize = (15.10)). However, it did not increase. Do you know how I can enlarge the graph? – Jane Borges Jun 01 '20 at 14:25
  • 1
    @JaneBorges : Use `fig, ax = plt.subplots(figsize = (15, 10))` and then rest of the code remains the same – Sheldore Jun 01 '20 at 14:26
  • 1
    might want a comma in there, e.g. `figsize=(15, 10)` – Sam Mason Jun 01 '20 at 14:27
  • @SamMason : Good observation, that was the reason I think it didn't work before for him/her – Sheldore Jun 01 '20 at 14:27
1

I'd suggest merging the two dataframes first:

df_c = pd.merge(df_One, df_Two, on='Category')
df_c.plot.bar(x='Category')

gives:

resulting plot

note that you might want to pass how='outer' to merge if you have missing categories.

Sam Mason
  • 15,216
  • 1
  • 41
  • 60