从文件中提取每个对象的最大值

从文件中提取每个对象的最大值

我需要从bashCentOS 系统上的文件中提取一些值。我myfile.txt有一个被调用的对象列表Info_region,其中每个对象都用代码(例如BARD1_region_005BIRC2_region_002等)标识。此外,还有一些其他列报告了一些数值变量。相同的对象(相同的代码名称)可以在我的文件中重复多次。我还有一个文件,其中包含完整的列表,其中包含所有目标代码,没有重复项。我想获得一个output.txt 文件,其中每个对象(代码名)仅报告一次,如我的list-file.txt 中所示,并且我想将与myfile 中该代码名关联的最大可能值关联到此文件。 TXT。

myfile.txt:(列由 分隔tab

Info_region Lig_score   Lig_prevista    Lig_prevista_+1 Int_score   Expo_score  Protac_score
BARD1_region_005    0   3   3   0   1   1
BARD1_region_006    0   1   1   0   1   1
BIRC2_region_001    1   6   7   0   1   2
BIRC2_region_001    1   7   8   0   1   2
BIRC2_region_001    0   2   2   0   0   0
BIRC2_region_001    0   12  12  0   1   1
BIRC2_region_001    1   10  11  -1  1   1
BIRC2_region_001    1   2   3   0   1   2
BIRC2_region_001    1   0   1   0   1   2
BIRC2_region_001    1   6   7   0   1   2
BIRC2_region_002    0   0   0   0   1   1
BIRC2_region_002    1   0   0   -1  0.5 0.5
BIRC2_region_003    0   0   0   0   1   1
BIRC2_region_004    0   1   1   0   1   1
UHRF1_region_004    0   0   0   1   1   2
UHRF1_region_004    0   0   0   1   1   2
UHRF1_region_004    1   0   1   0   0.5 1.5
UHRF1_region_004    0   0   0   1   1   2
UHRF1_region_005    0   3   3   1   1   2
UHRF1_region_005    1   0   0   -1  1   1

文件列表.txt:

Info_region
BARD1_region_005
BARD1_region_006
BIRC2_region_001
BIRC2_region_002
BIRC2_region_003
BIRC2_region_004
UHRF1_region_004
UHRF1_region_005

输出.txt:

Info_region Lig_score   Lig_prevista    Lig_prevista_+1 Int_score   Expo_score  Protac_score
BARD1_region_005    0   3   3   0   1   1
BARD1_region_006    0   1   1   0   1   1
BIRC2_region_001    1   12  12  0   1   2
BIRC2_region_002    1   0   0   0   1   1
BIRC2_region_003    0   0   0   0   1   1
BIRC2_region_004    0   1   1   0   1   1
UHRF1_region_004    1   0   1   1   1   2
UHRF1_region_005    1   3   3   1   1   2

有人可以帮我吗?谢谢你!

答案1

假设数据位于被调用的文件中file并且在第一列上排序,GNUdatamash实用程序可以单独对数据文件一次性执行此操作:

datamash -H -W -g 1 max 2-7 <file

这指示实用程序使用空格分隔的列(-W;如果您的列确实是制表符分隔的,则删除此列),数据的第一行包含标题 ( -H),按第一列 ( ) 进行分组-g 1,并计算最大值从第 2 列到第 7 列。

考虑到问题中的数据,结果:

GroupBy(Info_region)    max(Lig_score)  max(Lig_prevista)       max(Lig_prevista_+1)    max(Int_score)     max(Expo_score) max(Protac_score)
BARD1_region_005        0       3       3       0       1       1
BARD1_region_006        0       1       1       0       1       1
BIRC2_region_001        1       12      12      0       1       2
BIRC2_region_002        1       0       0       0       1       1
BIRC2_region_003        0       0       0       0       1       1
BIRC2_region_004        0       1       1       0       1       1
UHRF1_region_004        1       0       1       1       1       2
UHRF1_region_005        1       3       3       1       1       2

您还可以使用--header-inin 来-H获取无标头输出,然后从原始数据文件中获取标头:

{ head -n 1 file; datamash --header-in -W -g 1 max 2-7 <file; } >output

在这里,我还将结果写入一些名为output.


使用awk并假设制表符分隔字段:

awk -F '\t' '
    BEGIN { OFS = FS }
    NR == 1 { print; next }
    {
        n[$1] = 1
        for (i = 2; i <= NF; ++i)
            a[$1,i] = (a[$1,i] == "" || $i > a[$1,i] ? $i : a[$1,i])
    }
    END { 
        nf = NF
        for (j in n) {
            $0 = j
            for (i = 2; i <= nf; ++i)
                $i = a[$1,i]
            print
         }
     }' file

这将计算每组每列中的最大值。这些数字存储在a数组中,而n数组仅将组名称作为键保存。

答案2

我假设您实际上不想在 bash 中执行此操作(而且您不应该这样做),但愿意使用其他工具。这是一个 GNUawk方法:

$ gawk -vOFS="\t" -F'\t' \
    '{ 
        if(NR==1){print; } 
        else{ 
            for(i=2;i<=NF;i++){ 
                if($i > a[$1][i] || ! a[$1][i]){a[$1][i]=$i}
           }
        } 
     }
     END{ 
        for (region in a){ 
            printf "%s", region; 
            for(i=2;i<=NF;i++){ 
                printf "%s%s", OFS,a[region][i]
            } 
            printf "\n";  
        } 
     }' myfile.txt 
Info_region Lig_score   Lig_prevista    Lig_prevista_+1 Int_score   Expo_score  Protac_score
BIRC2_region_001    1   12  12  0   1   2
BIRC2_region_002    1   0   0   -1  1   1
BIRC2_region_003    0   0   0   0   1   1
BIRC2_region_004    0   1   1   0   1   1
BARD1_region_005    0   3   3   0   1   1
BARD1_region_006    0   1   1   0   1   1
UHRF1_region_004    1   0   1   1   1   2
UHRF1_region_005    1   3   3   1   1   2

答案3

这是一种既不使用真正的多维数组也不使用模拟多维的方法。相反,我们将块存储在同一个键中。

awk '
BEGIN { OFS = FS = "\t" }
NR==1 { print; next }
{
  obj = $1; $1=""; sub(FS, "")
  a[obj] = a[obj] $0 FS
}
END {
  nf0 = NF
  for (obj in a) {
    $1 = obj
    nf = split(a[obj], f)
    for (i=1; i<=nf0; i++) {
      $(i+1) = f[i]
      for (j=0; j<int(nf/nf0); j++) {
        idx = i + nf0*j
        if ( f[idx] > $(i+1) ) $(i+1) = f[idx]
      }
    }
    print
  }
}
' myfile.txt

相关内容