고유한 값을 계산하고 결과 값을 새 열로 추가합니다.

고유한 값을 계산하고 결과 값을 새 열로 추가합니다.

대용량 csv 파일이 있고 간단한 순위를 작성하고 싶습니다.

$ cat file.csv
2022-12-01     RED     1     
2022-12-01     RED     1     
2022-12-01     RED     2     
2022-12-01     RED     2     
2022-12-01     RED     2     
2022-12-01     YELLOW     1     
2022-12-01     YELLOW     1     
2022-12-01     YELLOW     2     
2022-12-01     YELLOW     2     
2022-12-01     YELLOW     2     
$ sort file.csv | uniq -c | sort -nr > file_sort.csv
$ cat file_sort.csv 
3 2022-12-01     RED     2     
3 2022-12-01     YELLOW     2     
2 2022-12-01     RED     1     
2 2022-12-01     YELLOW     1     

결과를 새 열로 추가하고 싶지만 다음과 같이 기존 $1에 추가하고 싶습니다.

$ cut -f1 file_sort.csv
3 2022-12-01
3 2022-12-01
2 2022-12-01
2 2022-12-01

uniq 행의 값을 새 열로 저장하는 방법이 있나요? 이와 같이:

$ cut -f1 file_sort.csv
3
3
2
2

답변1

당신이 원하는 것은 첫 번째 필드에서 마지막 필드로 숫자를 이동하는 것뿐입니다. 이를 지정하지 않았지만 cut표시된 명령을 사용하면 파일이 탭으로 구분되어 있음을 의미합니다. 그렇다면 uniq -c출력이 공백(표시하지 않음)으로 줄을 채우고 발생 후에 탭을 추가하지 않는다는 점을 고려하면 다음과 같이 간단하게 작업을 수행할 수 있습니다.

$ sort file.csv | uniq -c | sort -nr | perl -pe 's/^\s+(\d+) (.*)/$2\t$1/' 
2022-12-01  YELLOW  2   3
2022-12-01  RED 2   3
2022-12-01  YELLOW  1   2
2022-12-01  RED 1   2

또는 다음 sed을 지원합니다 -E.

$ sort file.csv | uniq -c | sort -nr | sed -E 's/^ *([0-9]*) (.*)/\2\t\1/' 
2022-12-01  YELLOW  2   3
2022-12-01  RED 2   3
2022-12-01  YELLOW  1   2
2022-12-01  RED 1   2

그리고 어떤 sed에서도:

$ sort file.csv | uniq -c | sort -nr | sed 's/^ *\([0-9]*\) \(.*\)/\2\t\1/' 
2022-12-01  YELLOW  2   3
2022-12-01  RED 2   3
2022-12-01  YELLOW  1   2
2022-12-01  RED 1   2

또는 개수를 계산하고 awk원하는 위치에 필드를 추가한 후 네 번째 필드를 기준으로 정렬할 수 있습니다.

$ awk -F'\t' -v OFS='\t' '{ cnt[$0]++ } 
                          END{
                            for(line in cnt){
                              print line,cnt[line]
                            }
                          }' file.csv | sort -nrk4,4 
2022-12-01  YELLOW  2   3
2022-12-01  RED 2   3
2022-12-01  YELLOW  1   2
2022-12-01  RED 1   2

답변2

사용행복하다(이전 Perl_6)

당신이 원하는 것은 Bag요소입니다. 이 경우 요소는 다음과 같습니다 lines:

~$ raku -e '.say for lines.Bag;'  file

입력 예(탭으로 구분):

2022-12-01     RED     1     
2022-12-01     RED     1     
2022-12-01     RED     2     
2022-12-01     RED     2     
2022-12-01     RED     2     
2022-12-01     YELLOW     1     
2022-12-01     YELLOW     1     
2022-12-01     YELLOW     2     
2022-12-01     YELLOW     2     
2022-12-01     YELLOW     2 

예제 출력:

2022-12-01    RED    2        3
2022-12-01    RED    1        2
2022-12-01    YELLOW    2        3
2022-12-01    YELLOW    1        2

참고: 여기서 실제 문제는 후행 공백일 수 있습니다. trim-trailing각 줄의 오른쪽 끝에 공백을 제거하는 호출을 추가할 수 있습니다 .

~$ raku -e '.put for lines.map(*.trim-trailing).Bag;' 

#OR

~$ raku -e '.put for lines>>.trim-trailing.Bag;'  

https://docs.raku.org/type/Bag
https://raku.org

답변3

count-distinctMiller( ) 하위 명령을 사용하여 mlr입력이 탭으로 구분되고 열 머리글이 없다고 가정하고 처음 세 필드에 고유 값이 있는 레코드 수를 계산합니다.

$ mlr --tsv -N count-distinct -f 1,2,3 file
2022-12-01      RED     1       2
2022-12-01      RED     2       3
2022-12-01      YELLOW  1       2
2022-12-01      YELLOW  2       3

개수는 필드 목록 끝에 새 필드로 추가됩니다. 입력을 정렬할 필요가 없습니다.

개수를 첫 번째 필드로 사용하려면 reorder하위 명령을 사용하십시오. 제목이 출력에 표시되지 않더라도 작업 count으로 생성된 명명된 필드를 참조 할 수 있습니다.count-distinct

$ mlr --tsv -N count-distinct -f 1,2,3 then reorder -f count file
2       2022-12-01      RED     1
3       2022-12-01      RED     2
2       2022-12-01      YELLOW  1
3       2022-12-01      YELLOW  2

답변4

awk 명령의 연관 배열 아이디어를 사용하면 고유한 행 수를 쉽게 계산할 수 있습니다.

$ awk  '{a[$0]++} END {for (i in a) print a[i]"--->",i}' infile

2---> 2022-12-01     YELLOW     2     
3---> 2022-12-01     RED     2     
2---> 2022-12-01     YELLOW     1     
1---> 2022-12-01     YELLOW     2
2---> 2022-12-01     RED     1

관련 정보