Reputation: 65
I apologize in advanced if this is a noob question (my first attempt at matpotlib). I have a dictionary with a length of about 70 and the values are a list of max length 2 elements, example:
dictionary = {
'Product Name 1' : [10.99,20.99],
'Product Name 2' : [50.99,10.99],
'Product Name 3' : [40.00,15.99],
'Product Name 4' : [50.00],
'Product Name 5' : [50.00]
}
I have tried the following code:
import matplotlib.pyplot as plt
import numpy as np
c = []
v = []
for key, val in dictionary.items():
c.append(key)
v.append(val)
v = np.array(v)
plt.bar(range(len(c)), v[:,0])
plt.bar(range(len(c)), v[:,1], bottom=v[:,0])
plt.xticks(range(len(c)), c)
plt.show()
I am getting an index error when plt.bar, too many indices for array.
Upvotes: 1
Views: 3604
Reputation: 4547
Let's first focus on your dictionary. Each key is associated with a list, that can contain up to two elements. When you execute the following piece of code,
dictionary = {
'Product Name 1' : [10.99,20.99],
'Product Name 2' : [50.99,10.99],
'Product Name 3' : [40.00,15.99],
'Product Name 4' : [50.00],
'Product Name 5' : [50.00]
}
print(dictionary.values())
# dict_values([[10.99, 20.99], [50.99, 10.99], [40.0, 15.99], [50.0], [50.0]])
you can see the output takes the shape of a list of sub-lists, each sub-list containing the values associated with a specific key. However, not all lists have the same length. This is a problem as you want to convert your list to a numpy array. Indeed, you cannot generate an array with inconsistent dimensions. As a result, you get an array of dtype object
that is just storing the sub-lists as before.
import numpy as np
print(np.array([x for x in dictionary.values()]))
print(np.array([x for x in dictionary.values()]).dtype)
# [list([10.99, 20.99]) list([50.99, 10.99]) list([40.0, 15.99])
# list([50.0]) list([50.0])]
# object
This is why you get an IndexError when you try to slice your numpy array, because you simply cannot. I propose a solution below. The keys and values are gathered using list comprehensions. Two bar plots are produced, one for each potential entry in your original dictionary lists. For each bar plot, the height of the bars is determined using a list comprehension. The first one simply fetches the first item of the list. The second one fetches the second item if it exists, otherwise, it uses 0. FInally, the ticks on the X axis are updated to reflect the dictionary keys.
import matplotlib.pyplot as plt
import numpy as np
dictionary = {
'Product Name 1' : [10.99,20.99],
'Product Name 2' : [50.99,10.99],
'Product Name 3' : [40.00,15.99],
'Product Name 4' : [50.00],
'Product Name 5' : [50.00]
}
keys = [key for key in dictionary.keys()]
values = [value for value in dictionary.values()]
fig, ax = plt.subplots()
ax.bar(np.arange(len(keys)) - 0.2, [value[0] for value in values],
width=0.2, color='b', align='center')
ax.bar(np.arange(len(keys)) + 0.2,
[value[1] if len(value) == 2 else 0 for value in values],
width=0.2, color='g', align='center')
ax.set_xticklabels(keys)
ax.set_xticks(np.arange(len(keys)))
plt.show()
Upvotes: 2