gnuplot:绘制数据并使用重复x值的最大值

gnuplot:绘制数据并使用重复x值的最大值,plot,gnuplot,Plot,Gnuplot,我想用两列绘制一个巨大数据文件的曲线: 数据文件(示例): 如果我使用“plot'data.txt'using 0:1 with lines”并正确设置日期格式等,我将得到一个几乎正确的绘图,但不幸的是,如果每个日期有多行,它将使用“lower/upper”值。我想在绘图中绘制每天总和列的最大值。我想使用每天最后/最高的给定值。这有点棘手。我对的回答显示了如何对数字x轴执行此操作。如果您有时间数据,则必须使用timecolumn(1)而不是$1,仅此而已: reset xval = -1e10

我想用两列绘制一个巨大数据文件的曲线:

数据文件(示例):


如果我使用“plot'data.txt'using 0:1 with lines”并正确设置日期格式等,我将得到一个几乎正确的绘图,但不幸的是,如果每个日期有多行,它将使用“lower/upper”值。我想在绘图中绘制每天总和列的最大值。我想使用每天最后/最高的给定值。

这有点棘手。我对的回答显示了如何对数字x轴执行此操作。如果您有时间数据,则必须使用
timecolumn(1)
而不是
$1
,仅此而已:

reset
xval = -1e10
max(x, y) = (x > y ? x : y)
maxval = 0

set timefmt '%Y-%m-%d'
set xdata time

plot 'data.txt' using (val = $2, timecolumn(1)):\
     (maxval_prev = (xval == timecolumn(1) ? maxval : 0), \
      maxval = (xval == timecolumn(1) ? max(maxval, val) : val),\
      xval = timecolumn(1), \
      (maxval > maxval_prev ? maxval-maxval_prev : 0)\
     ) \
     smooth frequency lw 3 with linespoints t 'maximum values'
结果如下(见4.6.3):


有关更详细的解释,请参见上面的链接答案。

另一个解决方案可能是下面的代码。我们假设日期是严格的升序或降序,但不是随机的。 公认的解决方案当然是更有效的解决方案,但并不容易遵循。 基本思想是将最后一个日期(几个相同的日期)及其值写入一个新的数据块,并简单地绘制这个新数据集

### start code
reset session

$Data <<EOD
#dateYMD sum
2014-02-01 70
2014-02-01 85
2014-02-01 95
2014-02-02 116
2014-02-02 123
2014-02-09 130
2014-02-09 134
2014-02-11 145
EOD

stats $Data nooutput
set table $Dummy
set print $Data2
tmp = ""
do for [i=STATS_records-1:0:-1] {
   plot $Data u (a=stringcolumn(1),b=stringcolumn(2),$2) every ::i::i with table
   if (tmp ne a) { print sprintf("%s\t%s",a,b); tmp = a}
}
set print
unset table

set xdata time
set timefmt "%Y-%m-%d"
set yrange[0:160]
plot $Data2 u (timecolumn(1)):2 w lp lw 2 pt 7 t "maximum values"
### end code
###开始代码
重置会话

$Data好的,我想这里有一个解决方案

  • 处理未排序的日期
  • 返回最大值和最小值
  • 仅为gnuplot(无外部工具)
  • 一个小缺点:我不知道如何防止来自“stats”的警告

    ### start code
    reset session
    
    # unsorted dates and values
    $Data <<EOD
    #dateYMD sum
    2014-02-01 85
    2014-02-09 134
    2014-02-01 95
    2014-02-02 116
    2014-02-01 70
    2014-02-02 123
    2014-02-09 130
    2014-02-11 145
    EOD
    
    # get unique dates in seconds
    set xdata time
    set format x "%s"
    set table $DataInSeconds
        plot $Data u (timecolumn(1,"%Y-%m-%d")):2  smooth freq
    unset table
    set xdata  # stats will not work with 'xdata time'
    stats $DataInSeconds nooutput
    UniqueDates = STATS_records
    
    # get the maximum and minimum value per date
    set print $MinMaxData
    set table $Dummy
    do for [i=0:UniqueDates-1] {
        plot $DataInSeconds u (a=$1,$1):2 every ::i::i with table
        stats [a:a] $Data u (timecolumn(1,"%Y-%m-%d")):2 nooutput
        print sprintf("%s\t%g\t%g", strftime("%Y-%m-%d",a), STATS_min_y, STATS_max_y)
    }
    unset table
    set print
    print $MinMaxData
    
    # plot the results
    set key top left
    set yrange[0:160]
    set xdata time
    set format x "%m/%d"
    plot $MinMaxData u (timecolumn(1,"%Y-%m-%d")):3 \
            w lp lw 2 pt 7 ps 2 lc rgb "red" t "maximum values",\
         '' u (timecolumn(1,"%Y-%m-%d")):2 \
            w lp lw 2 pt 6 ps 2 lc rgb "web-green" t "minimum values",\
         $Data u (timecolumn(1,"%Y-%m-%d")):2 \
            w p lw 2 pt 2 ps 1 lc rgb "blue" t "all values"
    ### end code
    
    ###开始代码
    重置会话
    #未排序的日期和值
    
    $Data您可以使用
    awk'{if(date&&date!=$1){print date,val};date=$1;val=$2}'
    筛选数据。这将只为每个日期保留最后一个值。@max taldykin此awk脚本将忽略最后一个日期。@hfs,您是对的。我不知道如何在不生成两倍长的代码的情况下解决这个问题。哇,这为我今天节省了很多时间
    平滑频率
    对数据进行排序,所以这是一个假设,它总是有效的,不需要反复迭代所有行。我同意,使用
    每个
    进行循环可能不是很有效。是的,
    smooth frequency
    在“平滑”之后对数据进行排序。如果使用不严格按升序排列的日期测试脚本,将无法获得所需的结果。尽管如此,同一特定日期的值可能是随机的。因此,至少您必须假设日期严格按升序排列,或者首先必须使用外部工具对日期进行排序。
    ### start code
    reset session
    
    # unsorted dates and values
    $Data <<EOD
    #dateYMD sum
    2014-02-01 85
    2014-02-09 134
    2014-02-01 95
    2014-02-02 116
    2014-02-01 70
    2014-02-02 123
    2014-02-09 130
    2014-02-11 145
    EOD
    
    # get unique dates in seconds
    set xdata time
    set format x "%s"
    set table $DataInSeconds
        plot $Data u (timecolumn(1,"%Y-%m-%d")):2  smooth freq
    unset table
    set xdata  # stats will not work with 'xdata time'
    stats $DataInSeconds nooutput
    UniqueDates = STATS_records
    
    # get the maximum and minimum value per date
    set print $MinMaxData
    set table $Dummy
    do for [i=0:UniqueDates-1] {
        plot $DataInSeconds u (a=$1,$1):2 every ::i::i with table
        stats [a:a] $Data u (timecolumn(1,"%Y-%m-%d")):2 nooutput
        print sprintf("%s\t%g\t%g", strftime("%Y-%m-%d",a), STATS_min_y, STATS_max_y)
    }
    unset table
    set print
    print $MinMaxData
    
    # plot the results
    set key top left
    set yrange[0:160]
    set xdata time
    set format x "%m/%d"
    plot $MinMaxData u (timecolumn(1,"%Y-%m-%d")):3 \
            w lp lw 2 pt 7 ps 2 lc rgb "red" t "maximum values",\
         '' u (timecolumn(1,"%Y-%m-%d")):2 \
            w lp lw 2 pt 6 ps 2 lc rgb "web-green" t "minimum values",\
         $Data u (timecolumn(1,"%Y-%m-%d")):2 \
            w p lw 2 pt 2 ps 1 lc rgb "blue" t "all values"
    ### end code