在 x 轴上具有多个标签的分组条形图
Grouped bar plot with multiple labels in x-axis
我正在尝试在 gnuplot 中复制接近下图的内容,因为我需要在乳胶纸上使用它。我已经尝试了很多,但我无法在底部制作两行标签。你能指导我吗?另外,如何将 % 字符作为 x 轴标签的一部分? Latex 抱怨它。
数据采用以下格式(示例)。每种不同的颜色对应不同的方法。蓝色是方法一(m1),橙色是方法二(m2),棕色是方法三(m3)
#% system1-m1 system1-m2 system1-m3 system2-m1 ...
0.5% 16 8 15 6
1% 15 17 16 8
2% 12 10 20 15
谢谢
编辑
到目前为止我的代码如下:
set rmargin 0
set key outside tmargin center top horizontal width 3
set border
set grid
set boxwidth 0.8
set style fill solid 1.00
set xtics nomirror rotate by 0
set format y '%1.f'
set yrange [0 to 22]
set ylabel 'Gain (\%)'
set ytics 0, 5
set style data histograms
set label 1 at -0.3, -4 '|---------System 1------------|'
set label 2 at 2.7, -4 '|---------System 2------------|'
plot "./data/metrics.dat" using 2:xtic(1) title 'Method 1' ,\
"" using 3 title 'Method 2', \
"" using 4 title 'Method 3',
并且我已经将 .dat 文件修改为
0.5 16 8 15
1.0 15 17 16
2.0 12 10 20
0.5 13 6 4
1.0 11 13 13
2.0 14 12 14
因为我无法让它打印 % 字符。输出图为
如您所见,它不可扩展。我必须手动放置标签(反复试验)并且 x 轴下方的标签不包含 % 字符。
我们已经很接近了:set format x '%.1f\%%'
。以下适用于 cairolatex
终端(检查 help cairolatex
)。
代码:
### percent sign for tic label in TeX
reset session
set term cairolatex
set output 'SO70029830.tex'
set title 'Some \TeX\ or \LaTeX\ title: $a^2 + b^2 = c^2$'
set format x '%.1f\%%'
plot x
set output
### end of code
结果:(截图)
加法:
抱歉,我忘记了你问题的第二部分:标签。
此外,在您的图表中,您使用 xtic(1)
作为抽动标签,即文本格式,因此我上面的回答中的命令 set format x '%.1f\%%'
在这里无济于事。一种可能的解决方案是像这样创建和使用您的特殊 TeX 标签:
myTic(col) = sprintf('%.1f\%%',column(col))
plot $Data using 2:xtic(myTic(1))
对于标签,我会使用箭头和标签。每个直方图都放置在从 0
开始的整数处。因此,箭头必须从 x 值 -0.5
到 2.5
以及从 2.5
到 5.5
。标签位于 x 值 1
和 4
处。当然还有改进的空间。
代码:
### tic labels with % for TeX and lines/labels
reset session
set term cairolatex
set output 'SO70029830.tex'
$Data <<EOD
0.5 16 8 15
1.0 15 17 16
2.0 12 10 20
0.5 13 6 4
1.0 11 13 13
2.0 14 12 14
EOD
set rmargin 0
set key outside center top horizontal width 3
set border
set grid
set boxwidth 0.8
set style fill solid 1.00
set xtics nomirror rotate by 0
set format y '%1.f'
set yrange [0 to 22]
set ylabel 'Gain (\%)'
set ytics 0, 5
set style data histograms
set bmargin 4
set arrow 1 from -0.5, screen 0.05 to 2.5, screen 0.05 heads size 0.05,90
set label 1 at 1, screen 0.05 'System 1' center offset 0,-0.7
set arrow 2 from 2.5, screen 0.05 to 5.5, screen 0.05 heads size 0.05,90
set label 2 at 4, screen 0.05 'System 2' center offset 0,-0.7
myTic(col) = sprintf('%.1f\%%',column(col))
plot $Data using 2:xtic(myTic(1)) title 'Method 1' ,\
"" using 3 title 'Method 2', \
"" using 4 title 'Method 3',
set output
### enf of code
结果:(LaTeX 文档截图)
作为@theozh 答案的替代方案,已经有一个名为 newhistogram
的内置函数,它直接允许将标签放置在 x 轴下方。
在处理涉及 newhistogram
的答案时,我发现了水平键布局的错误,现在由于 Ethan 已修复。因此,借助手头最新的 gnuplot 开发版本,我能够提供一种解决方案,允许进行更多微调,例如更改组间间距的能力。
set terminal cairolatex standalone colour header '\usepackage{siunitx}' size 25cm, 7cm
# generate some random data in your format
N = 7
set print $MYDATA
do for [i=1:N] {
print sprintf('0.5 %f %f %f', rand(0)*20, rand(0)*20, rand(0)*20)
print sprintf('1.0 %f %f %f', rand(0)*20, rand(0)*20, rand(0)*20)
print sprintf("2.0 %f %f %f", rand(0)*20, rand(0)*20, rand(0)*20)
}
unset print
# define the look
set style data histograms
set style fill solid 1.00
set boxwidth 0.8
set key horizontal outside t c width 1
set xr [-1:27]
set xtics nomirror
set ytics out 5 nomirror
set grid y # I don't think vertical grid lines are needed here
set ylabel 'Gain/\%'
set rmargin 0.01
set bmargin 3
关于刻度线,我对@theozh 的回答做了一些调整——因为你已经在使用 LaTeX,你不妨通过 siunitx
解析数字,这将确保数字和单位之间的正确间距:
myTic(col) = sprintf('\SI{%.1f}{\%}',column(col))
您提供的屏幕截图中的垂直分隔标记可以迭代创建:
do for [i=1:N+1] {set arrow i from first -1+(i-1)*4, graph 0 to first -1+(i-1)*4, screen 0 lw 2 nohead}
现在是实际的绘图命令:
plot newhistogram "System 1" offset 0,-0.5 lt 1, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::0::2 title sprintf('Method %.0f',i), \
newhistogram "System 2" offset 0,-0.5 lt 1 at 4, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::3::5 not, \
newhistogram "System 3" offset 0,-0.5 lt 1 at 8, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::6::8 not, \
newhistogram "System 4" offset 0,-0.5 lt 1 at 12, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::9::11 not, \
newhistogram "System 5" offset 0,-0.5 lt 1 at 16, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::12::14 not, \
newhistogram "System 6" offset 0,-0.5 lt 1 at 20, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::15::17 not, \
newhistogram "System 7" offset 0,-0.5 lt 1 at 24, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::18::20 not
这看起来很恶心,这是怎么回事?
newhistogram
创建一组新的直方图框,它的第一个参数是一个放在 x 轴下方的字符串。它还被告知将线型计数器重置为 1。
然后迭代地绘制数据的三列,但不是一次绘制所有行,而是仅绘制前三行,以及相应的键条目。
然后创建另一个新直方图,并告知它从 x 值 4 开始(无论如何这将是默认值)。现在绘制了接下来的三行,依此类推。
现在,每次调用 newhistogram
时,都会在键中添加一个空行,从而给键的放置带来麻烦。因此Ethan引入的新关键字是
set style histogram nokeyseparators
这将禁用此行为。
如您所见,组之间的空间比内部大。您可能想要更改 newhistogram at ...
中的数字并相应地调整垂直线位置的计算。
plot命令当然是重复性很强的,做成迭代调用就好了。不幸的是,跨越多个对象的迭代在 plot
调用中是不可能的。但是,可以迭代地将绘图命令字符串放在一起(过度使用字符串连接.
),然后绘制它。
A = 'newhistogram "System '
B = '" offset 0,-0.5 lt 1'
C = 'for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::'
myplotstring = A.'1'.B.', '.C."0::2 title sprintf('Method %.0f',i),"
do for [i=2:N] {myplotstring = myplotstring.A.i.B.'at '.(4*(i-1)).', '.C.(3*i-3).'::'.(3*i-1).' not, '}
plot @myplotstring
我正在尝试在 gnuplot 中复制接近下图的内容,因为我需要在乳胶纸上使用它。我已经尝试了很多,但我无法在底部制作两行标签。你能指导我吗?另外,如何将 % 字符作为 x 轴标签的一部分? Latex 抱怨它。
数据采用以下格式(示例)。每种不同的颜色对应不同的方法。蓝色是方法一(m1),橙色是方法二(m2),棕色是方法三(m3)
#% system1-m1 system1-m2 system1-m3 system2-m1 ...
0.5% 16 8 15 6
1% 15 17 16 8
2% 12 10 20 15
谢谢
编辑
到目前为止我的代码如下:
set rmargin 0
set key outside tmargin center top horizontal width 3
set border
set grid
set boxwidth 0.8
set style fill solid 1.00
set xtics nomirror rotate by 0
set format y '%1.f'
set yrange [0 to 22]
set ylabel 'Gain (\%)'
set ytics 0, 5
set style data histograms
set label 1 at -0.3, -4 '|---------System 1------------|'
set label 2 at 2.7, -4 '|---------System 2------------|'
plot "./data/metrics.dat" using 2:xtic(1) title 'Method 1' ,\
"" using 3 title 'Method 2', \
"" using 4 title 'Method 3',
并且我已经将 .dat 文件修改为
0.5 16 8 15
1.0 15 17 16
2.0 12 10 20
0.5 13 6 4
1.0 11 13 13
2.0 14 12 14
因为我无法让它打印 % 字符。输出图为
如您所见,它不可扩展。我必须手动放置标签(反复试验)并且 x 轴下方的标签不包含 % 字符。
我们已经很接近了:set format x '%.1f\%%'
。以下适用于 cairolatex
终端(检查 help cairolatex
)。
代码:
### percent sign for tic label in TeX
reset session
set term cairolatex
set output 'SO70029830.tex'
set title 'Some \TeX\ or \LaTeX\ title: $a^2 + b^2 = c^2$'
set format x '%.1f\%%'
plot x
set output
### end of code
结果:(截图)
加法:
抱歉,我忘记了你问题的第二部分:标签。
此外,在您的图表中,您使用 xtic(1)
作为抽动标签,即文本格式,因此我上面的回答中的命令 set format x '%.1f\%%'
在这里无济于事。一种可能的解决方案是像这样创建和使用您的特殊 TeX 标签:
myTic(col) = sprintf('%.1f\%%',column(col))
plot $Data using 2:xtic(myTic(1))
对于标签,我会使用箭头和标签。每个直方图都放置在从 0
开始的整数处。因此,箭头必须从 x 值 -0.5
到 2.5
以及从 2.5
到 5.5
。标签位于 x 值 1
和 4
处。当然还有改进的空间。
代码:
### tic labels with % for TeX and lines/labels
reset session
set term cairolatex
set output 'SO70029830.tex'
$Data <<EOD
0.5 16 8 15
1.0 15 17 16
2.0 12 10 20
0.5 13 6 4
1.0 11 13 13
2.0 14 12 14
EOD
set rmargin 0
set key outside center top horizontal width 3
set border
set grid
set boxwidth 0.8
set style fill solid 1.00
set xtics nomirror rotate by 0
set format y '%1.f'
set yrange [0 to 22]
set ylabel 'Gain (\%)'
set ytics 0, 5
set style data histograms
set bmargin 4
set arrow 1 from -0.5, screen 0.05 to 2.5, screen 0.05 heads size 0.05,90
set label 1 at 1, screen 0.05 'System 1' center offset 0,-0.7
set arrow 2 from 2.5, screen 0.05 to 5.5, screen 0.05 heads size 0.05,90
set label 2 at 4, screen 0.05 'System 2' center offset 0,-0.7
myTic(col) = sprintf('%.1f\%%',column(col))
plot $Data using 2:xtic(myTic(1)) title 'Method 1' ,\
"" using 3 title 'Method 2', \
"" using 4 title 'Method 3',
set output
### enf of code
结果:(LaTeX 文档截图)
作为@theozh 答案的替代方案,已经有一个名为 newhistogram
的内置函数,它直接允许将标签放置在 x 轴下方。
在处理涉及 newhistogram
的答案时,我发现了水平键布局的错误,现在由于 Ethan 已修复。因此,借助手头最新的 gnuplot 开发版本,我能够提供一种解决方案,允许进行更多微调,例如更改组间间距的能力。
set terminal cairolatex standalone colour header '\usepackage{siunitx}' size 25cm, 7cm
# generate some random data in your format
N = 7
set print $MYDATA
do for [i=1:N] {
print sprintf('0.5 %f %f %f', rand(0)*20, rand(0)*20, rand(0)*20)
print sprintf('1.0 %f %f %f', rand(0)*20, rand(0)*20, rand(0)*20)
print sprintf("2.0 %f %f %f", rand(0)*20, rand(0)*20, rand(0)*20)
}
unset print
# define the look
set style data histograms
set style fill solid 1.00
set boxwidth 0.8
set key horizontal outside t c width 1
set xr [-1:27]
set xtics nomirror
set ytics out 5 nomirror
set grid y # I don't think vertical grid lines are needed here
set ylabel 'Gain/\%'
set rmargin 0.01
set bmargin 3
关于刻度线,我对@theozh 的回答做了一些调整——因为你已经在使用 LaTeX,你不妨通过 siunitx
解析数字,这将确保数字和单位之间的正确间距:
myTic(col) = sprintf('\SI{%.1f}{\%}',column(col))
您提供的屏幕截图中的垂直分隔标记可以迭代创建:
do for [i=1:N+1] {set arrow i from first -1+(i-1)*4, graph 0 to first -1+(i-1)*4, screen 0 lw 2 nohead}
现在是实际的绘图命令:
plot newhistogram "System 1" offset 0,-0.5 lt 1, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::0::2 title sprintf('Method %.0f',i), \
newhistogram "System 2" offset 0,-0.5 lt 1 at 4, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::3::5 not, \
newhistogram "System 3" offset 0,-0.5 lt 1 at 8, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::6::8 not, \
newhistogram "System 4" offset 0,-0.5 lt 1 at 12, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::9::11 not, \
newhistogram "System 5" offset 0,-0.5 lt 1 at 16, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::12::14 not, \
newhistogram "System 6" offset 0,-0.5 lt 1 at 20, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::15::17 not, \
newhistogram "System 7" offset 0,-0.5 lt 1 at 24, for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::18::20 not
这看起来很恶心,这是怎么回事?
newhistogram
创建一组新的直方图框,它的第一个参数是一个放在 x 轴下方的字符串。它还被告知将线型计数器重置为 1。
然后迭代地绘制数据的三列,但不是一次绘制所有行,而是仅绘制前三行,以及相应的键条目。
然后创建另一个新直方图,并告知它从 x 值 4 开始(无论如何这将是默认值)。现在绘制了接下来的三行,依此类推。
现在,每次调用 newhistogram
时,都会在键中添加一个空行,从而给键的放置带来麻烦。因此Ethan引入的新关键字是
set style histogram nokeyseparators
这将禁用此行为。
如您所见,组之间的空间比内部大。您可能想要更改 newhistogram at ...
中的数字并相应地调整垂直线位置的计算。
plot命令当然是重复性很强的,做成迭代调用就好了。不幸的是,跨越多个对象的迭代在 plot
调用中是不可能的。但是,可以迭代地将绘图命令字符串放在一起(过度使用字符串连接.
),然后绘制它。
A = 'newhistogram "System '
B = '" offset 0,-0.5 lt 1'
C = 'for [i=1:3] $MYDATA using (column(i+1)):xtic(myTic(1)) every ::'
myplotstring = A.'1'.B.', '.C."0::2 title sprintf('Method %.0f',i),"
do for [i=2:N] {myplotstring = myplotstring.A.i.B.'at '.(4*(i-1)).', '.C.(3*i-3).'::'.(3*i-1).' not, '}
plot @myplotstring