使用 awk 计算汇率/“导数”

使用 awk 计算汇率/“导数”

awk这里是新手。

假设我有两列数据,并且我想计算增长率,由 delta(y)/delta(x) 给出。我将如何在awk脚本中执行此操作?到目前为止我所学到的仅涉及逐行操作,并且我不确定如何处理多行。

注意:假设我有 N 个数据点,我将获得 N-1 个斜率/速率值。

例子:

  • 输入

    x y 
    2 4 
    3 5 
    4 7
    
  • 输出

    Slope
    -
    1
    2
    

这里是awk最好的选择吗?或者其他工具更好吗?

答案1

使用变量来存储需要从一行到下一行记住的数据。

输出中的第 N+1 行是根据输入中的第 N 行和第 N+1 行计算得出的,因此您需要变量来存储前一行的内容。每行有两个字段,因此每个字段使用一个变量。

第 1 行和第 2 行得到特殊处理(标题行,数据不足)。您可以通过测试特殊变量来匹配特定的行号NR。该指令next导致当前行的其余处理被跳过。

由于这个处理相当简单,因此使用变量来表示上一行的内容就足够了。处理完当前行后,使用处理上一行时设置的变量,将当前行的内容存储到变量中。

NR == 1 { print "Slope"; next; }
NR == 2 { print "-"; }
NR >= 3 { print ($2 - y) / ($1 - x) }
NR >= 2 { x = $1; y = $2; }

回想一下,awk 依次运行每个输入行的代码,每个花括号组之前的表达式是运行该组的条件,因此这相当于以下伪代码:

for each line {
    NR = current line number;
    $1 = first field; $2 = second field;
    if (NR == 1) { print "Slope"; next; }
}

或者,如果为前一行的数据和当前行的数据都指定名称,您可能会发现代码更具可读性。在当前行处理结束时,将数据从“当前”变量传输到“上一个”变量。

NR == 1 { print "Slope"; next; }
NR == 2 { print "-"; }
NR >= 2 { current_x = $1; current_y = $2; }
NR >= 3 { print (current_y - previous_y) / (current_x - previous_x) }
NR >= 2 { previous_x = current_x; previous_y = current_y; }

答案2

$ awk 'NR==1 { print; next; }; '\
'      NR==2 { former_x=$1; former_y=$2; $3="-"; print; next; };'\
' { $3=($2-former_y)/($1-former_x); print; former_x=$1; former_y=$2; }' input

x y Slope
2 4 -
3 5 1
4 7 2

第一行只是按原样打印。

在以下所有行中,您必须存储列中的值xy以便它们可用于以下行中的计算。第 2 行经过特殊处理,因为还没有什么可计算的。

在以下所有行中,计算比率,将其作为新字段添加到该行,打印该行,并存储该行的值。

答案3

假设你的输入是

x y
2 4
3 5
4 7
4 8

然后

awk 'NR==1{print $0" Slope"; getline}
  {dx=($1-xold); dy=($2-yold);$3=(xold&&dx!=0)?dy/dx:"-"; xold=$1; yold=$2; print}' file

给你

x y Slope
2 4 -
3 5 1
4 7 2
4 8 -

解释-o

awk 'NR==1{print $0" Slope"; getline}

如果它是第一条记录/行NR==1,则将其与附加标题一起打印并跳转到下一行getline

  {dx=($1-xold); dy=($2-yold);

计算dxdy

  $3=(xold&&dx!=0)?dy/dx:"-"; 

如果xold已初始化(仅在该测试后发生在第 2 行,因此仅在第 2 行失败)并且dx!=0(没有 div 0 错误)则$3=dy/dx否则$3="-"

     xold=$1; yold=$2; 

然后更新xoldyold值到该记录/行上的当前 x 和 y

      print}' file

然后打印整个记录/行(包括新的$3

相关内容