インデックスが数値ではなくawkを使用して古いインデックスから減算する

インデックスが数値ではなくawkを使用して古いインデックスから減算する

前の値から値を減算したいのですが、条件を満たす必要があります。

文書:

2022-02-01 01:00:00|abc|2001|5
2022-02-01 01:00:00|abc|2002|10
2022-02-01 01:01:00|abc|2001|6
2022-02-01 01:01:00|abc|2002|11
2022-02-01 01:02:00|abc|2001|10
2022-02-01 01:02:00|abc|2002|11
2022-02-01 01:02:00|abc|2003|2

希望の出力:

2022-02-01 01:00:00|abc|2001|5
2022-02-01 01:00:00|abc|2002|10
2022-02-01 01:01:00|abc|2001|1
2022-02-01 01:01:00|abc|2002|1
2022-02-01 01:02:00|abc|2001|4
2022-02-01 01:02:00|abc|2002|0
2022-02-01 01:02:00|abc|2003|2

私はawkを試しましたが、値を減算するために古いインデックスにアクセスすることはできません。

awk -F"|" 'BEGIN{OFS="|"}{a[$1,$2,$3]=$4}END{for (i in a) print i, a[i]-a[i-1] }' file

答え1

あなたがしたいことは次のようになります:

awk -v FS="|" -v OFS="|" '{ a=$4;if($3 in dict)$4-=dict[$3]; dict[$3]=a}1' file

私はassociative arraysキーとして持っている年を保存するためにawkを使用しています;その値は最後の列になります。たとえば、配列は次のようになります。

dict[2001] = "4th column"
dict[2002] = "4th column"
dict[2003] = "4th column"
....

したがって、dict キー/値は次のようになります。

dict[2001] = "5"
dict[2002] = "10"
dict[2001] = "6"
dict[2002] = "11"
dict[2001] = "10"
dict[2002] = "11"
dict[2003] = "2" # this never changes because you have only one 2003 as year.

したがって、awkコードを使用すると、現在の主要年から4番目の列に保存されている最後の値を引くa=$4;if($3 in dict)$4-=dict[$3]; dict[$3]=aことができます。dict3ドルは年ですそして$ 4はインデックス/値です。


あなたの意見で述べたように、keys連想配列はabc|year。その場合は、以下を使用する必要があります。

awk -F'|' -v OFS='|' '{a=$4; if(($2,$3) in dict)$4-=dict[$2,$3]; dict[$2,$3]=a }1' file

答え2

使用miller:

mlr --nidx --fs '|' put '$delta = is_present(@last[$3]) ? $4 - @last[$3]  : $4; @last[$3] = $4; unset $4' file

このコマンドでは、4番目のフィールドが@last3番目のフィールドのインデックスに格納されます。それが真であることis_presentを確認してから@last[$3](つまり、現在のレコードの3番目のフィールドにインデックス変数がある)、2つの値の違いを印刷します。それ以外の場合は、4番目のフィールドを印刷します。

最後の4番目のフィールドは設定されていません。

最初の値が必要ない場合は、次の値を使用できます。

 mlr --nidx --fs '|' step -g 3 -a delta -f 4 file

関連情報