绘制Y轴文本数据(非数字)和X轴数字数据

时间:2017-10-17 18:04:43

标签: python python-3.x dictionary matplotlib plot

我可以根据简单的'在matplotlib中创建一个简单的柱状图。字典:

import matplotlib.pyplot as plt
D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(range(len(D)), D.values(), align='center')
plt.xticks(range(len(D)), D.keys())
plt.show()

enter image description here 但是,我怎么在这个词典的文本和数字数据上创建曲线,我不知道?

Т_OLD = {'10': 'need1', '11': 'need2', '12': 'need1', '13': 'need2', '14': 'need1'}

如下图所示 enter image description here

3 个答案:

答案 0 :(得分:3)

您可以使用numpy将字典转换为具有两列的数组,可以绘制。

import matplotlib.pyplot as plt
import numpy as np

T_OLD = {'10' : 'need1', '11':'need2', '12':'need1', '13':'need2','14':'need1'}
x = list(zip(*T_OLD.items()))
# sort array, since dictionary is unsorted
x = np.array(x)[:,np.argsort(x[0])].T
# let second column be "True" if "need2", else be "False
x[:,1] = (x[:,1] == "need2").astype(int)

# plot the two columns of the array
plt.plot(x[:,0], x[:,1])
#set the labels accordinly
plt.gca().set_yticks([0,1])
plt.gca().set_yticklabels(['need1', 'need2'])

plt.show()

enter image description here

以下是一个版本,它独立于字典的实际内容;唯一的假设是密钥可以转换为浮点数。

import matplotlib.pyplot as plt
import numpy as np

T_OLD = {'10': 'run', '11': 'tea', '12': 'mathematics', '13': 'run', '14' :'chemistry'}
x = np.array(list(zip(*T_OLD.items())))
u, ind = np.unique(x[1,:], return_inverse=True)
x[1,:] = ind
x = x.astype(float)[:,np.argsort(x[0])].T

# plot the two columns of the array
plt.plot(x[:,0], x[:,1])
#set the labels accordinly
plt.gca().set_yticks(range(len(u)))
plt.gca().set_yticklabels(u)

plt.show()

enter image description here

答案 1 :(得分:2)

使用y轴刻度的数值,然后使用plt.yticks()将它们映射到所需的字符串:

import matplotlib.pyplot as plt
import pandas as pd 

# example data
times = pd.date_range(start='2017-10-17 00:00', end='2017-10-17 5:00', freq='H')
data = np.random.choice([0,1], size=len(times))
data_labels = ['need1','need2']

fig, ax = plt.subplots()
ax.plot(times, data, marker='o', linestyle="None")
plt.yticks(data, data_labels)
plt.xlabel("time")

enter image description here

注意:使用折线图来表示时间上的分类变化(例如从need1need2)通常不是一个好主意。这样做会给出时间点之间连续性的视觉印象,这可能不准确。在这里,我将绘图样式更改为点而不是线。如果由于某种原因您需要这些行,只需从调用linestyle="None"中删除plt.plot()

<强>更新
(根据评论)

要使用任意长度的y轴类别集进行此操作,请使用ax.set_yticks()ax.set_yticklabels()映射到y轴值。

例如,给定一组潜在的y轴值labels,让Nlabels子集的大小(此处我们将其设置为4 ,但它可以是任何尺寸)。

然后绘制y值的随机样本data并绘制时间图,根据完整集labels标记y轴刻度。请注意,我们仍然首先使用set_yticks()数字标记,然后使用set_yticklabels()替换我们的类别标签。

labels = np.array(['A','B','C','D','E','F','G'])
N = 4

# example data
times = pd.date_range(start='2017-10-17 00:00', end='2017-10-17 5:00', freq='H')
data = np.random.choice(np.arange(len(labels)), size=len(times))

fig, ax = plt.subplots(figsize=(15,10))
ax.plot(times, data, marker='o', linestyle="None")
ax.set_yticks(np.arange(len(labels)))
ax.set_yticklabels(labels)
plt.xlabel("time")

答案 2 :(得分:2)

这给出了确切的期望图:

import matplotlib.pyplot as plt
from collections import OrderedDict

T_OLD = {'10' : 'need1', '11':'need2', '12':'need1', '13':'need2','14':'need1'}
T_SRT = OrderedDict(sorted(T_OLD.items(), key=lambda t: t[0]))

plt.plot(map(int, T_SRT.keys()), map(lambda x: int(x[-1]), T_SRT.values()),'r')

plt.ylim([0.9,2.1])
ax = plt.gca()
ax.set_yticks([1,2])
ax.set_yticklabels(['need1', 'need2'])

plt.title('T_OLD')
plt.xlabel('time')
plt.ylabel('need')

plt.show()

对于Python 3.X,绘图线需要将map()输出显式转换为列表:

plt.plot(list(map(int, T_SRT.keys())), list(map(lambda x: int(x[-1]), T_SRT.values())),'r')

在Python 3.X map()中返回迭代器而不是Python 2.7中的列表。

该图使用转换为整数的字典键和need1need2的最后一个元素,也转换为整数。这取决于您的数据的特定结构,如果need1need3的值需要更多操作。

在绘制和更改轴限制之后,程序只需修改y位置1和2处的刻度标签。然后它还会添加标题以及x和y轴标签。

重要的是必须对字典/输入数据进行排序。一种方法是使用OrderedDict。此处T_SRTOrderedDict对象,按T_OLD中的键排序。

输出结果为:

enter image description here

这是T_OLD中更多值/标签的更一般情况。它假设标签始终为'needX',其中X为任意数字。对于数字前面的任何字符串的一般情况,可以很容易地做到这一点,尽管它需要更多的处理,

import matplotlib.pyplot as plt
from collections import OrderedDict
import re

T_OLD = {'10' : 'need1', '11':'need8', '12':'need11', '13':'need1','14':'need3'}
T_SRT = OrderedDict(sorted(T_OLD.items(), key=lambda t: t[0]))

x_val = list(map(int, T_SRT.keys()))
y_val = list(map(lambda x: int(re.findall(r'\d+', x)[-1]), T_SRT.values()))

plt.plot(x_val, y_val,'r')

plt.ylim([0.9*min(y_val),1.1*max(y_val)])
ax = plt.gca()
y_axis = list(set(y_val))
ax.set_yticks(y_axis)
ax.set_yticklabels(['need' + str(i) for i in y_axis])

plt.title('T_OLD')
plt.xlabel('time')
plt.ylabel('need')

plt.show()

此解决方案使用re.findall查找标签末尾的数字,以适应多位数字的可能性。之前的解决方案只占用了字符串的最后一个部分,因为数字是单个数字。它仍然假设绘制位置的数字是字符串中的最后一个数字,因此[-1]。再次为Python 3.X映射输出显式转换为list,在Python 2.7中不需要步骤。

现在通过首先使用set选择唯一的y值,然后通过将字符串'need'与其对应的整数串联来重命名其标签来生成标签。

y轴的极限设置为最小值的0.9和最大值的1.1。其余格式与以前一样。

此测试用例的结果是:

enter image description here