別の列の最も早い日付に基づいてIDごとに1つのレコードのみを選択するにはどうすればよいですか?

別の列の最も早い日付に基づいてIDごとに1つのレコードのみを選択するにはどうすればよいですか?

次のフィールドで構成される複数行を含むファイルがあります。商標:

ID Code Date
1  XX   23/1/2018
1  XX   11/3/2021
2  XX   14/5/2011
2  XX   20/9/2013
3  XX   08/7/2014
3  XX   11/9/2016
3  XX   27/10/2018

ID列の日付が最も早い項目に基づいて各参加者の項目を維持したいと思いますDate。各参加者の日付は、早いものから遅いものの順にソートされます。

私が望む出力は次のとおりです。

1  XX   23/1/2018
2  XX   14/5/2011
3  XX   08/7/2014

答え1

各参加者の記録は、最も古いものから最新の順に並べられており、各参加者に対して最も早い日付の記録のみを印刷したいので、IDこれはそれぞれの新しい出会いの最初の記録を印刷するのと同じですID。これは以下を使用して簡単に達成できますawk

awk -F'\t' 'FNR>1 && !seen[$1]++' input.txt

これにより、まずフィールド区切り記号がに設定されます\t。次に、間の条件を評価して、' ... '現在の行を印刷するかどうかを決定します。次の場合、1行が印刷されます。

  • 1より大きいファイルあたりのラインカウンタ(ヘッダラインをスキップするため)、そして
  • 配列には、最初の列()の現在の値のエントリはseenまだ含まれていません。$1まだ割り当てられていない配列の値を逆参照すると評価されますfalse。また、後続演算子は++その評価後にのみ適用されるため、特定の最初の発生に対しては true を返しますが、0 より大きいID後続の発生については返し、行印刷を抑制します。seen[$1]false

ヘッダー行を維持するには、FNR>1条件を削除するだけです。

awk -F'\t' '!seen[$1]++' input.txt

ID(この行のために印刷されます。文字通り IDもちろん、その特定の値が最初に表示される場合です。 )

答え2

次の用途ミラーmlr、構造化データを処理するためのツール)を使用してTSVファイルのレコードを解析します。ID値と出力によってレコードをグループ化します。最初各グループで価値を見つけてください。

$ mlr --tsv head -g ID -n 1 file
ID      Code    Date
1       XX      23/1/2018
2       XX      14/5/2011
3       XX      08/7/2014

日付が次の場合いいえそれぞれを並べ替えるには、ID各日付文字列をUnixタイムスタンプに変換し、この新しいフィールドを数値順に並べ替えることで、各項目を並べ替えることができます。並べ替え後は、上記と同じ操作を実行し、タイムスタンプフィールドを切り取り(削除)して値を並べhead替えます。ID

mlr --tsv \
    put '$ts = strptime($Date, "%d/%m/%Y")' then \
    sort -n ts then \
    head -g ID -n 1 then \
    cut -x -f ts then \
    sort -n ID file

出力は質問に示された例と同じです。

答え3

次のコードを使用して目的の出力を取得できます。

sed 1d file_of_data | sort -k1,2n -u

これがすることは、

  1. sedヘッダーを含む最初の行を削除(削除)するために使用されます。
  2. sort結果ファイルは最初の列で数値順にソートされ、そのソートフィールドの重複エントリは削除されます。

出力

1  XX   23/1/2018
2  XX   14/5/2011
3  XX   08/7/2014

関連情報