2012-05-09 5 views
6

Ich bin neu in Python und versuche, "Blöcke" von Daten aus einer Datei zu lesen. Die Datei wird geschrieben so etwas wie:Lesen von Datenblöcken aus einer Datei in Python

# Some comment 
# 4 cols of data --x,vx,vy,vz 
# nsp, nskip =   2   10 


#   0 0.0000000 


#   1   4 
0.5056E+03 0.8687E-03 -0.1202E-02 0.4652E-02 
0.3776E+03 0.8687E-03 0.1975E-04 0.9741E-03 
0.2496E+03 0.8687E-03 0.7894E-04 0.8334E-03 
0.1216E+03 0.8687E-03 0.1439E-03 0.6816E-03 


#   2   4 
0.5056E+03 0.8687E-03 -0.1202E-02 0.4652E-02 
0.3776E+03 0.8687E-03 0.1975E-04 0.9741E-03 
0.2496E+03 0.8687E-03 0.7894E-04 0.8334E-03 
0.1216E+03 0.8687E-03 0.1439E-03 0.6816E-03 


#   500 0.99999422 


#   1   4 
0.5057E+03 0.7392E-03 -0.6891E-03 0.4700E-02 
0.3777E+03 0.9129E-03 0.2653E-04 0.9641E-03 
0.2497E+03 0.9131E-03 0.7970E-04 0.8173E-03 
0.1217E+03 0.9131E-03 0.1378E-03 0.6586E-03 

and so on 

Jetzt möchte ich in der Lage sein, nur einen Block von Daten aus diesen vielen Blöcken spezifizieren und lesen. Ich benutze numpy.loadtxt('filename',comments='#'), um die Daten zu lesen, aber es lädt die ganze Datei auf einmal. Ich suchte online und jemand hat einen Patch für die numpy io Routine erstellt, um Lese-Blöcke zu spezifizieren, aber es ist nicht im Mainstream numpy.

Es ist viel einfacher, Blöcke von Daten in gnuplot zu wählen, aber ich würde die Routine schreiben müssen, um die Verteilungsfunktionen zu zeichnen. Wenn ich bestimmte Blöcke Lesen herausfinden können, wäre es viel einfacher, in Python sein. Außerdem verschiebe ich alle meine Visualisierungscodes von IDL und gnuplot nach python, also ist es schön, alles in Python zu haben, anstatt Dinge in mehreren Paketen herumzustreuen.

Ich dachte über gnuplot aus Python aufrufen, um einen Block zu einer Tabelle Plotten und die Ausgabe zu einem gewissen Array in Python zuweisen. Aber ich fange noch und ich konnte nicht die Syntax herauszufinden, es zu tun.

Irgendwelche Ideen, Hinweise, um dieses Problem zu lösen, wäre eine große Hilfe.

+0

So möchten Sie die Benutzer angeben, sagen wir ein Wertepaar (i, j) und lese alle Zeilen zwischen der Zeile "# ij" und der nächsten Leerzeile? –

+0

Alsmot!Das Genauere, was ich tun kann, ist, i, j angeben zu können, wobei i der Startblock und j der letzte Block ist und ein Block durch Zeilen definiert ist, die durch zwei oder mehr leere Zeilen getrennt sind. – toylas

Antwort

6

Eine schnelle Basis-Lese:

>>> def read_blocks(input_file, i, j): 
    empty_lines = 0 
    blocks = [] 
    for line in open(input_file): 
     # Check for empty/commented lines 
     if not line or line.startswith('#'): 
      # If 1st one: new block 
      if empty_lines == 0: 
       blocks.append([]) 
      empty_lines += 1 
     # Non empty line: add line in current(last) block 
     else: 
      empty_lines = 0 
      blocks[-1].append(line) 
    return blocks[i:j + 1] 

>>> for block in read_blocks(s, 1, 2): 
    print '-> block' 
    for line in block: 
     print line 


-> block 
0.5056E+03 0.8687E-03 -0.1202E-02 0.4652E-02 
0.3776E+03 0.8687E-03 0.1975E-04 0.9741E-03 
0.2496E+03 0.8687E-03 0.7894E-04 0.8334E-03 
0.1216E+03 0.8687E-03 0.1439E-03 0.6816E-03 
-> block 
0.5057E+03 0.7392E-03 -0.6891E-03 0.4700E-02 
0.3777E+03 0.9129E-03 0.2653E-04 0.9641E-03 
0.2497E+03 0.9131E-03 0.7970E-04 0.8173E-03 
0.1217E+03 0.9131E-03 0.1378E-03 0.6586E-03 
>>> 

Nun ich denke, man numpy den Zeilen lesen können ...

+0

Vielen Dank Emmanuel !! Es funktionierte fast genau wie von selbst. Ich musste ein paar Bits lernen und kümmere mich um Leerzeichen in meinen Dateien usw. Ich implementierte auch Pascals Vorschlag, die Zeile vor dem Anhängen des Blocks zu teilen. Jetzt gibt mir der finale Code ein 3D-Array, wobei jeder Block eine Ebene im 3D-Array ist. Vielen Dank für die Hilfe! Ich wünschte, ich könnte Python etwas schneller lernen. – toylas

+0

Gibt es eine elegantere Art, diese Linie zu implementieren? b = a.split(); b = np.array (b); b = b.type (float) – toylas

+0

Danke für die Validierung! Was deine Frage angeht, sehe ich nicht, warum 'b = np.array (a.split()). Astype (float)' nicht funktionieren würde. – Emmanuel

1

Der folgende Code sollte Sie wahrscheinlich starten. Sie werden wahrscheinlich das neue Modul benötigen.

Sie die Datei mit zum Lesen öffnen:

f = open("file_name_here") 

Sie die Datei eine Zeile zu einem Zeitpunkt lesen können mit

line = f.readline() 

in die nächste Zeile springen, die mit beginnt ein " #“können Sie verwenden:

while not line.startswith("#"): 
    line = f.readline() 

Um eine Zeile zu analysieren, die aussieht wie‚# ij‘, könnten Sie den folgenden regulären e verwenden xpression:

is_match = re.match("#\s+(\d+)\s+(\d+)",line) 
if is_match: 
    i = is_match.group(1) 
    j = is_match.group(2) 

Weitere Informationen hierzu finden Sie in der Dokumentation zum Modul "re".

einen Satz zu analysieren, können Sie das folgende Stück Code verwenden:

block = [[]] # block[i][j] will contain element i,j in your block 
while not line.isspace(): # read until next blank line 
    block.append(map(float,line.split(" "))) 
    # splits each line at each space and turns all elements to float 
    line = f.readline() 

Anschließend können Sie Ihr Block in eine numpy Array drehen, wenn Sie möchten:

block = np.array(block) 

Vorausgesetzt, Sie importiert haben numpy als np. Wenn Sie mehrere Blöcke zwischen i und j lesen möchten, setzen Sie einfach den obigen Code ein Block in eine Funktion zu lesen und es mehrfach verwenden.

Hoffe, das hilft!

+0

Vielen Dank Pascal! Ich nahm mir vor, die Zeile von Ihrem Beitrag zu trennen und benutzte sie in Emmanuals Vorschlag. Letztendlich werde ich Ihren Vorschlag umsetzen, den Text auch von den '#' Zeilen zu analysieren, aber im Moment muss ich nur einen funktionierenden Code bekommen und einige Plots innerhalb dieser Woche machen! Seufz ... – toylas