【问题标题】:Stacked and grouped bar histogram with Gnuplot使用 Gnuplot 的堆叠和分组条形直方图
【发布时间】:2014-02-03 00:01:35
【问题描述】:

我想重现像this one 这样的条形图,即:多个组,每个组有许多条(在我的情况下为 4 个条),每个条被分割成几片(在我的情况下为两片)。

在我的例子中,我有四种算法应用于不同大小的向量(2^0 到 2^20)。每个算法都有两个“部分”,本地计算和通信。对于每个向量大小,我想显示每个算法执行本地计算和通信所需的时间,以及对应于这两个部分总和的总时间。

因此,我希望为每个矢量大小设置一个组。在每组中,有四个条形对应于四种算法,每个条形被分割为(例如)对应于本地计算的红色部分和对应于通信的蓝色部分。

这对 gnuplot 可行吗?我可以提供任何有用格式的数据。

非常感谢。

【问题讨论】:

  • 示例数据和示例脚本将极大地帮助您获得答案。 :) 还要指出你的脚本中缺少什么以及你尝试了什么。
  • 当然。我在此处放置了我的数据样本:pastebin.com/vtemLn98。由于我是一个绝对的初学者(我正在从 Matlab 转移到 gnuplot),我什至不知道我想做的事情是否可行(例如,在 Matlab 中,除非你去低级或应用一些不寻常的东西,否则这是不可能的技巧),所以我还没有开始编写脚本。

标签: gnuplot histogram


【解决方案1】:

对于您的数据集,堆叠本地和通信部分没有意义,因为通信部分太小而无法在图表中看到。在任何情况下,根据进一步的要求(图例条目、刻度标签等),组合堆叠和集群也是非常棘手的。

以下是如何为您的数据集绘制聚类直方图的示例:

set style histogram clustered gap 1
set style data histogram
set style fill solid 1.0 noborder

set termoption enhanced

set xtics out nomirror

myxtic(x) = sprintf('2^{%d}', int(floor(log(x)/log(2) + 0.5)))
plot 'test.dat' using ($2+$3):xtic(myxtic(stringcolumn(1))) title 'Algorithm 1',\
     for [i=2:4] '' using (column(2*i)+column(2*i+1)) title sprintf('Algorithm %d', i)

结果是:

要按算法分组,您可以使用newhistogram 关键字创建新组:

set style histogram rowstacked title offset 4,1
set boxwidth 0.9 relative
set style fill solid 1.0 border lt -1
set xtics rotate by 90 right
plot newhistogram "Algorithm 1" lt 1,\
     'test.dat' using 2:xtic(1) title columnheader, \
     '' using 3 title columnheader,\
     newhistogram "Algorithm 2" lt 1,\
     'test.dat' using 4:xtic(1) notitle, \
     '' using 5 notitle,\
     newhistogram "Algorithm 3" lt 1,\
     'test.dat' using 6:xtic(1) notitle, \
     '' using 7 notitle,\
     newhistogram "Algorithm 4" lt 1,\
     'test.dat' using 8:xtic(1) notitle, \
     '' using 9 notitle

localcomm 数据是堆叠在一起的,但 comm 部分太小了,以至于您无法在图表中看到它(仅当您放大时)。

对于我使用 4.6.3 和以下设置的输出:

set terminal pngcairo size 1000,400
set output 'test.png'
set xtics font ',6'

结果是:

更复杂的 xtics 显示需要一些技巧,因为对于直方图,xtics 不被视为数字,而是字符串。这是一个例子:

set terminal pngcairo size 1000,400
set output 'test.png'

set style histogram rowstacked title offset 0,-0.5
set bmargin 3
set boxwidth 0.9 relative
set style fill solid 1.0 border lt -1
set termoption enhanced
set xtics out nomirror
myxtic(x) = (int(floor(log(x)/log(2) + 0.5)) % 5 == 0) ? sprintf('2^{%d}', int(floor(log(x)/log(2) + 0.5))) : ""

plot newhistogram "Algorithm 1" lt 1,\
     'test.dat' using 2:xtic(myxtic(real(stringcolumn(1)))) title columnheader, \
     '' using 3 title columnheader,\
     newhistogram "Algorithm 2" lt 1,\
     'test.dat' using 4:xtic(myxtic(real(stringcolumn(1)))) notitle, \
     '' using 5 notitle,\
     newhistogram "Algorithm 3" lt 1,\
     'test.dat' using 6:xtic(myxtic(real(stringcolumn(1)))) notitle, \
     '' using 7 notitle,\
     newhistogram "Algorithm 4" lt 1,\
     'test.dat' using 8:xtic(myxtic(real(stringcolumn(1)))) notitle, \
     '' using 9 notitle

结果

【讨论】:

  • 嗨克里斯托夫。这看起来不错,但我希望能够更直接地比较这些算法的运行时间,即将不同算法的结果直接放在另一个旁边。换句话说,分组不应该根据算法进行,而是根据大小进行。我从你的代码中学到了很多东西。您基本上创建了 4 个不同的直方图并将它们放在另一个旁边。有没有办法把它放在一个循环中,以避免写太多?
  • 抱歉,我错过了真正的要点;)我更新了我的答案。在这种情况下,您需要一个聚集直方图。这不允许您堆叠本地和通信数据,但这对您提供的数据也没有意义。通讯部分太小了,看不到。将集群与堆叠结合起来会变得非常棘手(尚未)尝试过。
  • 您说提供的数据不适合这种情节是完全正确的。实际上,我忘记了必须将每一列除以第一个算法的“comm”和“local”之和。您的旧图看起来非常好,它们只是以一种不太方便比较数据的方式分组。使用 plot 的“for”选项生成多个直方图是否有意义?