2017-10-17 117 views
0

我可以在matplotlib创建一个简单的柱状图的曲线图:绘制,其中Y轴的文本数据(不是数字),并且X轴的数值数据

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

回答

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

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

UPDATE
(每评论)

为了与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") 
+0

我想问你一两件事。如何为任何长度的字典编写代码。如果字典的长度是任意的,并且我们不想明确指定值(data_labels = ['need1','need2'])。 –

+0

好的,看我更新的答案。 –

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_SRT是按T_OLD中的键排序的OrderedDict对象。

的输出是:

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地图输出显式转换为列表,在Python 2.7中不需要步骤。

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

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

此测试情况下的结果是:

enter image description here

+0

感谢您的帮助,但在Python 3中引发了TypeError错误:'zip'对象不是子脚本。你能告诉我如何解决这个问题吗? –

+0

在Python 3中添加了需要的行,仅供将来参考。 – atru

+0

我想问你一件事。如何为任何长度的字典编写代码。如果字典的长度是任意的,我们不想明确指定值(ax.set_yticklabels(['need1','need2']),....]))。 –

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

+0

感谢您的帮助,但在Python 3中引发了TypeError错误:'zip'对象不是子脚本。你能告诉我如何解决这个问题吗? –

+0

'x = list(zip(* T_OLD.items()))''? – ImportanceOfBeingErnest

+0

我尝试了,但是Python 3引发了错误ValueError:无法将字符串转换为浮点数:'False'( –

相关问题