使用 GNUPlot 从单个数据集中绘制多个图形

Multiple graphs from a single data set with GNUPlot

我正在尝试使用 gnuplot v5.4 从一个数据集中生成多个图表,尽管每个图表使用来自集合的 select 数据。

我为我正在开发的一个小程序生成统计信息,并将它们写入 CSV 文件:

(这种 CSV 格式正是我取得最大进展的格式 - 我愿意改变)

TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60

下面给了我下面的图表:

cat <<"EOF" | gnuplot -p
$db <<DB
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
DB

set terminal windows size 2000,1000 enhanced font 'Arial,8'

set datafile separator ','
set yrange [0:100]
set boxwidth 0.1 relative
set style fill solid 1.0

plot $db using 2:xticlabel(1) notitle with boxes linestyle 1
EOF

我的目标是:

我用这个实现了:

cat <<"EOF" | gnuplot -p
$db <<DB
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
DB

set terminal windows size 2000,1000 enhanced font 'Arial,8'

set datafile separator ','
set yrange [0:100]
set boxwidth 0.1 relative
set style fill solid 1.0

set multiplot layout 1,2

plot $db using 2:xticlabel(1) every ::1::2 notitle with boxes linestyle 1
plot $db using 2:xticlabel(1) every ::3::4 notitle with boxes linestyle 1

unset multiplot
EOF

是否有更好或更惯用的方法 select 从数据文件中绘制 'rows' 的内容?这些索引(在 every 子句中)工作正常,但看起来很脆弱。

我以前使用过这样的技巧,其中在 using 中返回未定义的三元将导致 gnuplot 忽略该行(例如,也许我可以根据字符串比较将它用于 select)但是那看起来也没有更优雅,我真的不喜欢它使 plot 命令变得多么复杂。

如果您能灵活处理输入数据,我会按以下方式组织: 我不会将所有内容都转储到一个文件中并再次将其分开,而是创建两个文件,例如'Counts.dat''Scores.dat'.

在下面的(复制和粘贴)示例中,它包含在带有数据块 $Counts$Scores 的代码中,但是,如果您的数据在文件中,只需跳过数据块和绘图命令将其分别更改为 'Counts.dat''Scores.dat'。 您不一定需要数据中的总数,gnuplot 可以为您完成这项工作。 此外,在下面的示例中,我为框的颜色引入了第三列。检查以下示例作为进一步优化的起点。

代码:

### multiplot with boxes and total sum
reset session

$Counts <<EOD
Red     12    0xff0000
Green    5    0x00cc00
Blue    10    0x0000ff
Yellow   7    0xffff00
EOD

$Scores <<EOD
Red     60    0xff0000
Green   30    0x00cc00
Blue    50    0x0000ff
Yellow  80    0xffff00
EOD

set yrange[0:100]
set boxwidth 0.5 relative
set style fill solid 1.0
set key left noautotitle
set grid x,y

set multiplot layout 1,2

    set title "Counts"
    plot sum=0 $Counts u 0:(sum=sum+column(2),column(2)):3:xtic(1) w boxes lc rgb var, \
         keyentry w p ps 0 ti sprintf("Total count: %d",sum)

    set title "Scores"
    plot $Scores u 0:2:3:xtic(1) w boxes lc rgb var

unset multiplot
### end of code

结果:

加法:(一个数据块或文件中的所有数据)

代码:

### multiplot with boxes and total sum in a single file
reset session

$AllInOne <<EOD
# counts
Red     12    0xff0000
Green    5    0x00cc00
Blue    10    0x0000ff
Yellow   7    0xffff00


# scores
Red     60    0xff0000
Green   30    0x00cc00
Blue    50    0x0000ff
Yellow  80    0xffff00
EOD

set yrange[0:100]
set boxwidth 0.5 relative
set style fill solid 1.0
set key left noautotitle
set grid x,y

set multiplot layout 1,2

    set title "Counts"
    plot sum=0 $AllInOne u 0:(sum=sum+column(2),column(2)):3:xtic(1) index 0 w boxes lc rgb var, \
         keyentry w p ps 0 ti sprintf("Total count: %d",sum)

    set title "Scores"
    plot $AllInOne u 0:2:3:xtic(1) index 1 w boxes lc rgb var

unset multiplot
### end of code

为您提供更“可读”语法的一种可能性是使用 columnheaders,为此您需要转置您的数据集。您不一定需要使用逗号;空格或制表符也可以解决问题:

$db <<DB
TotalPlayerCount BluePlayerCount RedPlayerCount BluePlayerScoreTotal RedPlayerScoreTotal
22 10 12 50 60
DB

设置布局:

set xrange [0:3]
set yrange [0:100]
set boxwidth 0.5
set style fill solid 1.0

现在您可以 select 您想要使用 column("string") 绘制的列,这将为您提供正确的 y 值。至于 x 值,我只是为第一个图取常数 1,为第二个图取 2。为了生成 xticlabels,必须重复字符串:

plot $db u (1):(column("BluePlayerCount")):xticlabels("BluePlayerCount") w boxes not, \
$db u (2):(column("RedPlayerCount")):xticlabels("RedPlayerCount") w boxes not

或者,您可以从 plot 命令中删除 xticlabels 部分,而是使用:set xtics ("BluePlayerCount" 1, "RedPlayerCount" 2)

您还可以进一步自动化绘图:

whattoplot_1 = "BluePlayerCount"
whattoplot_2 = "RedPlayerCount"
x_pos_1 = 1
x_pos_2 = 2
set xtics (whattoplot_1 x_pos_1, whattoplot_2 x_pos_2)
plot $db u (x_pos_1):(column(whattoplot_1)) w boxes not, \
$db u (x_pos_2):(column(whattoplot_2)) w boxes not

根据你最终想要达到的效果,你可以考虑使用数组并遍历元素:

array whattoplot[2] = ["BluePlayerCount", "RedPlayerCount"]
plot for [i=1:|whattoplot|] $db u (i):(column(whattoplot[i])) w boxes not

我希望这能给你一些灵感,让你继续前进!