a.csv와 b.csv라는 두 개의 csv 파일이 있습니다. 두 파일 모두 동일한 행 세트를 포함합니다. 예를 들어:
a.csv:
Yield
5.68
1.34
1.47
9.01
7.59
b.csv:
Yield
5.68
2.01
0.78
7.98
8.17
이 두 파일을 비교하고(파일의 순서는 항상 동일합니다. 즉, a.csv의 i행은 항상 b.csv의 i행과 일치함) 다음 통계를 인쇄해야 합니다.
a.csv is greater than b.csv in 2/5 cases.
a.csv is smaller than b.csv in 2/5 cases.
a.csv is equal to b.csv in 1/5 cases.
참조: 이 작업을 수행하기 위해 R 코드를 작성했지만 Unix 자체에서 수행하고 싶습니다. 어쩌면 awk를 사용할까요?
a <- read.csv('path/a.csv')
b <- read.csv('path/b.csv')
sum(a > b)
sum(a < b)
sum(a == b)
답변1
$ paste a.csv b.csv | awk -F '\t' 'NR > 1 { ++cmp[$1>$2 ? 1 : $1==$2 ? 0 : -1] } END { printf "greater\t= %d\nsmaller\t= %d\nequal\t= %d\n", cmp[1],cmp[-1],cmp[0] }'
greater = 2
smaller = 2
equal = 1
awk
그러면 쇼트 프로그램에 대한 두 개의 열 입력이 생성됩니다 paste
. 의 내용은 a.csv
첫 번째 필드에 있고 의 내용은 b.csv
두 번째 필드에 있으며 그 사이에 탭 문자가 있습니다.
헤더 행은 삭제되고 첫 번째 코드 블록은 배열의 세 카운터 중 하나를 증가시킵니다 cmp
. cmp[1]
첫 번째 필드( a.csv
)가 두 번째 필드( )보다 크면 b.csv
값이 증가합니다. cmp[0]
두 필드가 동일하면 값이 증가합니다. cmp[-1]
두 번째 필드가 첫 번째 필드보다 크면 값이 증가합니다.
마지막으로 END
결과를 블록으로 인쇄합니다.
Perl에서도 우주선 연산자를 사용하여 동일한 작업이 수행됩니다 <=>
.
$ paste a.csv b.csv | perl -a -F'\t' -e '$. > 1 && ++$cmp{$F[0] <=> $F[1]}; END { printf "greater\t= %d\nsmaller\t= %d\nequal\t= %d\n", $cmp{1},$cmp{-1},$cmp{0} }'
greater = 2
smaller = 2
equal = 1
$.
NR
in Perl awk
은 in과 거의 동일하므로 $. > 1
입력의 헤더 행을 건너뜁니다. 를 사용한 경우 로 -MEnglish
변경할 수 있습니다 .$.
$NR
답변2
모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.
$ cat tst.awk
FNR==1 { next }
NR==FNR {
v[FNR] = $1
next
}
{
if ( v[FNR] > $1 ) { gt++ }
else if ( v[FNR] < $1 ) { lt++ }
else { eq++ }
}
END {
tot = gt + lt + eq
printf "%s is greater than %s in %d/%d cases.\n", ARGV[1], ARGV[2], gt, tot
printf "%s is smaller than %s in %d/%d cases.\n", ARGV[1], ARGV[2], lt, tot
printf "%s is equal to %s in %d/%d cases.\n", ARGV[1], ARGV[2], eq, tot
}
$ awk -f tst.awk a.csv b.csv
a.csv is greater than b.csv in 2/5 cases.
a.csv is smaller than b.csv in 2/5 cases.
a.csv is equal to b.csv in 1/5 cases.