我有一个看起来像这样的数据文件:
0;State a
1;State a
2;State b
3:State b
4:State a
第一列表示以秒为单位的时间,第二列表示某种状态。
我想在gnuplot中随时间绘制事件的出现。我正在尝试使用以下内容进行绘图:
set datafile separator ";"
plot 'data' using 1:2:yticlabels(2)
但是我收到以下错误:
warning: Skipping data file with no valid points
^
x range is invalid
似乎gnuplot不会将字符串识别为分类值。结果应该看起来像一个非连续的阶梯函数:
^
State b┼ ┌───────┐
│ │ │
State a┼───────┘ └────
│
┼───┼───┼───┼───┼───┼─>
0 1 2 3 4 5
这种情节可以用gnuplot吗?如果,你会怎么做?
答案 0 :(得分:2)
不,gnuplot不会将字符串识别为分类值。你必须做那些作业"字符串→整数"自己。
执行此映射的最简单方法是使用awk
之类的外部工具,并即时添加整数值。以下awk
调用执行此映射并将值添加到输出:
awk -F ';' -v OFS=';' '{
if (!($2 in array)) {
array[$2] = length(array)
}
print $1,$2,array[$2]
}' data.csv
使用gnuplot语法
plot "< awk ..."
您可以直接将awk
电话与绘图结合起来:
set datafile separator ";"
set offset 0.1,0.1,0.1,0.1
set xtics 0,1
plot "< awk -F ';' -v OFS=';' '{if (!($2 in array)) { array[$2] = length(array) }; print $1,$2,array[$2]}' data.csv" using 1:3:ytic(2) w step lw 3 notitle
输出
或者,如果您无法访问awk
,则也可以使用例如cat.py
进行预处理。像以下from __future__ import print_function
import sys
a={}
with open(sys.argv[1], 'r') as f:
for line in f:
fields = line.strip().split(';')
if (not fields[1] in a):
a[fields[1]] = len(a)
print("{0};{1};{2}".format(fields[0], fields[1], a[fields[1]]), file=sys.stdout)
一样的python脚本:
plot "< python cat.py data.csv" ...
并用
调用它quantity_traded < 20000
旁注:也许也可以使用gnuplot来做这件事,但这可能会变得非常难看,请参阅Gnuplot, plotting a graph with text on y axis了解类似的用例。
答案 1 :(得分:0)
由于只有两种状态,我不认为这符合 gnuplot不是数据处理工具判决(虽然该语句通常是正确的!)。
这应符合条例草案:
f(s) = s eq "state a" ? 0 : s eq "state b" ? 1 : NaN
set dataf sep ";"
plot dataf using 1:(f(stringcolumn(2))) with steps # or fsteps
如果你有十几个不同的状态,那就是另一个故事。
说明:您需要stringcolumn()
函数,因为column(2)
或$2
会返回一个fp编号,如果他们找不到可以转换为数字的错误,则会出错。
=
运算符仅比较数值,您必须使用eq
。
并且?B:C是ternary operator
,如果A == 0则返回C,否则返回B.