在matplotlib中绘制2个词典
我有两本字典:dict1={‘牛肉’:10,‘家禽’:13,‘猪肉’:14,‘羔羊’:11}和dict2={‘牛肉’:3,‘家禽’:1,‘猪肉’:17,‘羔羊’:16} 我想绘制一个双条形图,使用字典键作为x轴值,并在y轴上使用相关值。我正在为此使用matplotlib。有人有任何信息吗?matplotlib文档的一部分可能就是您要查找的内容。要绘制数据,需要从dict中提取x和y值,例如通过在matplotlib中绘制2个词典,matplotlib,Matplotlib,我有两本字典:dict1={‘牛肉’:10,‘家禽’:13,‘猪肉’:14,‘羔羊’:11}和dict2={‘牛肉’:3,‘家禽’:1,‘猪肉’:17,‘羔羊’:16} 我想绘制一个双条形图,使用字典键作为x轴值,并在y轴上使用相关值。我正在为此使用matplotlib。有人有任何信息吗?matplotlib文档的一部分可能就是您要查找的内容。要绘制数据,需要从dict中提取x和y值,例如通过dict.keys()和dict.values() 结果: 我想提出一个更一般的方法:如果我们有一个字典
dict.keys()
和dict.values()
结果:
我想提出一个更一般的方法:如果我们有一个字典列表,会发生什么呢
In [89]: from random import randint, seed, shuffle
...: seed(20201213)
...: cats = 'a b c d e f g h i'.split() # categories
...: # List Of Dictionaries
...: lod = [{k:randint(5, 15) for k in shuffle(cats) or cats[:-2]} for _ in range(5)]
...: lod
Out[89]:
[{'d': 14, 'h': 10, 'i': 13, 'f': 13, 'c': 5, 'b': 5, 'a': 14},
{'h': 12, 'd': 5, 'c': 5, 'i': 11, 'b': 14, 'g': 8, 'e': 13},
{'d': 8, 'a': 12, 'f': 7, 'h': 10, 'g': 10, 'c': 11, 'i': 12},
{'g': 11, 'f': 8, 'i': 14, 'h': 11, 'a': 5, 'c': 7, 'b': 8},
{'e': 11, 'h': 13, 'c': 5, 'i': 8, 'd': 12, 'a': 11, 'g': 11}]
正如您所看到的,键的顺序不同,字典也不包含所有可能的键
我们的第一步是找到一个键列表(lok
),使用set
理解,然后对键进行排序(是的,我们已经知道了键,但这里我们正在寻找一个通用的解决方案…)
两个列表中的元素数为
In [91]: nk, nd = len(lok), len(lod)
在这一点上,我们可以计算单个条的宽度,假设条组之间相距1个单位(因此x=range(nk)
),并且我们在组之间留出1/3个单位,我们得到
In [92]: x, w = range(nk), 0.67/nd
我们已经准备好进行阴谋了
In [93]: import matplotlib.pyplot as plt
...: for n, d in enumerate(lod):
...: plt.bar([ξ+n*w for ξ in x], [d.get(k, 0) for k in lok], w,
...: label='dict %d'%(n+1))
...: plt.xticks([ξ+w*nd/2 for ξ in x], lok)
...: plt.legend();
让我们编写一个小函数
def plot_lod(lod, ws=0.33, ax=None, legend=True):
"""bar plot from the values in a list of dictionaries.
lod: list of dictionaries,
ws: optional, white space between groups of bars as a fraction of unity,
ax: optional, the Axes object to draw into,
legend: are we going to draw a legend?
Return: the Axes used to plot and a list of BarContainer objects."""
from matplotlib.pyplot import subplot
from numpy import arange, nan
if ax is None : ax = subplot()
lok = sorted({k for d in lod for k in d})
nk, nd = len(lok), len(lod)
x, w = arange(nk), (1.0-ws)/nd
lobars = [
ax.bar(x+n*w, [d.get(k, nan) for k in lok], w, label='%02d'%(n+1))
for n, d in enumerate(lod)
]
ax.set_xticks(x+w*nd/2-w/2)
ax.set_xticklabels(lok)
if legend : ax.legend()
return ax, lobars
使用上一个示例的数据,我们得到一个稍微不同的图
参见
In [93]: import matplotlib.pyplot as plt
...: for n, d in enumerate(lod):
...: plt.bar([ξ+n*w for ξ in x], [d.get(k, 0) for k in lok], w,
...: label='dict %d'%(n+1))
...: plt.xticks([ξ+w*nd/2 for ξ in x], lok)
...: plt.legend();
def plot_lod(lod, ws=0.33, ax=None, legend=True):
"""bar plot from the values in a list of dictionaries.
lod: list of dictionaries,
ws: optional, white space between groups of bars as a fraction of unity,
ax: optional, the Axes object to draw into,
legend: are we going to draw a legend?
Return: the Axes used to plot and a list of BarContainer objects."""
from matplotlib.pyplot import subplot
from numpy import arange, nan
if ax is None : ax = subplot()
lok = sorted({k for d in lod for k in d})
nk, nd = len(lok), len(lod)
x, w = arange(nk), (1.0-ws)/nd
lobars = [
ax.bar(x+n*w, [d.get(k, nan) for k in lok], w, label='%02d'%(n+1))
for n, d in enumerate(lod)
]
ax.set_xticks(x+w*nd/2-w/2)
ax.set_xticklabels(lok)
if legend : ax.legend()
return ax, lobars