根据大数据集中的子组(A、B、C)查找命中

Finding hits based on subgroups (A, B, C) in big data set

我有大量数据需要分析。

从这个示例文件中,我需要知道找到的所有匹配项 ("samples")

但不是找到的

[编辑:为了更简单:B 和 C 不应同时出现]

这些字母位于 $8 列中。

前两列一起可以用作每个 "sample" 的标识符。

示例:您可以看到,对于“463;88”,我们在 $8 列中找到了 A 和 C,这将使“463;88”成为我需要在单独的输出文件中找到的命中。 “348;64”在 A、B 和 C 中找到,因此将是 discarded/ignored。

File1.csv

463;88;1;193187729;280062;CDC73;IS;A;0.0
463;88;1;193188065;280062;CDC73;IS;A;0.0
463;88;1;193188527;280062;CDC73;IS;A;0.0
463;88;1;193188542;280062;CDC73;IS;C;0.0
348;64;1;155219446;384172;GBAP1;IS;B;0.0
348;64;1;155224629;384172;GBAP1;IS;C;0.0
348;64;1;155224965;384172;GBAP1;IS;A;0.0
71;35;2;27400461;145220;PPM1G;IS;A;0.0
71;35;2;27400930;145220;PPM1G;IS;A;0.0
71;35;2;27401162;145220;PPM1G;IS;A;0.0
71;35;2;27403518;145220;PPM1G;IS;B;0.0
71;35;2;27403545;145220;PPM1G;IS;B;0.0
71;35;2;27404353;145220;PPM1G;IS;B;0.0
71;35;2;27419156;145220;NRBP1;IS;B;0.0
7;14;20;2894103;92099;PTPRA;IS;B;0.0
7;14;20;2906211;92099;PTPRA;IS;C;0.0
7;14;20;2907301;92099;PTPRA;IS;C;0.0
...

有没有人建议如何使用 bash、awk、grep...?

不需要非常高效或快速,只需要可靠即可。

编辑:

我通过几个步骤生成了一个 csv table,其中行的第 1 列和第 2 列在 $8 列中包含 <3 个不同的条目。

awk 打印 $1、$2、$8 |排序-n | uniq > file.tmp1

awk 从 file.tmp1 打印 $1, $2 |排序-n | unic –c | sed 用于 csv 格式 > file.tmp2

最后,
awk 仅打印 file.tmp2 中计数小于 3 的标识符列(= 原始文件的 $8 列中只有一个或两个不同的字母)。

File2.csv
6;3;
12;9;
348;40; 463;88; ...

然后,我想用 fgrep --file=File2.csv File1.csv

但这似乎无法正常工作。而且它仍然需要手动分析,因为它也给了我错误的命中。

像这样的东西应该有用,除非你运行内存不足:

BEGIN { FS=";"; }
{
    keys[,] = 1;
    data[,,] = [=10=];
}
END {
    for (key in keys) {
        a = data[key,"A"];
        b = data[key,"B"];
        c = data[key,"C"];
        if (!(b && c)) {
            if (a) { print a; }
            if (b) { print b; }
            if (c) { print c; }
        }
    }
}

假设具有相同键的所有行都是连续的,这应该可行:

BEGIN { FS=";"; }
";" != key {
    if (!(data["B"] && data["C"])) {
        print key;
    }
    delete data;
    key = ";";
}
{
    data[] = 1;
}

你没有在你的问题中显示预期的输出,所以这是一个猜测,但这就是你要找的吗?

$ cat tst.awk
BEGIN { FS=OFS=";" }
{ curr =  FS  }
curr != prev { prt(); prev=curr }
{ lines[++numLines]=[=10=]; seen[]++ }
END { prt() }
function prt() {
    if ( !(seen["B"] && seen["C"]) ) {
        for ( lineNr=1; lineNr<=numLines; lineNr++) {
            print lines[lineNr]
        }
    }
    delete seen
    numLines=0
}

$ awk -f tst.awk file
463;88;1;193187729;280062;CDC73;IS;A;0.0
463;88;1;193188065;280062;CDC73;IS;A;0.0
463;88;1;193188527;280062;CDC73;IS;A;0.0
463;88;1;193188542;280062;CDC73;IS;C;0.0
71;35;2;27400461;145220;PPM1G;IS;A;0.0
71;35;2;27400930;145220;PPM1G;IS;A;0.0
71;35;2;27401162;145220;PPM1G;IS;A;0.0
71;35;2;27403518;145220;PPM1G;IS;B;0.0
71;35;2;27403545;145220;PPM1G;IS;B;0.0
71;35;2;27404353;145220;PPM1G;IS;B;0.0
71;35;2;27419156;145220;NRBP1;IS;B;0.0

另一种选择

只保留要删除的行的键,但扫描文件两次。另外,文件不需要排序。

$ awk -F';' '{k= FS } 
     NR==FNR {if(=="B") b[k]; 
              else if(=="C") c[k]; 
              if(k in b && k in c) d[k]; 
              next}  
    !(k in d)' file{,}

463;88;1;193187729;280062;CDC73;IS;A;0.0
463;88;1;193188065;280062;CDC73;IS;A;0.0
463;88;1;193188527;280062;CDC73;IS;A;0.0
463;88;1;193188542;280062;CDC73;IS;C;0.0
71;35;2;27400461;145220;PPM1G;IS;A;0.0
71;35;2;27400930;145220;PPM1G;IS;A;0.0
71;35;2;27401162;145220;PPM1G;IS;A;0.0
71;35;2;27403518;145220;PPM1G;IS;B;0.0
71;35;2;27403545;145220;PPM1G;IS;B;0.0
71;35;2;27404353;145220;PPM1G;IS;B;0.0
71;35;2;27419156;145220;NRBP1;IS;B;0.0

gawks位运算,可以进一步简化为

$ awk -F';' 'BEGIN {c["B"]=1; c["C"]=2} 
                   {k= FS } 
           NR==FNR {d[k]=or(d[k],c[]); next}  
           d[k]!=3' file{,}

or 是一个幂等函数,如果看到 "B" 或 "C" 就会更新数组。如果两者都看到该值将是 3,在第二轮打印其他所有内容。