【问题标题】:How to control how many xlabels are printed in gnuplot?如何控制在 gnuplot 中打印多少 xlabel?
【发布时间】:2020-11-14 13:50:00
【问题描述】:

我正在使用带有数据矩阵的 Gnuplot 的颜色盒来显示日常活动的热图样式:

数据文件的示例部分:

Week commencing,29 Jun 2020,06 Jul 2020,13 Jul 2020,20 Jul 2020,27 Jul 2020,03 Aug 2020,10 Aug 2020,17 Aug 2020,24 Aug 2020,31 Aug 2020,07 Sep 2020,14 Sep 2020,21 Sep 2020,28 Sep 2020,05 Oct 2020,12 Oct 2020,19 Oct 2020,26 Oct 2020,02 Nov 2020,09 Nov 2020
Mon,11,6,0,4,4,9,10,7,5,0,22,10,9,8,9,2,4,11,11,7
Tues,3,5,0,6,3,4,11,3,6,12,6,3,4,4,9,12,2,1,8,2
Weds,10,1,0,9,4,1,6,5,6,3,2,5,1,5,7,5,8,10,2,12
Thurs,6,3,0,8,3,2,7,14,10,12,14,8,1,3,19,11,8,16,3,7
Fri,16,1,2,5,10,3,0,1,10,1,13,10,0,10,6,10,7,4,9,5
Sat,6,6,8,21,2,7,0,11,0,7,2,23,2,8,11,11,5,3,12,0
Sun,8,7,3,1,8,2,8,2,2,2,6,6,3,3,2,2,4,5,8,0

使用此脚本:

DATAFILE="done_tasks_matrix.csv"
set term png size 800, 300 font "Avenir,9"
set datafile separator comma columnheaders
set palette rgbformula -9,2,-9
set cbrange [0:*]
set cblabel "Completed tasks (Goals + Projects + Other)"
unset cbtics
set xrange writeback
set yrange [6.5:-0.5] writeback # to get it displaying Mon->Sun not Sun->Mon down the page
set xdata time
set timefmt "%d %b %Y" # format of the dates in the input
set format x "%d %b" # format of dates to show
set output "/Users/jonathan/Dropbox/NPSummaries/done_tasks_heatmap.png"
plot DATAFILE matrix rowheaders columnheaders using 1:2:3 with image, \
     DATAFILE matrix rowheaders columnheaders using 1:2:($3 == 0 ? "" : sprintf("%g",$3) ) with labels font ",8" tc rgb "#22BB22"

随着我收集更多数据,xlabels 重叠。我找不到一种方法让它只显示 1 in n 个标签。但是,在日期为 xlabel 的简单折线图上,Gnuplot 似乎会自动删除标签以确保它们不会重叠。

是否可以删除一些 xlabels,或者我是否需要更改输入数据以使一些为空白?

额外的问题:为什么输出包含第二个情节线作为文本,以及遵守它的指示?

【问题讨论】:

    标签: gnuplot axis-labels


    【解决方案1】:

    正如@Tom Solid 已经指出的那样,最简单的可能就是旋转 xtic 标签。 您的“额外问题”也可以通过插入一行来回答:unset key

    顺便说一句,你代码中的set xdata timeset timefmt "%d %b %Y"等都没有效果。列标题将仅用作 xtic 标签的文本。

    另一种(更复杂一点)的建议是将日期转换为日历周。这将节省空间。但请记住,一周的开始时间(周日还是周一?)以及日历的第 1 周有不同的定义。

    代码:

    ### schedule with calendar weeks
    reset session
    
    $Data <<EOD
    Week commencing,29 Jun 2020,06 Jul 2020,13 Jul 2020,20 Jul 2020,27 Jul 2020,03 Aug 2020,10 Aug 2020,17 Aug 2020,24 Aug 2020,31 Aug 2020,07 Sep 2020,14 Sep 2020,21 Sep 2020,28 Sep 2020,05 Oct 2020,12 Oct 2020,19 Oct 2020,26 Oct 2020,02 Nov 2020,09 Nov 2020
    Mon,11,6,0,4,4,9,10,7,5,0,22,10,9,8,9,2,4,11,11,7
    Tue,3,5,0,6,3,4,11,3,6,12,6,3,4,4,9,12,2,1,8,2
    Wed,10,1,0,9,4,1,6,5,6,3,2,5,1,5,7,5,8,10,2,12
    Thu,6,3,0,8,3,2,7,14,10,12,14,8,1,3,19,11,8,16,3,7
    Fri,16,1,2,5,10,3,0,1,10,1,13,10,0,10,6,10,7,4,9,5
    Sat,6,6,8,21,2,7,0,11,0,7,2,23,2,8,11,11,5,3,12,0
    Sun,8,7,3,1,8,2,8,2,2,2,6,6,3,3,2,2,4,5,8,0
    EOD
    
    set datafile separator comma
    unset key
    
    set palette rgbformula -9,2,-9
    set cbrange [0:*]
    set cblabel "Completed tasks (Goals + Projects + Other)"
    unset cbtics
    set style fill solid 1.0
    
    set locale "English_US"    # if not already set, to correctly interpret the month abbreviations
    set xlabel "Calendar week"
    
    myCW(col) = sprintf("%s",strftime("%W",strptime("%d %b %Y",strcol(col))))  # date --> calendar week
    stats [*:*][*:*] $Data u 2 skip 1 nooutput  # get the number of columns
    MaxCol = STATS_columns
    set xrange [-0.5:MaxCol-1.5] 
    set yrange [6.5:-0.5]
    
    plot $Data matrix rowheaders using 1:2:3 skip 1 with image, \
         $Data matrix rowheaders using 1:2:($3==0 ? "" : sprintf("%g",$3) ) skip 1 with labels font ",8" tc rgb "#22BB22", \
         for [i=2:MaxCol] $Data u (i-2):(NaN):xtic(myCW(i)) every ::0::0 
    ### end of code
    

    结果:

    加法:

    @JGC,这就是 gnuplot 的优势,不知何故会有解决方案,有时有点麻烦,但大多数情况下存在一些解决方法。

    通常,我认为数据是给定的和固定的。在某些情况下,您可能在创建数据格式时就已经更改了数据格式,并使其适应 gnuplot 的“特殊需求”以实现您的特殊愿望。

    正如我所提到的,您的标签太长了。 plot ... matrix columnheaders 只会将它们全部用作文本标签。我不知道你可以直接跳过一些。但这是 gnuplot,......所以,有一个解决方法。

    1. 您需要知道您有多少列。这一点,您可以使用stats 查找。但是,如果第一行是标题或字符串,gnuplot 不会识别列,这就是为什么您必须跳过第一行,即skip 1。虽然有语法 plot for [i=2:*] u 1:(column(i)) ... 应该循环所有列,但我体验到这可能导致 gnuplot 挂起或崩溃(我还没有发现这是为什么以及如何定期重现它)。

    2. 使用以下构造,您可以选择要显示多少个 xtic 标签:for [i=2+Noffset:MaxCol:Nxtic] $Data u (i-2):(NaN):xtic(strcol(i)) every ::0::0。这里:每个Nxtic=4 标签的偏移量为Noffset=1。此外,我认为让一些 xtic 标记可见很重要,特别是如果您的 xtic 标签相当长。否则你不会知道日期实际属于哪一列。

    代码:

    ### schedule from matrix with every nth label only
    reset session
    
    $Data <<EOD
    Week commencing,29 Jun 2020,06 Jul 2020,13 Jul 2020,20 Jul 2020,27 Jul 2020,03 Aug 2020,10 Aug 2020,17 Aug 2020,24 Aug 2020,31 Aug 2020,07 Sep 2020,14 Sep 2020,21 Sep 2020,28 Sep 2020,05 Oct 2020,12 Oct 2020,19 Oct 2020,26 Oct 2020,02 Nov 2020,09 Nov 2020
    Mon,11,6,0,4,4,9,10,7,5,0,22,10,9,8,9,2,4,11,11,7
    Tue,3,5,0,6,3,4,11,3,6,12,6,3,4,4,9,12,2,1,8,2
    Wed,10,1,0,9,4,1,6,5,6,3,2,5,1,5,7,5,8,10,2,12
    Thu,6,3,0,8,3,2,7,14,10,12,14,8,1,3,19,11,8,16,3,7
    Fri,16,1,2,5,10,3,0,1,10,1,13,10,0,10,6,10,7,4,9,5
    Sat,6,6,8,21,2,7,0,11,0,7,2,23,2,8,11,11,5,3,12,0
    Sun,8,7,3,1,8,2,8,2,2,2,6,6,3,3,2,2,4,5,8,0
    EOD
    
    set datafile separator comma
    unset key
    set palette rgbformula -9,2,-9
    set cbrange [0:*]
    set cblabel "Completed tasks (Goals + Projects + Other)"
    unset cbtics
    set style fill solid 1.0
    stats [*:*][*:*] $Data u 2 skip 1 nooutput    # get the number of columns
    MaxCol = STATS_columns
    Nxtic = 4
    Noffset = 1
    set xtics out
    set yrange [6.5:-0.5]
    
    plot $Data matrix rowheaders using 1:2:3 skip 1 with image, \
         $Data matrix rowheaders using 1:2:($3==0 ? "" : sprintf("%g",$3) ) skip 1 with labels font ",8" tc rgb "#22BB22", \
         for [i=2+Noffset:MaxCol:Nxtic] $Data u (i-2):(NaN):xtic(i) every ::0::0
    ### end of code
    

    结果:

    【讨论】:

    • 感谢@theozh 的建议。碰巧我不想使用日历周,因为它们不会像几个月那样触发关联。如果有足够的数据,它们也会相互碰撞。这就是我追求自动适应解决方案的原因。
    • 也感谢 @tehozh 为我澄清 xdata 与列标题的关系。
    • @JGC,查看添加的灵活性,仅显示每 N 个标签。
    • 优秀的@theozh——这就是我所追求的。
    【解决方案2】:

    主要问题

    我找不到使用某些选项“删除某些 xlabels”的简单方法。如您所说,如果您可以像下面这样轻松地“更改输入数据,使某些数据为空白”,那么这是获得所需输出的捷径。

    # Week commencing,29 Jun 2020,06 Jul 2020,13 Jul 2020,20 Jul 2020,27 Jul 2020,03 Aug 2020,10 Aug 2020,17 Aug 2020,24 Aug 2020,31 Aug 2020,07 Sep 2020,14 Sep 2020,21 Sep 2020,28 Sep 2020,05 Oct 2020,12 Oct 2020,19 Oct 2020,26 Oct 2020,02 Nov 2020,09 Nov 2020
    Week commencing,29 Jun,,,20 Jul,,,10 Aug,,,31 Aug,,,21 Sep,,,12 Oct,,,02 Nov,
    Mon,11,6,0,4,4,9,10,7,5,0,22,10,9,8,9,2,4,11,11,7
    Tues,3,5,0,6,3,4,11,3,6,12,6,3,4,4,9,12,2,1,8,2
    Weds,10,1,0,9,4,1,6,5,6,3,2,5,1,5,7,5,8,10,2,12
    Thurs,6,3,0,8,3,2,7,14,10,12,14,8,1,3,19,11,8,16,3,7
    Fri,16,1,2,5,10,3,0,1,10,1,13,10,0,10,6,10,7,4,9,5
    Sat,6,6,8,21,2,7,0,11,0,7,2,23,2,8,11,11,5,3,12,0
    Sun,8,7,3,1,8,2,8,2,2,2,6,6,3,3,2,2,4,5,8,0
    

    第一行是原始行之外的注释。第二行 插入以存储要在 xtics 处显示的标签。如果你有这样的输入文件,你可以简单地运行你的脚本并得到这样的图像。

    奖金(?)问题

    您还可以通过执行以下操作删除图例中的长字符串,

    set key noautotitle
    

    “设置键自动标题”是默认设置。并且 plot 命令中没有明确给出标题字符串(包括关键字“notitle”),plot 命令本身的字符串将显示在图例中,如您所见。上面的命令禁用了这个默认设置。

    【讨论】:

      【解决方案3】:

      或者,您可以旋转xtics

       set xtics rotate by -90
      

      奖励:在你的第二个情节之后输入notitle

      plot DATAFILE matrix rowheaders columnheaders using 1:2:3 with image, \
           DATAFILE matrix rowheaders columnheaders using 1:2:($3 == 0 ? "" : sprintf("%g",$3) ) with labels font ",8" tc rgb "#22BB22" notitle
      

      【讨论】:

      • 感谢@Tom Solid,已修复不需要的文本。知道为什么将其视为标题吗?还是这是一个错误?
      • 我还在寻找主要问题的答案;旋转标签是可能的,但没有我想象的那么优雅。
      • @JGC:不,这不是错误。对于每一个绘制的数据集和曲线,都会有一个键;默认是绘图命令本身。您可以通过ttitle 设置曲线/数据集的键,也可以使用notitle 取消设置它们。或者,正如@theozh 所提到的,您可以通过unset key 取消设置所有键。顺便说一句,您的第一个情节也有一个不需要的键,但它只是被第二个情节覆盖。
      • 感谢您解释默认键/标题 @Tom Solid 的情况。我现在明白了!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 2017-04-28
      • 2011-04-23
      • 2012-03-04
      • 2014-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多