2015-01-02 38 views
0

我與線條爲製表符分隔的文件:提取的行的最大 - 最小該行中滿足某些條件

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

請出示你試了一下,然後我們會幫助您解決問題。 SO不是免費的編碼服務。 – Barmar

+0

提示:你的代碼應該有一個像for(i = 5; i <= NF; i ++)這樣的循環來遍歷列並找到最小/最大值。 – Barmar

+0

目前我正在嘗試'awk'{min = max = $ 5; for(i = 5; i <= 11; i ++){if($ i max)max = $ i} print min,max}'test.txt'來測試'awk'是否可以提取最大值和最小值。然後我想着如何操作它來給我帶來改變。然後我會弄清楚如何設置給定的條件。 – Turtle

回答

1

主要是你只是缺少minmax之間的差是否大於你的閾值測試。您還應該使用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,它跳過這些值。

+0

太棒了!那個'==「不適用」位正是我所需要的。真棒 – Turtle

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, 
0

另一個awk的方式

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 

這在每行的開始設定的最小值和最大值爲0。
然後從5循環到行中的字段數。
然後,如果min未設置或小於$,我將它設置爲$ i。
如果最大值超過$ i,將其設置爲$ i
$ i + 0將刪除「NA」,然後將其設置爲0.
打印行,其中max minus min大於或等於到.1。

這個答案假定最大永遠是大於0

如果最大可小於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 
+0

我已經看到它使用了幾次,不能完全包圍我爲什麼人們這樣做,所以你可以解釋什麼好處是設置一個變量的一些其他變量尚未填充(var = x')而不是將其明確設置爲空字符串('var =「」')?我總是浪費時間去尋找「x」,看看它的價值是什麼,然後當我終於說服自己這是一個用來替代''「''的未設置變量時,感覺就像敲擊鍵盤一樣。如果它確實將評論中的最小和最大值設置爲零,那麼這就是錯誤的做法。 –

+1

@EdMorton對不起,我不知道我爲什麼這樣做,猜測它只是一個壞習慣。此外,我忘記編輯腳本後編輯評論,所以再次爲錯誤信息道歉。 –

+0

你並不孤單,我見過其他人這樣做,我真的只是不明白爲什麼所以我認爲必須有一些好處,我只是沒有得到...感謝回覆。 –

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"或任何其他非數字值的情況。

作爲增強,你可以很容易地調整它報告說根本沒有數字值的行,如果你喜歡:

{ 
    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 
相關問題