Daten aus Textdatei extrahieren, welche sich im Aufbau ändert

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Patrick1990
User
Beiträge: 116
Registriert: Freitag 3. Juni 2016, 05:45

Hallo,

ich habe überlegt ein Programm zu schreiben, welches mir bestimmte Daten aus einer Textdatei extrahiert.
Die Textdatei wird von einem Programm geschrieben, welches je nach Einstellungen die Datei unterschiedlich erzeugt.

Was schlagt ihr vor, wie gehe ich dort vor?
Ich würde eventuell nach markanten Tabellenheadern suchen und diese dann ausgeben und später dann die benötigten Header anklicken und die dazugehörigen Tabellen mit Daten einliest.

Wie bewerkstelligt man sowas am besten? Vielleicht hat jemand von euch schon etwas ähnliches gemacht.

Vielen Dank.
BlackJack

@Patrick1990: Das kommt jetzt sehr stark darauf an wie die Daten denn nun genau aussehen. Also Beispielsweise wie strukturiert sie sind, oder zumindest die Teile die Dich interessieren.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du musst da schon deutlich präziser werden, was genau meinst du mit Aufbau und inwiefern gibt es da Unterschiede? Dein Beitrag klingt danach als ob du einfach eine Tabelle hast die je nach Einstellung des Programms unterschiedliche Spalten (mehr oder weniger?) Spalten haben kann. Die Unterschiede die sich daraus ergeben würde ich noch lange nicht als unterschiedlichen Aufbau beschreiben.
Patrick1990
User
Beiträge: 116
Registriert: Freitag 3. Juni 2016, 05:45

Hier als Beispiel ein kleiner Auszug aus einer möglichen Datei:
Datei von filehorst.de laden

Ich möchte die Tabellen nach
Flux-Area k : Winding Key: 1
Flux-Area k : Winding Key: 2
Flux-Area k : Winding Key: 3

einlesen, weiterhin die Torque-Force Tabellen zu den Windig Keys usw.
Dies alles nochmals passend zu verschiedenen Winkelwerten:
Results for Angle I-Up [Degree]: 0.000
Results for Angle I-Up [Degree]: -20.000
...

Konnte ich euch das nun etwas näher bringen?
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Da musst du den üblichen Weg nehmen.
Datei öffnen, Zeile für Zeile einlesen, nach Schlüsselwörter suchen und dann analysieren.
Das dauert halt ein paar Stunden, um das zu programmieren.

Code: Alles auswählen

 with open("filename.txt", "r") as f:
        for line in f:
            line = line.strip()
            ...
            ...
           
BlackJack

@Patrick1990: So ganz allgemein: Probleme in Teilprobleme zerlegen. Und die dann auch wieder in Teilprobleme. Solange bis die kleinen Teilprobleme mit einer Funktion mit ein paar Zeilen einfach gelöst werden können. Diese Teillösungen dann zu grösseren Teillösungen zusammensetzen. Solange bis man eine Gesamtlösung hat.

Bei den Beispieldaten fallen mir auf Anhieb die Trennzeilen auf. Man könnte also vielleicht das Problem „Parsen der gesamten Datei“ in das Parsen von diesen getrennten Zeilenblöcken zerlegen. Schon ist es etwas kleiner und man kann Teillösungen für kleinere Datenhäppchen entwickeln und testen. Im allgemeinen Teil könnte man vielleicht anhand der ersten Zeile eines Blocks entscheiden welche Funktion zum Auswerten des Blocks verwendet werden soll, oder ob der Block ignoriert werden soll.

Schnell für die Beispieldaten zusammengehackt:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from collections import namedtuple
from itertools import chain, groupby, imap, takewhile
from operator import itemgetter


Table = namedtuple('Table', 'header units values')


def split_tab_line(line, convert=lambda x: x):
    return [convert(x.strip()) for x in line.split('\t')]


def parse_table(lines):
    return Table(
        split_tab_line(next(lines)),
        split_tab_line(next(lines)),
        [
            split_tab_line(line, float)
            for line in takewhile(lambda s: not s.startswith('...'), lines)
        ]
    )


class ObservedFlux(namedtuple('ObservedFlux', 'key table')):

    PREFIX = 'Flux observed:'

    @classmethod
    def parse_lines(cls, lines):
        next(lines)
        parts = next(lines).split('\t')
        assert parts[0] == 'Flux-Area k : Winding  ' and parts[1] == 'Key:'
        return cls(int(parts[2]), parse_table(lines))


class ResultsForAngle(namedtuple('ResultsForAngle', 'angle')):

    PREFIX = 'Results for Angle I-Up [Degree]:'

    @classmethod
    def parse_lines(cls, lines):
        return cls(float(next(lines).split('\t')[-1]))


class TorqueForce(namedtuple('TorqueForce', 'table')):

    PREFIX = 'Torque-Force'

    @classmethod
    def parse_lines(cls, lines):
        next(lines)
        second_line = next(lines)
        if second_line.startswith('F-Path'):
            return cls(parse_table(chain([second_line], lines)))
        else:
            return None


BLOCK_TYPES = [ObservedFlux, ResultsForAngle, TorqueForce]


def iter_blocks(lines):
    
    def stamp():
        i = 0
        for line in lines:
            if line.startswith('[*****'):
                i += 1
            else:
                yield (i, line)

    return (imap(itemgetter(1), g) for _, g in groupby(stamp(), itemgetter(0)))


def parse_blocks(lines):
    for block in iter_blocks(lines):
        try:
            first_line = next(block)
        except StopIteration:
            pass  # Block had zero lines.
        else:
            for block_type in BLOCK_TYPES:
                if first_line.startswith(block_type.PREFIX):
                    result = block_type.parse_lines(chain([first_line], block))
                    if result is not None:
                        yield result
                    break


def main():
    with open('test.txt') as lines:
        for result in parse_blocks(lines):
            print(result)


if __name__ == '__main__':
    main()
Antworten