我有这样的数据集(文件名“data”):
a 10.1
b 10.1
c 10.2
b 15.56
a 3.20
plot 'data' using 2:xticlabels(1)
我的真实数据文件如下所示:
2-8-16-17-18 962.623408
2-3-4-5-6 -97.527840
2-8-9-10-11 962.623408
2-8-9-10-11 937.101308
2-3-4-5-6 37.101308
我不知道如何使用 mgilson 的代码,但他给了我一个想法。我向数据文件添加附加列(索引):
1 a 10.1
2 b 10.1
3 c 10.2
2 b 15.56
1 a 3.20
之后在 gnuplot 中绘图就很容易了: plot 'data' u 1:3
我使用 perl,所以我的脚本看起来像这样:
#!/usr/bin/perl
$index_number = 0;
while (<>)
{
$line = $_;
@columns = split(" ",$line);
$col1 = $columns[0];
$col2 = $columns[1];
if( not exists $non_numeric{$col1} )
{
$index_number++;
$non_numeric{$col1} = $index_number;
}
print "".$non_numeric{$col1}."\t".$col1."\t".$col2."\n";
}
我怀疑你能否想出一个仅限 gnuplot 的解决方案。然而,只要您的系统上安装了 python2.5 或更高版本,这个应该就可以工作。 (它适用于您的测试数据)。
import sys
import collections
data = collections.defaultdict(list)
keys = []
# build a mapping which maps values to xticlabels (hereafter "keys")
# Keep a second keys list so we can figure out the order we put things into
# the mapping (dict)
with open(sys.argv[1]) as f:
for line in f:
key,value = line.split()
data[key.strip()].append( value )
keys.append(key.strip())
def unique(seq):
"""
Simple function to make a sequence unique while preserving order.
Returns a list
"""
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x) ]
keys = unique(keys) #make keys unique
#write the keys alongside 1 element from the corresponding list.
for k in keys:
sys.stdout.write( '%s %s\n' % (k, data[k].pop()) )
# Two blank lines tells gnuplot the following is another dataset
sys.stdout.write('\n\n')
# Write the remaining data lists in order assigning x-values
# for each list (starting at 0 and incrementing every time we get
# a new key)
for i,k in enumerate(keys):
v = data[k]
for item in v:
sys.stdout.write( '%d %s\n' % (i, item) )
现在是绘制此图的脚本:
set style line 1 lt 1 pt 1
plot '<python pythonscript.py data' i 0 u 2:xticlabels(1) ls 1,\
'' i 1 u 1:2 ls 1 notitle
这就是它的工作原理。当您执行类似
plot ... u 2:xticlabels(1)
之类的操作时,gnuplot 隐式 会将连续的整数 x 值分配给数据点(从 0 开始)。 python 脚本重新排列数据以利用这一事实。基本上,我创建一个映射,将第一列中的“键”映射到与该键对应的元素列表。换句话说,在虚拟数据文件中,键 'a'
映射到值列表 [10.1, 3.2]
。但是,Python 字典(映射)不是有序的。因此,我保留了第二个列表来维护顺序(例如,轴被标记为“a”、“b”、“c”,而不是“c”、“a”、“b”)。我确保轴列表是唯一的,以便我可以使用它来打印必要的数据。我分两遍写入数据。第一遍仅打印每个列表中的一个值以及映射“键”。第二遍打印其余的值以及 gnuplot 将隐式分配给它们的 x 值。在两个数据集之间,我插入了 2 个空行,以便 gnuplot 可以使用 index
关键字(此处缩写为 i
)来找出差异。现在我们只需相应地绘制两个数据集即可。首先,我们设置线条样式,以便绘制时两个通道具有相同的样式。然后我们使用 xticlabels 绘制索引 0(第一个数据集),使用 python 脚本计算的 x 值、y 值对绘制索引 1 (u 1:2
)。抱歉,解释很长(并且原始版本略有错误)。祝你好运,gnuplot 快乐!
仅供记录,有 is 一个不太复杂的 gnuplot-only 解决方案! 正如OP已经写的那样,它不能简单地通过
plot FILE u 2:xtic(1)
来完成。
解决方案是克里斯托夫答案的变体和混合 Gnuplot,在 y 轴上绘制带有文本的图形以及我对如何使用 Gnuplot 对字符串及其数据进行分组?
的回答工作原理:
myX(col)
:逐行绘制数据时:如果在字符串变量list
中尚未找到(x列的)字符串,则将其用引号括起来,将计数器c
增加1并将 c
的值也添加到列表中,并返回当前字符串的索引最后,下例中字符串
list
的值将是:
"a" 1 "b" 2 "c" 3
index(list,s)
将通过匹配子字符串s
(检查list
)并提取后续数字来返回s
中help strstrt
的索引。数据:
SO12123578.dat
a 10.1
b 10.1
c 10.2
b 15.56
a 3.20
脚本:(至少适用于 gnuplot>=4.4.0,2010 年 3 月)
### use string values as x-values
reset
FILE = "SO12123578.dat"
list = ''
c = 0
index(list,s) = (_n=strstrt(list,s)) ? int(word(list[_n+strlen(s):],1)) : 0
myX(col) = (_s='"'.strcol(col).'"', strstrt(list, _s) ? '' : list=list.sprintf('%s %d ',_s,c=c+1), index(list,_s))
set offset 1,1,1,1
plot FILE u(myX(1)):2:xtic(1) w p pt 7 lc rgb "red" notitle
### end of script
结果: