Exclua uma linha que contém 0 mais do que 'x' quantidade de vezes

Exclua uma linha que contém 0 mais do que 'x' quantidade de vezes

Eu tenho um arquivo grande separado por vírgula. Preciso filtrar linhas que contenham x quantidade de colunas contendo zeros (excluindo a primeira linha). Para simplificar, digamos que eu queira filtrar linhas com mais de 4 zeros:

    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2
    gene3,0,0,0,0,6,0,0

Retornaria:

    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

Filtrando "gene3".

Aqui está o que eu tentei (tentando e não conseguindo usar ',0' como delimitador):

awk -F',0' 'NF<4 {print}' file.csv

Responder1

Com awk -F',0', três cópias ,0serão tomadas como trêsseparadores, dando quatroCamposno total. Portanto, se você usar awk -F',0' 'NF<5 {print}', deverá ver as linhas corretas na saída.

,0também corresponderá a strings como 213,0123, que você pode ou não querer considerar como separadores de zero.

Então, você também pode usar ,como separador de campos e contar os campos que contêm apenas aquele zero:

awk -F, '{z=0; for (i = 1 ; i <= NF ; i++) if ($i == 0) z++} z <= 4' file.csv

Responder2

Você também pode resolver seu problema usando expressões regulares e grep.

grep -Ev '(,0(,[^0,]+)*){4,}' file.csv

Eu testei neste arquivo:

gene,v1,v2,v3,v4,v5,v6,v7
gene1,0,1,5,0,0,4,100
gene2,1,0,0,0,5,210,2
gene3,0,0,0,0,6,0,0
gene4,0,0,0,4,6,0,0
gene5,0,1,0,4,6,0,0

Existem algumas suposições:

  • nenhum número diferente de zero começa com zero,
  • números zero contêm apenas um zero,
  • todos os números são inteiros.

A expressão regular pode ser estendida para resolver esses casos, caso seja necessário.

Responder3

Abordagem KISS, comawk

awk -F, '{c = 0; for(i=1; i<=NF; i++) {c += $i == "0" ? 1 : 0}} c <= 3' file.csv
    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

Comperl

perl -F, -ne 'print unless (grep { $_ eq "0" } @F) > 3' file.csv
    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

Responder4

Se todos os números forem inteiros, então usandoGNU awkque suporta limites de palavras \<...\>, você poderia fazer

gawk 'gsub(/\<0\>/, "0") <5' infile

informação relacionada