0

l would like to make a histogram with bars where each bar is set beside another bar for the same labem. From the post answered by @ImportanceOfBeingErnest l would like to make histogram with bars where we have a set of labels and two lists. For five labels for instance , l need to get 2 bars for each label (first for list1 and second for list2) Here is the original code.

   from collections import Counter
   import matplotlib.pyplot as plt
   list1 = list("ABADEAABEDDA3EDBBBBBDG") # letters A, B, D, E, G
   list2 = list("HAABAEEDCCFFFGEDABEEC")  # all letters A-F, G,H
   items1, counts1 = zip(*sorted(Counter(list1).items()))
   items2, counts2 = zip(*sorted(Counter(list2).items()))
   plt.bar(items1+items2, [5]*len(items1+items2), visible=False)
   plt.bar(items1, counts1, label="list1")
   plt.bar(items2, counts2, label="list2")
   plt.legend()
   plt.show()
Joseph
  • 343
  • 6
  • 18
  • As I said in my previous comment, you need to replace `plt.plot` by `plt.bar`. – ImportanceOfBeingErnest Feb 09 '18 at 16:25
  • @ImportanceOfBeingErnest, when l replace plt.plot() by plt.bar() l get a stacked bar. However l'm looking for a bar for each list. For instance at A l need to get two bars , the first for list1 and another for list2 (one next to the other) – Joseph Feb 09 '18 at 16:35
  • Because if number of elements of A in list1 is considerably higher than the number of elements of A in list2 lets say 100 in list1 and 1 in list2 the bar for list2 will not appear – Joseph Feb 09 '18 at 16:38
  • The bars are not stacked, but overlapping, because you define them to be at the same position. Maybe you update your quesiton with the *actual* problem. – ImportanceOfBeingErnest Feb 09 '18 at 16:40
  • Thank you for this nuance. Definitely l want them one next each other – Joseph Feb 09 '18 at 16:43
  • @ImportanceOfBeingErnest, question updated – Joseph Feb 09 '18 at 16:47

1 Answers1

2

You reached the limit of what matplotlib categorical plots can currently do (as of version 2.1). Because each category has a fixed position on the axes, bar's will overlap.

Alternatives:

Seaborn and pandas

You may use a seaborn countplot.

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

list1 = list("ABADEAABEDDAEDBBBBBD")
list2 = list("AABAEEDCCFFFEDABEEC")

df = pd.DataFrame({"item" : list1+list2, 
                  "implementation" : [0]*len(list1) + [1]*len(list2)})

sns.countplot(data=df, x="item", hue="implementation")

plt.show()

enter image description here

Shifting the bars

Using an Affine2D translation you may shift the bars to the left and right.

from collections import Counter

list1 = list("ABADEAABEDDAEDBBBBBD")
list2 = list("AABAEEDCCFFFEDABEEC")

items1, counts1 = zip(*sorted(Counter(list1).items()))
items2, counts2 = zip(*sorted(Counter(list2).items()))


import matplotlib.pyplot as plt
import matplotlib.transforms

plt.plot(items1+items2, [5]*len(items1+items2), visible=False)

trans1 = matplotlib.transforms.Affine2D().translate(-0.2,0)
trans2 = matplotlib.transforms.Affine2D().translate(+0.2,0)

plt.bar(items1, counts1, label="list1", width=0.4, transform=trans1+plt.gca().transData)
plt.bar(items2, counts2, label="list2", width=0.4, transform=trans2+plt.gca().transData)
plt.legend()
plt.show()

enter image description here

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