Не могли бы вы попробовать следующее:
awk -v OFS="\t" '
NR==FNR { # this block is executed in the 1st pass only
if (FNR > 1) sum[$1] += $3
# accumulate the "count" for each "SampleID"
next
}
# the following block is executed in the 2nd pass only
FNR > 1 { # skip the header line
if ($1 != prev_id) {
# SampleID has changed. then update the output filename and print the header line
if (outfile) close(outfile)
# close previous outfile
outfile = $1 "_summary"
print "ASV_ID", "ASV_in_sample", "total_ASVs_inSample", "treshold_for_30%", "ASV_over30%" >> outfile
prev_id = $1
}
mark = ($3 > sum[$1] * 0.3) ? 1 : 0
# set the mark to "1" if the "Count" exceeds 30% of sum
print $2, $3, sum[$1], sum[$1] * 0.3, mark >> outfile
# append the line to the summary file
}
' data.csv data.csv
data.csv:
SampleID ASV Count
1000A ASV_1216 14
1000A ASV_12580 150
1000A ASV_12691 260
1000A ASV_135 434
1000A ASV_147 79
1000A ASV_15 287
1000A ASV_16 361
1000A ASV_184 8
1000A ASV_19 42
1000B ASV_1 90
1000B ASV_2 90
1000B ASV_3 20
1000C ASV_4 100
1000C ASV_5 10
1000C ASV_6 10
В следующих выходных примерах последнее поле ASV_over30%
указывает 1
, если число превышает 30% от суммы суммы.
1000A_summary:
ASV_ID ASV_in_sample total_ASVs_inSample treshold_for_30% ASV_over30%
ASV_1216 14 1635 490.5 0
ASV_12580 150 1635 490.5 0
ASV_12691 260 1635 490.5 0
ASV_135 434 1635 490.5 0
ASV_147 79 1635 490.5 0
ASV_15 287 1635 490.5 0
ASV_16 361 1635 490.5 0
ASV_184 8 1635 490.5 0
ASV_19 42 1635 490.5 0
1000B_summary:
ASV_ID ASV_in_sample total_ASVs_inSample treshold_for_30% ASV_over30%
ASV_1 90 200 60 1
ASV_2 90 200 60 1
ASV_3 20 200 60 0
1000C_summary:
ASV_ID ASV_in_sample total_ASVs_inSample treshold_for_30% ASV_over30%
ASV_4 100 120 36 1
ASV_5 10 120 36 0
ASV_6 10 120 36 0
[Пояснения]
При расчете среднего значения входных данных нам нужно go до конца данных. Если мы хотим распечатать входную запись и среднее значение (или другую информацию, основанную на среднем) одновременно, нам нужно использовать хитрость:
- Чтобы сохранить все входные записи в память.
- Чтобы прочитать входные данные дважды.
Поскольку awk
подходит для чтения нескольких файлов, меняя порядок действий в зависимости от порядка файлов, я выбрал 2-й метод.
- Условие
NR==FNR
возвращает TRUE
при чтении только 1-го файла. Мы вычисляем сумму поля count
в этом блоке как 1-й проход. - В операторе
next
в конце блока пропускаются следующие коды. - Если 1-й файл Готово, скрипт читает 2-й файл, который, естественно, совпадает с 1-м файлом.
- При чтении 2-го файла условие
NR==FNR
больше не возвращает TRUE
и 1-й блок пропускается. - 2-й блок снова считывает входной файл, открывая файл для печати вывода, построчно считывая входные данные и добавляя информацию, такую как среднее значение, полученное в 1-м проходе.