我有一个具有以下结构的文本文件
ID,operator,a,b,c,d,true
WCBP12236,J1,75.7,80.6,65.9,83.2,82.1
WCBP12236,J2,76.3,79.6,61.7,81.9,82.1
WCBP12236,S1,77.2,81.5,69.4,84.1,82.1
WCBP12236,S2,68.0,68.0,53.2,68.5,82.1
WCBP12234,J1,63.7,67.7,72.2,71.6,75.3
WCBP12234,J2,68.6,68.4,41.4,68.9,75.3
WCBP12234,S1,81.8,82.7,67.0,87.5,75.3
WCBP12234,S2,66.6,67.9,53.0,70.7,75.3
WCBP12238,J1,78.6,79.0,56.2,82.1,84.1
WCBP12239,J2,66.6,72.9,79.5,76.6,82.1
WCBP12239,S1,86.6,87.8,23.0,23.0,82.1
WCBP12239,S2,86.0,86.9,62.3,89.7,82.1
WCBP12239,J1,70.9,71.3,66.0,73.7,82.1
WCBP12238,J2,75.1,75.2,54.3,76.4,84.1
WCBP12238,S1,65.9,66.0,40.2,66.5,84.1
WCBP12238,S2,72.7,73.2,52.6,73.9,84.1
每个
ID
对应一个由运算符(operator)多次分析的数据集。即 J1
和 J2
是运算符 J 的第一次和第二次尝试。 a
、 b
、 c
和 d
使用 4 种略有不同的算法来测量其真实值位于 true
列中的值我想做的是创建 3 个新的文本文件,比较
J1
与 J2
、 S1
与 S2
和 J1
与 S1
的结果。 J1
与 J2
的示例输出:ID,operator,a1,a2,b1,b2,c1,c2,d1,d2,true
WCBP12236,75.7,76.3,80.6,79.6,65.9,61.7,83.2,81.9,82.1
WCBP12234,63.7,68.6,67.7,68.4,72.2,41.4,71.6,68.9,75.3
其中
a1
是 a
的测量 J1
等。另一个例子是
S1
与 S2
:ID,operator,a1,a2,b1,b2,c1,c2,d1,d2,true
WCBP12236,77.2,68.0,81.5,68.0,69.4,53.2,84.1,68.5,82.1
WCBP12234,81.8,66.6,82.7,67.9,67.0,53,87.5,70.7,75.3
ID 不会按字母数字顺序排列,也不会为同一 ID 聚集运算符。我不确定如何最好地完成这项任务 - 使用 linux 工具或 perl/python 之类的脚本语言。
我最初使用 linux 的尝试很快就碰壁了
首先找到所有唯一ID(已排序)
awk -F, '/^WCBP/ {print $1}' file | uniq | sort -k 1.5n > unique_ids
循环遍历这些 ID 并对
J1
、 J2
进行排序:foreach i (`more unique_ids`)
grep $i test.txt | egrep 'J[1-2]' | sort -t',' -k2
end
这给了我排序的数据
WCBP12234,J1,63.7,67.7,72.2,71.6,75.3
WCBP12234,J2,68.6,68.4,41.4,68.9,80.4
WCBP12236,J1,75.7,80.6,65.9,83.2,82.1
WCBP12236,J2,76.3,79.6,61.7,81.9,82.1
WCBP12238,J1,78.6,79.0,56.2,82.1,82.1
WCBP12238,J2,75.1,75.2,54.3,76.4,82.1
WCBP12239,J1,70.9,71.3,66.0,73.7,75.3
WCBP12239,J2,66.6,72.9,79.5,76.6,75.3
我不确定如何重新排列这些数据以获得所需的结构。我尝试在
awk
循环 foreach
中向 awk 'BEGIN {RS="\n\n"} {print $1, $3,$10,$4,$11,$5,$12,$6,$13,$7}'
添加一个额外的管道有任何想法吗?我确信这可以使用
awk
以一种不那么麻烦的方式完成,尽管使用适当的脚本语言可能会更好。 最佳答案
您可以使用 Perl csv 模块 Text::CSV 提取字段,然后将它们存储在哈希中,其中 ID 是主键,第二个字段是辅助键,所有字段都存储为值。然后做任何你想做的比较应该是微不足道的。如果要保留行的原始顺序,可以在第一个循环中使用数组。
use strict;
use warnings;
use Text::CSV;
my %data;
my $csv = Text::CSV->new({
binary => 1, # safety precaution
eol => $/, # important when using $csv->print()
});
while ( my $row = $csv->getline(*ARGV) ) {
my ($id, $J) = @$row; # first two fields
$data{$id}{$J} = $row; # store line
}
关于python - 组合具有匹配键的行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17272454/