awk: фильтр по числу ненулевых нефильтрующих - PullRequest
0 голосов
/ 05 июля 2018

Ранее я использовал awk, чтобы уменьшить огромную таблицу данных, которая в основном состоит из нулей, до таблицы меньшего размера, содержащей только интересные строки (те, у которых не слишком много нулей), примерно так:

awk -F '\t' '{count=0} {for(i=2; i<30; i++) if($i==0) count++} {if(count<5) print $0}' BigTable > SmallerTable 

Теперь я хотел бы отфильтровать похожую таблицу, чтобы найти строки с ненулевыми значениями в большинстве "женских" столбцов и нули в большинстве "мужских" столбцов. Я пытался использовать ту же логику awk, но мой код возвращает все строки входного файла.

#! /usr/bin/awk -f 
FS="\t"
{countF=0} {for(i=2; i<7; i++) if($i==0) countF++} 
# count zeros in female columns 2-6
{countM=0} {for(i=7; i<12; i++) if($i==0) countM++} 
# count zeros in male columns 7-12
{if (countF<2 && countM>3) {print $0}}
# if fewer than 2/5 females AND more than 3/5 males are zero, print line

Мой входной файл начинается так:

NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN F_CR1   F_CR2   F_CR3   F_CR4   F_CR6   M_CR10  M_CR5   M_CR7   M_CR8   M_CR9
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 14727   13526   13318   13862   11040   18975   21411   20079   16285   15611
CCGGTGTGACAACTGTAGTGAACTCAGCTCA 23  32  26  15  28  28  42  29  8   22
AACCAAATCTACAAACAGGAGATGTTGTTCT 107 110 118 106 95  100 121 132 92  90
GAAATAGAACAGGCCTGGAAGCCATGTCAAA 15  15  16  12  11  31  23  19  9   28

Не перепутал ли я синтаксис в строке печати? Любой совет высоко ценится!

1 Ответ

0 голосов
/ 05 июля 2018

Измените FS="\t" на BEGIN{FS="\t"}. Прямо сейчас результатом этого присваивания является истинное условие, которое вызывает действие по умолчанию печати каждой строки.

Затем измените ваш сценарий оболочки на:

/usr/bin/awk '
BEGIN { FS="\t" }
{
    # count zeros in female columns
    countF=0
    for(i=2; i<=6; i++) {
        if ($i==0) {
            countF++
        }
    }

    # count zeros in male columns
    countM=0
    for(; i<=NF; i++) {
        if ($i==0) {
            countM++
        }
    }
}
# if fewer than 2/5 females AND more than 3/5 males are zero, print line
countF<2 && countM>3
' "$@"

так что это более awk-ish и его легче улучшать позже, если / когда вам нужно разделить аргументы оболочки на awk args и присваивания переменных awk (shebangs для этого не нужны).

Также рассмотрите возможность его сокращения и удаления жестко запрограммированных лимитов Муж / Женщина, но вместо этого получите их из строки заголовка:

/usr/bin/awk '
BEGIN { FS="\t" }
FNR==1 {
    for (i=2; i<=NF; i++) {
        sub(/_.*/,"",$i)
        gender[i] = $i
    }
    next
}
{
    for (i=2; i<=NF; i++) {
        count[gender[i]] += ($i==0)
    }
}
count["F"]<2 && count["M"]>3
' "$@"

Выше не проверено, так как вы не предоставили ожидаемый результат для нас для тестирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...