在进行数值分析的后处理时,我有以下选择数据的问题:
time_1 result_1 time_2 result_2
1 10 1.1 10.1
2 20 1.6 15.1
3 30 2.1 20.1
4 40 2.6 25.1
5 50 3.1 30.1
6 60 3.6 35.1
7 70 4.1 40.1
8 80 4.6 45.1
9 90 5.1 50.1
10 100 5.6 55.1
6.1 60.1
6.6 65.1
7.1 70.1
7.6 75.1
8.1 80.1
8.6 85.1
9.1 90.1
9.6 95.1
10.1 100.1
此文件有4列,第一列(time_1)表示程序1的计算时刻,第二列(result_1)是为每个时刻计算的结果。
第三列(time_2)表示另一个程序的计算时刻,第四列(result_2)是为该程序2的每个时刻计算的结果。
现在我希望仅选择非常接近第一列(time_1)时刻的第三列(time_2)的时刻,允许的差异小于或等于0.1。例如:
对于time_1列的瞬间1,我希望选择time_2列的即时1.1,因为(1.1 - 1)= 0.1,我不想选择time_2列的其他时刻因为(1.6 - 1)> 0.1,或(2.1-1)> 0.1
对于time_1列的瞬间2,我希望选择time_2列的即时2.1,因为(2.1 - 2)= 0.1,我不想选择time_2列的其他时刻因为(2.6 - 1)> 0.1,或(3.1-1)> 0.1
最后,我想获得以下数据:
time_1 result_1 time_2 result_2
1 10 1.1 10.1
2 20 2.1 20.1
3 30 3.1 30.1
4 40 4.1 40.1
5 50 5.1 50.1
6 60 6.1 60.1
7 70 7.1 70.1
8 80 8.1 80.1
9 90 9.1 90.1
10 100 10.1 100.1
我希望使用awk,但我还没有熟悉这段代码。我不知道如何修复第一列的元素,然后将其与第三列的所有元素进行比较,以便选择第三列的正确值。如果我非常喜欢这样,我只能打印第一行:
{if (($3>=$1) && (($3-$1) <= 0.1)) {print $2, $4}}
提前感谢您的帮助!
答案 0 :(得分:1)
您可以尝试以下perl脚本:
#! /usr/bin/perl
use strict;
use warnings;
use autodie;
use File::Slurp qw(read_file);
my @lines=read_file("file");
shift @lines; # skip first line
my @a;
for (@lines) {
my @fld=split;
if (@fld == 4) {
push (@a,{id=>$fld[0], val=>$fld[1]});
}
}
for (@lines) {
my @fld=split;
my $id; my $val;
if (@fld == 4) {
$id=$fld[2]; $val=$fld[3];
} elsif (@fld == 2) {
$id=$fld[0]; $val=$fld[1];
}
my $ind=checkId(\@a,$id);
if ($ind>=0) {
$a[$ind]->{sel}=[] if (! exists($a[$ind]->{sel}));
push(@{$a[$ind]->{sel}},{id=>$id,val=>$val});
}
}
for my $item (@a) {
if (exists $item->{sel}) {
my $s= $item->{sel};
for (@$s) {
print $item->{id}."\t".$item->{val}."\t";
print $_->{id}."\t".$_->{val}."\n";
}
}
}
sub checkId {
my ($a,$id) = @_;
my $dif=0.1+1e-10;
for (my $i=0; $i<=$#$a; $i++) {
return $i if (abs($a->[$i]->{id}-$id)<=$dif)
}
return -1;
}
答案 1 :(得分:0)
有一点需要注意:由于浮点数的变幻莫测,将值与0.1进行比较不太可能为您提供所需的结果:
awk 'BEGIN {x=1; y=x+0.1; printf "%.20f", y-x}'
0.10000000000000008882⏎
此处y=x+0.1
,但y-x > 0.1
因此,我们将差异视为diff = 10*y - 10x
:
此外,我将处理文件两次:一次获取所有time_1 / result_1值,第二次提取“匹配”time_2 / result_2值。
awk '
NR==1 {print; next}
NR==FNR {if (NF==4) r1[$1]=$2; next}
FNR==1 {next}
{
if (NF == 4) {t2=$3; r2=$4} else {t2=$1; r2=$2}
for (t1 in r1) {
diff = 10*t1 - 10*t2;
if (-1 <= diff && diff <= 1) {
print t1, r1[t1], t2, r2
break
}
}
}
' ~/tmp/timings.txt ~/tmp/timings.txt | column -t
time_1 result_1 time_2 result_2
1 10 1.1 10.1
2 20 2.1 20.1
3 30 3.1 30.1
4 40 4.1 40.1
5 50 5.1 50.1
6 60 6.1 60.1
7 70 7.1 70.1
8 80 8.1 80.1
9 90 9.1 90.1
10 100 10.1 100.1