根据大数据集中的子组(A、B、C)查找命中
Finding hits based on subgroups (A, B, C) in big data set
我有大量数据需要分析。
从这个示例文件中,我需要知道找到的所有匹配项 ("samples")
- 只在B,
- 仅在 C 中,
- 在 A 和 C 或
- 在 A 和 B 中,
但不是找到的
- 在 B 和 C 或
- 在 A、B 和 C 中。
[编辑:为了更简单: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
与gawk
s位运算,可以进一步简化为
$ 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
,在第二轮打印其他所有内容。
我有大量数据需要分析。
从这个示例文件中,我需要知道找到的所有匹配项 ("samples")
- 只在B,
- 仅在 C 中,
- 在 A 和 C 或
- 在 A 和 B 中,
但不是找到的
- 在 B 和 C 或
- 在 A、B 和 C 中。
[编辑:为了更简单: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
与gawk
s位运算,可以进一步简化为
$ 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
,在第二轮打印其他所有内容。