-->

Plotting a dictionary with multiple values per key

2020-04-10 06:25发布

问题:

I have a dictionary that looks like this:

1: ['4026', '4024', '1940', '2912', '2916], 2: ['3139', '2464'], 3:['212']...

For a few hundred keys, I'd like to plot them with the key as y for its set of x values, I tried this bit of code which gives the error underneath:

for rank, structs in b.iteritems():
    y = b.keys()
    x = b.values()
    ax.plot(x, y, 'ro')
    plt.show()

ValueError: setting an array element with a sequence

I'm at a bit of a loss on how to proceed so any help would be greatly appreciated!

回答1:

You need to construct your list of Xs and Ys manually:

In [258]: b={1: ['4026', '4024', '1940', '2912', '2916'], 2: ['3139', '2464'], 3:['212']}

In [259]: xs, ys=zip(*((int(x), k) for k in b for x in b[k]))

In [260]: xs, ys
Out[260]: ((4026, 4024, 1940, 2912, 2916, 3139, 2464, 212), (1, 1, 1, 1, 1, 2, 2, 3))

In [261]: plt.plot(xs, ys, 'ro')
     ...: plt.show()

resulting:



回答2:

1) Repeat your x values

plot expects a list of x values and a list of y values which have to have the same length. That's why you have to repeat the rank value several times. itertools.repeat() can do that for you.

2) change your iterator

iteritems() already returns a tuple (key,value). You don't have to use keys() and items().

Here's the code:

import itertools
for rank, structs in b.iteritems():
    x = list(itertools.repeat(rank, len(structs)))
    plt.plot(x,structs,'ro')

3) combine the plots

Using your code, you'd produce one plot per item in the dictionary. I guess you rather want to plot them within a single graph. If so, change your code accrodingly:

import itertools
x = []
y = []
for rank, structs in b.iteritems():
    x.extend(list(itertools.repeat(rank, len(structs))))
    y.extend(structs)
plt.plot(x,y,'ro')

4) example

Here's an example using your data:

import itertools
import matplotlib.pyplot as plt
d = {1: ['4026', '4024', '1940', '2912', '2916'], 2: ['3139', '2464'], 3:['212']}
x= []
y= []
for k, v in d.iteritems():
    x.extend(list(itertools.repeat(k, len(v))))
    y.extend(v)
plt.xlim(0,5)
plt.plot(x,y,'ro')



回答3:

This is because you mismatched your data entries.

Currently you have

1: ['4026', '4024', '1940', '2912', '2916']
2: ['3139', '2464'],
...

hence

x = [1,2,...]
y = [['4026', '4024', '1940', '2912', '2916'],['3139', '2464'],...

when you really need

x = [1, 1, 1, 1, 1, 2, 2, ...]
y = ['4026', '4024', '1940', '2912', '2916', '3139', '2464',...]

Try

for rank, structs in b.iteritems():
    # This matches each value for a given key with the appropriate # of copies of the 
    # value and flattens the list
    # Produces x = [1, 1, 1, 1, 1, 2, 2, ...]
    x = [key for (key,values) in b.items() for _ in xrange(len(values))]

    # Flatten keys list
    # Produces y = ['4026', '4024', '1940', '2912', '2916, '3139', '2464',...]
    y = [val for subl in b.values() for val in subl]

    ax.plot(x, y, 'ro')
    plt.show()