我有两个 csv 文件:a.csv 和 b.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 中也有同样的事情,使用它的 spaceship 操作符<=>
:
$ 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 与inawk
或多或少相同,因此$. > 1
会跳过输入中的标题行。如果您使用过-MEnglish
,则可以更改$.
为$NR
。
答案2
在每个 Unix 机器上的任何 shell 中使用任何 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.