我有大量数据要分析。
在此示例文件中,我需要知道所有命中("样本"(
- 仅在B中,
- 仅在C中,
- 在A和C或 中
- 在A和B中,
但不是找到的
- 在B和C或C或 中
- 在a,b和c。 中
[编辑:保持更简单:B和C]
不应同时存在这些字母在第8列中找到。
前两列可以一起用作每个"样本"的标识符。
示例:您可以看到" 463; 88",我们在第8列中找到A和C,这将使" 463; 88"成为我在单独的输出文件中需要的命中。在A,B和C中发现了" 348; 64",因此将被丢弃/忽略。
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 ...?
它不需要非常有效或快速,只需要可靠。
编辑:
i生成了一个CSV表,其中包含< 3列中的3列条目的第1和2列的CSV表,以几个步骤$ 8。
尴尬打印$ 1,$ 2,$ 8 |排序–N |uniq> file.tmp1
awk打印$ 1,$ 2来自file.tmp1 |排序–N |UNIC –C |用于CSV格式> file.tmp2
最后,
awk仅在file.tmp2中打印标识符列,其中计数为< 3(=原始文件的列8列中的$ 8中的一个或两个不同的字母(。
file2.csv
6; 3;
12; 9;
348; 40;463; 88;...
然后,我想使用fgrep -file = file2.csv file1.csv
但这似乎无法正常工作。而且它仍然需要手动分析,因为它也给了我错误的命中。
另一种替代
仅保留要删除的行的键,但两次扫描文件。另外,不需要对文件进行排序。
$ awk -F';' '{k=$1 FS $2}
NR==FNR {if($8=="B") b[k];
else if($8=="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=$1 FS $2}
NR==FNR {d[k]=or(d[k],c[$8]); next}
d[k]!=3' file{,}
or
是一个IDEMPOTENT函数,如果可以看到" B"或" C",则更新数组。如果两者都看到该值是3
,则在第二轮中打印所有其他内容。
您没有在问题中显示预期的输出,所以这是一个猜测,但是这是您要寻找的吗?
$ cat tst.awk
BEGIN { FS=OFS=";" }
{ curr = $1 FS $2 }
curr != prev { prt(); prev=curr }
{ lines[++numLines]=$0; seen[$8]++ }
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
这样的东西应该有效,除非您的内存用完了:
BEGIN { FS=";"; }
{
keys[$1,$2] = 1;
data[$1,$2,$8] = $0;
}
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=";"; }
$1";"$2 != key {
if (!(data["B"] && data["C"])) {
print key;
}
delete data;
key = $1";"$2;
}
{
data[$8] = 1;
}