Извлечь максимальные значения для каждого объекта из файла

Вы можете передать свой расчет для percentв bc.

percent=$(echo "scale=0;$num2*100" | bc)

Это даст вам число вроде "41.00", которое вы можете отрезать в конце с помощью

percent=${percent%.*}
0
09.04.2021, 14:58
3 ответа

Если предположить, что данные находятся в файле с именем fileи что они отсортированы по первому столбцу, утилита GNU datamashможет сделать это за один раз только с файлом данных:

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-inвместо -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просто содержит имена групп в качестве ключей.

5
28.04.2021, 22:53

Я предполагаю, что вы на самом деле не хотите делать это в bash (и не должны ), но готовы использовать другие инструменты. Вот подход GNU awk:

$ 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
2
28.04.2021, 22:53

Это подход, в котором не используются ни настоящие многомерные массивы, ни эмулированные многомерные -измерения. Вместо этого мы храним фрагменты в одном и том же ключе.

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
0
28.04.2021, 22:53

Теги

Похожие вопросы