我有一个如下所示的数据样本:
a 10:15:22 10:15:30 OK
b 10:15:23 10:15:28 OK
c 10:16:00 10:17:10 FAILED
b 10:16:30 10:16:50 OK
我想要的是以下列方式绘制上述数据:
captions ^
|
c | *------*
b | *---* *--*
a | *--*
|___________________
time >
线条的颜色取决于数据点的OK/FAILED
状态。标签(a/b/c/...
)可能重复也可能不重复。
正如我从 gnuplot 和 matplotlib 的文档中收集的那样,这种类型的情节应该更容易在后者中进行,因为它不是标准情节而且会需要一些预处理。
问题是:
答案 0 :(得分:23)
更新:现在包括处理数据样本并使用mpl日期功能。
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, MinuteLocator, SecondLocator
import numpy as np
from StringIO import StringIO
import datetime as dt
### The example data
a=StringIO("""a 10:15:22 10:15:30 OK
b 10:15:23 10:15:28 OK
c 10:16:00 10:17:10 FAILED
b 10:16:30 10:16:50 OK
""")
#Converts str into a datetime object.
conv = lambda s: dt.datetime.strptime(s, '%H:%M:%S')
#Use numpy to read the data in.
data = np.genfromtxt(a, converters={1: conv, 2: conv},
names=['caption', 'start', 'stop', 'state'], dtype=None)
cap, start, stop = data['caption'], data['start'], data['stop']
#Check the status, because we paint all lines with the same color
#together
is_ok = (data['state'] == 'OK')
not_ok = np.logical_not(is_ok)
#Get unique captions and there indices and the inverse mapping
captions, unique_idx, caption_inv = np.unique(cap, 1, 1)
#Build y values from the number of unique captions.
y = (caption_inv + 1) / float(len(captions) + 1)
#Plot function
def timelines(y, xstart, xstop, color='b'):
"""Plot timelines at y from xstart to xstop with given color."""
plt.hlines(y, xstart, xstop, color, lw=4)
plt.vlines(xstart, y+0.03, y-0.03, color, lw=2)
plt.vlines(xstop, y+0.03, y-0.03, color, lw=2)
#Plot ok tl black
timelines(y[is_ok], start[is_ok], stop[is_ok], 'k')
#Plot fail tl red
timelines(y[not_ok], start[not_ok], stop[not_ok], 'r')
#Setup the plot
ax = plt.gca()
ax.xaxis_date()
myFmt = DateFormatter('%H:%M:%S')
ax.xaxis.set_major_formatter(myFmt)
ax.xaxis.set_major_locator(SecondLocator(interval=20)) # used to be SecondLocator(0, interval=20)
#To adjust the xlimits a timedelta is needed.
delta = (stop.max() - start.min())/10
plt.yticks(y[unique_idx], captions)
plt.ylim(0,1)
plt.xlim(start.min()-delta, stop.max()+delta)
plt.xlabel('Time')
plt.show()
答案 1 :(得分:0)
gnuplot with vector
解决方案
最小化于:http://gnuplot.sourceforge.net/demo_5.2/gantt.html
main.gnuplot
#!/usr/bin/env gnuplot
$DATA << EOD
1 1 5
1 11 13
2 3 10
3 4 8
4 7 13
5 6 15
EOD
set terminal png size 512,512
set output "main.png"
set xrange [-1:]
set yrange [0:]
unset key
set border 3
set xtics nomirror
set ytics nomirror
set style arrow 1 nohead linewidth 3
plot $DATA using 2 : 1 : ($3-$2) : (0.0) with vector as 1, \
$DATA using 2 : 1 : 1 with labels right offset -2
输出:
您可以通过删除第二个plot
命令行来删除标签,我之所以添加它们是因为它们在许多应用程序中对于更轻松地识别时间间隔很有用。
我链接到的甘特示例显示了如何处理日期格式而不是整数。
在gnuplot 5.2补丁程序级别2(Ubuntu 18.04)中进行了测试。
答案 2 :(得分:0)
gnuplot 5.2版本,具有创建唯一密钥列表的功能
与@CiroSantilli解决方案的主要区别在于,从第1列自动创建唯一键列表,并且可以通过定义的函数Lookup()
访问索引。所引用的gnuplot演示已经使用了唯一项列表,但是,在OP中,存在重复项。
在gnuplot中并不立即创建这样的唯一项列表,因此您必须自己实现它。
该代码要求gnuplot> = 5.2。可能很难获得在gnuplot 4.4(OP提出问题的时间)下工作的解决方案,因为当时尚未实现一些有用的功能:do for
-循环,summation
,数据块等。 。(某些解决方法可能会使用gnuplot 4.6的版本)。
编辑:较早的版本使用with vectors
和linewidth 20
绘制条形图,但是linewidth 20
也沿x方向延伸,这在此处是不希望的。因此,现在使用with boxxyerror
。
代码:
### Time chart
reset session
$Data <<EOD
# category start end status
"event 1" 10:15:22 10:15:30 OK
"event 2" 10:15:23 10:15:28 OK
pause 10:16:00 10:17:10 FAILED
"something else" 10:16:30 10:17:50 OK
unknown 10:17:30 10:18:50 OK
"event 3" 10:18:30 10:19:50 FAILED
pause 10:19:30 10:20:50 OK
"event 1" 10:17:30 10:19:20 FAILED
EOD
# create list of keys
List = ''
set table $Dummy
plot $Data u (List=List.'"'.strcol(1).'" ',NaN) w table
unset table
# create list of unique keys
UniqueList = ''
do for [i=1:words(List)] {
item = word(List,i)
found = 0
do for [j=1:words(UniqueList)] {
if (item eq word(UniqueList,j)) { found=1; break }
}
if (!found) { UniqueList = UniqueList.'"'.item.'" '}
}
print UniqueList
# define functions for lookup and color
Lookup(s) = (Index = NaN, sum [i=1:words(UniqueList)] \
(Index = s eq word(UniqueList,i) ? i : Index,0), Index)
Color(s) = s eq "OK" ? 0x00cc00 : 0xff0000
set xdata time
set timefmt "%H:%M:%S"
set format x "%M'".'%S"'
set yrange [0.5:words(UniqueList)+0.5]
plot $Data u (timecolumn(2)):(Idx=Lookup(strcol(1))): \
(timecolumn(3)):(timecolumn(2)):(Idx-0.3):(Idx+0.3): \
(Color(strcol(4))):ytic(strcol(1)) \
w boxxyerror fill solid 1.0 lc rgb var notitle
### end of code
结果: