Remover linhas específicas

Remover linhas específicas

Gostaria de remover algumas linhas de um arquivo csv.

As regras são bastante simples (mantenha a linha se):

  • É a primeira linha do arquivo.
  • O primeiro valor é diferente do primeiro valor da linha anterior.
  • O segundo valor aumentou em pelo menos 10 em relação à linha mantida anterior.

Fonte

Test1,  0.0, 1
Test1,  0.2, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2,  0.3, 3
Test2,  1.0, 5
Test2, 11.0, 7

Resultado

Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7

Eu estava pensando em fazer isso com o awk e algumas instruções if, mas não tenho certeza se posso fazer uma variável que seja transferida entre o processamento de registros.


EDIT: isso estava escondido na seção de comentários (de mim):

Acabei de descobrir que as variáveis ​​podem ser utilizadas entre registros. Algo que não funciona como C. Retirarei esta pergunta, a menos que alguém dê uma resposta que considero útil para outras pessoas ou alguém me peça para fornecer a resposta.

Responder1

Já que está marcado com awk

awk -F", *" 'x!=$1||$2>=y+10{y=$2;print}{x=$1}' file


Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7

Responder2

Usando Perl:

perl -lane 'if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}$F0=@F[0]' file

Expandido:

if($. == 1 || "$F[0]" ne "$F0" || $F[1] >= $F1 + 10){
    print;
    $F1 = @F[1]
}
$F0 = @F[0]
  • if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}: se o número da linha atual for 1, o primeiro campo da linha atual é igual ao primeiro campo da linha anterior ou o segundo campo da linha atual é maior ou igual ao segundo campo da linha anterior, imprime a linha atual e atribui o valor da linha atual segundo campo para F1;
  • $F0=@F[0]: atribui o valor do primeiro campo da linha atual a F0;
% cat file
Test1,  0.0, 1
Test1,  0.2, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2,  0.3, 3
Test2,  1.0, 5
Test2, 11.0, 7
% perl -lane 'if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}$F0=@F[0]' file
Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7

Responder3

Usando um script Python:

#! /usr/bin/env python3
import sys
with open (sys.argv[1]) as f:
  rows=[list(map(str.strip, line.split(','))) for line in f.readlines()]
  result=rows[0:1]
  for r in rows:
    if r[0] != result[-1][0] or float(r[1]) >= float(result[-1][1])+10:
      result.append(r)
  print("\n".join([",".join(res) for res in result]))

Copie o script acima e cole-o em um arquivo chamado, csvfilter.pypor exemplo.
Torne-o executável usando chmod +x csvfilter.py.

Então você pode executá-lo a partir da linha de comando com o arquivo csv para processar (salvei seu exemplo da pergunta como source.csv) como argumento:

$ ./csvfilter.py source.csv 
Test1,0.0,1
Test1,10.0,3
Test2,0.1,1
Test2,11.0,7

O script não modificará o arquivo original, apenas imprimirá a nova versão na saída padrão. Além disso, qualquer formatação anterior com espaços será descartada.

Para substituir o arquivo original pela versão modificada, redirecione a saída de volta para o arquivo original:

$ ./csvfilter.py source.csv > source.csv

Você também pode salvar a versão modificada como um arquivo:

$ ./csvfilter.py source.csv > modified.csv

informação relacionada