从一列中查找最小值和最大值及其对应的另一列值

从一列中查找最小值和最大值及其对应的另一列值

这是我的示例文本文件

[s]            [K]        
1              900
2              100 
3              200
8              1000
1              80
55             12
6              90000
5              1

我需要在第 2 列中找到最大值,并在第 1 列中找到相应的值,然后从第 1 列的所有元素中减去该值。

我想要的输出是这样的

[s]            [K]        
-5              900
-4              100 
-3              200
2              1000
-5              80
49             12
0              90000
-1              1

这是我的片段

awk 'function abs(x) {return x<0?-x:x}
FNR==1  { $1=$1; print; next }
{if(max<$2){max=$2;line=$1}}{print $1-line "\t"$2}' test.txt

不知何故,这没有给我正确的结果。我也希望第 2 列中的最小值具有相同的值。

答案1

您必须对数据进行两次遍历,首先找到最小值和最大值,然后进行计算:

awk 'BEGIN { OFS = "\t" }
     FNR == NR { if (FNR > 1 && (min == "" || $2 < min)) { min = $2; minval = $1 }
                 if (FNR > 1 && (max == "" || $2 > max)) { max = $2; maxval = $1 }
                 next }
     FNR == 1 { print "[s (-max)]", "[s (-min)]", "[K]"; next }
              { print $1 - maxval, $1 - minval, $2 }' file file

对于给定的数据,这将产生

[s (-max)]      [s (-min)]      [K]
-5      -4      900
-4      -3      100
-3      -2      200
2       3       1000
-5      -4      80
49      50      12
0       1       90000
-1      0       1

awk代码有四个块,我们将输入文件传递给它两次。第一个块 ( BEGIN) 只是将输出字段分隔符设置为制表符。

第二个块 ( FNR == NR) 将在第一次遍历文件期间对每一行执行,并跟踪第二列 (maxmin) 中的最大值和最小值以及第一列 (maxvalminval) 中的相应值,并根据需要更新它们。在此块的末尾,next用于跳过当前输入的脚本的其余部分。

NR是当前记录的总体序号(“行号”),而FNR是当前文件的相同编号。 将与仅第一次传递输入文件时NR相同。FNR

FNR == 1当刚刚从第二遍文件中读取第一行时,将执行第三个块 ( )。它只是打印出一个标题。我们将计算第一列的值减去minval和 的值,因此我们添加一个新的列标题。maxval

最后一个块是无条件的,将在第二次遍历文件时执行第二行,并执行数据的实际计算和输出。

您可以通过将输出传递给以下方式获得稍微漂亮的输出column -s $'\t' -t

[s (-max)]  [s (-min)]  [K]
-5          -4          900
-4          -3          100
-3          -2          200
2           3           1000
-5          -4          80
49          50          12
0           1           90000
-1          0           1

答案2

$ cat tst.awk
BEGIN { OFS="\t" }
NR==1 { next }
NR==2 { maxVal = $2 }
NR==FNR {
    if ($2 >= maxVal) {
        maxSth = $1
        maxVal = $2
    }
    next
}
{ print (FNR>1 ? ($1 - maxSth) : $1) , $2 }

$ awk -f tst.awk file file
[s]     [K]
-5      900
-4      100
-3      200
2       1000
-5      80
49      12
0       90000
-1      1

答案3

也许是这样的?记录处理文件两次。

awk 'NR==FNR && NR>1 { max_col2=( max_col2>$2?max_col2:$2 ); max[$2]=$1;  
                       min_col1=( min_col1>$1?min_col1:$1 ); min[$1]=$2; }
     NR!=FNR && FNR>1{ print $1-max[max_col2], $2-min[min_col1]; }' OFS='\t' infile infile
-5      888
-4      88
-3      188
2       988
-5      68
49      0
0       89988
-1      -11

相关内容