다른 열의 가장 빠른 날짜를 기준으로 ID당 하나의 레코드만 선택하려면 어떻게 해야 합니까?

다른 열의 가장 빠른 날짜를 기준으로 ID당 하나의 레코드만 선택하려면 어떻게 해야 합니까?

다음과 같은 필드로 구성된 여러 줄이 포함된 파일이 있습니다.상표:

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보다 큰 파일당 라인 카운터(헤더 라인을 건너뛰기 위해),그리고
  • 배열에는 첫 번째 열( )의 현재 값에 대한 항목이 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

관련 정보