Bestimmte Zeilen entfernen

Bestimmte Zeilen entfernen

Ich möchte ein paar Zeilen aus einer CSV-Datei entfernen.

Die Regeln sind recht einfach (Linie beibehalten, wenn):

  • Es ist die erste Zeile in der Datei.
  • Der erste Wert unterscheidet sich vom ersten Wert der vorherigen Zeile.
  • Der zweite Wert ist gegenüber der zuvor beibehaltenen Linie um mindestens 10 gestiegen.

Quelle

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

Ergebnis

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

Ich habe darüber nachgedacht, dies mit awk und einigen if-Anweisungen zu tun, bin aber nicht sicher, ob ich eine Variable erstellen kann, die zwischen der Datensatzverarbeitung übertragen wird.


EDIT: das wurde im Kommentarbereich (vor mir) versteckt:

Ich habe gerade herausgefunden, dass die Variablen zwischen Datensätzen verwendet werden können. Das funktioniert nicht ganz so wie C. Ich werde diese Frage entfernen, es sei denn, jemand gibt eine Antwort, die ich für andere als nützlich erachte, oder jemand bittet mich, die Antwort bereitzustellen.

Antwort1

Da es mit awk getaggt ist

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

Antwort2

Mit Perl:

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

Erweitert:

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]}: wenn die Nummer der aktuellen Zeile ist 1, das erste Feld der aktuellen Zeile gleich dem ersten Feld der vorherigen Zeile ist oder das zweite Feld der aktuellen Zeile größer oder gleich dem zweiten Feld der vorherigen Zeile ist, druckt die aktuelle Zeile und weist den Wert des zweiten Felds der aktuellen Zeile zu F1;
  • $F0=@F[0]: weist den Wert des ersten Felds der aktuellen Zeile zu 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

Antwort3

Verwenden eines Python-Skripts:

#! /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]))

Kopieren Sie das obige Skript und fügen Sie es in eine Datei mit dem Namen ein csvfilter.py.
Machen Sie es mit ausführbar chmod +x csvfilter.py.

Anschließend können Sie es von der Befehlszeile aus mit der zu verarbeitenden CSV-Datei (ich habe Ihr Beispiel aus der Frage unter gespeichert source.csv) als Argument ausführen:

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

Das Skript ändert die Originaldatei nicht, sondern druckt lediglich die neue Version auf die Standardausgabe. Außerdem wird jede vorherige Formatierung mit Leerzeichen verworfen.

Um die Originaldatei durch die geänderte Version zu ersetzen, leiten Sie die Ausgabe zurück in die Originaldatei um:

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

Sie können die geänderte Version auch als Datei speichern:

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

verwandte Informationen