Remover linhas específicas

3

Gostaria de remover algumas linhas de um arquivo csv.

As regras são simples o suficiente (manter 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 da 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 do registro.

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

Acabei de descobrir que as variáveis são utilizáveis entre registros. Algo que não funciona como o C. Vou remover essa pergunta a menos que alguém dê uma resposta que considere útil para os outros ou alguém me peça para fornecer a resposta.

    
por 0xbaadf00d 24.11.2015 / 13:21

3 respostas

5

Como está marcado com o awk

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


Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7
    
por 123 24.11.2015 / 15:24
1

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.py , por exemplo.
Torne-o executável usando chmod +x csvfilter.py .

Em seguida, 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 modifica o arquivo original, apenas imprime a nova versão na saída padrão. Além disso, qualquer formatação anterior usando espaços será descartada.

Para substituir o arquivo original pela versão modificada, redirecione a saída de volta ao 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
    
por Byte Commander 24.11.2015 / 14:49
0

Usando o 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 do segundo campo da linha atual 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
    
por kos 24.11.2015 / 14:33