我有一个制表符分隔的文件,其行如下:
chr1 1001 + KEEP 0.5 0.3 0.06 0.4 0.2 0.3 0.5
chr1 40004 + KEEP 0.93 0.2 0.6 0.25 0.8 NA NA
chr2 140004 + KEEP 0.03 0.02 0.06 0.05 0.08 NA 0.01
chr2 455235504 - KEEP NA 0.12 0.67 0.51 0.8 NA NA
chr3 5004 + KEEP 0.53 0.52 NA 0.5 NA 0.54 NA
..
我想计算第5列以后每行的最大值和最小值之间的差值,并提取此(最大 - 最小)差值等于或大于0.1的行。例如,根据上面给出的输入,我应该得到:
chr1 1001 + KEEP 0.5 0.3 0.06 0.4 0.2 0.3 0.5
chr1 40004 + KEEP 0.93 0.2 0.6 0.25 0.8 NA NA
chr2 455235504 - KEEP NA 0.12 0.67 0.51 0.8 NA NA
..
如何使用awk为每个文件大约几百万行执行此操作?
目前我正在尝试
awk '{min=max=$5;
for(i=5;i<=67;i++){
if($i<min) min=$i;
if($i>max) max=$i
}
print min,max}' test.txt
答案 0 :(得分:1)
主要是您错过了min
和max
之间的差异是否大于阈值的测试。您还应该使用NF
作为for
循环中的限制,而不是对67
之类的数字进行硬编码。
awk '{min=max=$5;
for(i=6;i<=NF;i++){
if ($i == "NA") continue;
if (min == "NA" || $i<min) min=$i;
if (max == "NA" || $i>max) max=$i
}
if ((max - min) > .1) print}' test.txt
我还添加了对NA
的检查,它会跳过这些值。
答案 1 :(得分:0)
这是一个没有额外依赖关系的Python解决方案,几乎可以在任何地方运行:
import fileinput
for line in fileinput.input():
strings = line.rstrip().split(' ')[4:]
numbers = [float(string) for string in strings if string != 'NA']
if max(numbers) - min(numbers) >= 0.1:
print line,
答案 2 :(得分:0)
另一种方式
awk '{min=max=x;for(i=5;i<=NF;i++){min=min!~/./||$i<min?$i:min;max=$i+0>max?$i:max}}
max-min>=.1' file
在每行的开头将min和max设置为0
然后从5循环到行中的字段数
然后,如果min未设置或小于$ i,则将其设置为$ i
如果max大于$ i,请将其设置为$ i
$ i + 0将删除“NA”,然后将其设置为0
打印最大减去min大于或等于.1的行。
这个答案假定max总是高于0。
如果max可以小于0
awk '{min=max=x
for(i=5;i<=NF;i++){min=min!~/./||$i<min?$i:min
$i!="NA"&&max=max!~/./||$i>max?$i:max}
} max-min>=.1' file
答案 3 :(得分:0)
$ cat tst.awk
{
min = max = ""
for (i=5; i<=NF; i++) {
if ($i == $i+0) {
min = ( (min == "") || ($i < min) ? $i : min)
max = ( (max == "") || ($i > max) ? $i : max)
}
}
}
(max - min) >= 0.1
$ awk -f tst.awk file
chr1 1001 + KEEP 0.5 0.3 0.06 0.4 0.2 0.3 0.5
chr1 40004 + KEEP 0.93 0.2 0.6 0.25 0.8 NA NA
chr2 455235504 - KEEP NA 0.12 0.67 0.51 0.8 NA NA
$i == $i+0
的测试仅在$i
为数字时才会生效,因此会丢弃$i
为"NA"
或任何其他非数字值的情况。< / p>
作为一项增强功能,如果您愿意,可以轻松调整它以报告没有数值的行:
{
min = max = ""
for (i=5; i<=NF; i++) {
if ($i == $i+0) {
min = ( (min == "") || ($i < min) ? $i : min)
max = ( (max == "") || ($i > max) ? $i : max)
}
}
}
min == "" { printf "ERROR[%d]: \"%s\" has no numeric values.\n", NR, $0 | "cat>&2" }
(max - min) >= 0.1