CSV auslesen

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.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Ahhhhh. Danke, fürs Drauf-Stupsen.
Macht das so mehr Sinn?

Code: Alles auswählen

from pprint import pprint

classifications = {
    'PL': [
        {
            'Atttributes': [
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                # ...
            ],
            'Bemerkung': '',
            'Beschreibung': '',
            'Blockname': '',
            # ...
        },
        {
            'Atttributes': [
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                # ...
            ],
            'Bemerkung': '',
            'Beschreibung': '',
            'Blockname': '',
            # ...
        }
    ],
    'PT': [
        {
            'Atttributes': [
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                # ...
            ],
            'Bemerkung': '',
            'Beschreibung': '',
            'Blockname': '',
            # ...
        },
        {
            'Atttributes': [
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                {
                    'AT-Default': '',
                    'AT-Name': '',
                    'Ausrichtung': '',
                    # ...
                },
                # ...
            ],
            'Bemerkung': '',
            'Beschreibung': '',
            'Blockname': '',
            # ...
        }
    ]
}

# Anmerkung: "..." steht für die fehlenden keys() in CLASSIFICATION_OBJECT_KEYS bzw. CLASSIFICATION_ATTRIBUTE_KEYS
pprint(classifications)
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Ich sage mal: grundsätzlich ja. Es kommt auch ein bisschen darauf an, was du hinterher damit machen willst.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe nicht, dass das mehr Sinn macht. Jetzt sind es Leerstrings. Wozu? Was sollen die erreichen? Wenn du einfach nur eine Liste von Attributnamen haben willst dann nimm eine Liste von Attributnamen.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Naja, Leerstrings sind es nicht zwangsläufig, es hängt halt von den Daten in der CSV ab...
Ja, in den Beispieldaten der CSV die ich hochgelanden habe sind zwar viele Felder leer, aber wie gesagt weis ich noch nicht hundert Prozent welche Daten der AT-Zeile ich final brauche, deshalb will ich erst einmal alles "importieren".
Ferner habe ich etwas geändert, hat aber nichts mit der gerade geschriebenen Argumentation zu tun.

Code: Alles auswählen

CLASSIFICATION_OBJECT_KEYS = (
    'Objektart', 'Messcode', 'Bemerkung', 'Objekttyp', 'Beschreibung', 'Blockname', 'Layer', 'Kurzcode', 'Gruppe')
CLASSIFICATION_ATTRIBUTE_KEYS = (
    'Wert-ID', 'Wert-Spalte', 'Wert-Pos', 'Wert-Necessary', 'Wert-UebTab', 'Wert-Faktor', 'AT-Name', 'AT-Default',
    'Ausrichtung', 'SY-Art', 'SY-InsertMode', 'XSize', 'YSize', 'XSizeMin', 'XSizeMax', 'YSizeMin', 'YSizeMax',
    'XSize-ID', 'XSize-Pos', 'YSize-ID', 'YSize-Pos', 'SY-ZusObj', 'SY-EinsetzPkt', 'SY-RiCode', 'PosRechts', 'PosHoch',
    'Massband-Pos')
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Habe noch einmal getestet...sollte doch dann soweit passen...abgesehen von den wichtigen Attributes, oder kann man da noch etwas optimieren?!

Code: Alles auswählen

import csv
from collections import defaultdict
from pathlib import Path
from pprint import pprint

CLASSIFICATION_IDENTIFIER = (
    'PT',  # Punkte
    'SY',  # Symbole und gerichtete Punkte
    'PL',  # Linienzüge
    'SG',  # Gruppierte Linien
    'TX',  # Texte
    'FL',  # Flächen
)

ATTRIBUTE_IDENTIFIER = 'AT'  # Attribute zu einem Objekt
DELIMITER_CSV = ';'

CLASSIFICATION_OBJECT_KEYS = (
    'Objektart', 'Messcode', 'Bemerkung', 'Objekttyp', 'Beschreibung', 'Blockname', 'Layer', 'Kurzcode', 'Gruppe')
CLASSIFICATION_ATTRIBUTE_KEYS = (
    'Wert-ID', 'Wert-Spalte', 'Wert-Pos', 'Wert-Necessary', 'Wert-UebTab', 'Wert-Faktor', 'AT-Name', 'AT-Default',
    'Ausrichtung', 'SY-Art', 'SY-InsertMode', 'XSize', 'YSize', 'XSizeMin', 'XSizeMax', 'YSizeMin', 'YSizeMax',
    'XSize-ID', 'XSize-Pos', 'YSize-ID', 'YSize-Pos', 'SY-ZusObj', 'SY-EinsetzPkt', 'SY-RiCode', 'PosRechts', 'PosHoch',
    'Massband-Pos')

DATA_DIRECTORY = Path(
    r'C:/ProgramData/rmDATA/Shared/CodeGrafik')


def load_classification(filepath):
    classifications = defaultdict(list)
    with open(filepath) as csvdatei:
        reader = csv.DictReader(csvdatei, delimiter=DELIMITER_CSV)
        for line in reader:
            if line['Objektart'] in CLASSIFICATION_IDENTIFIER:
                needed_keys = {}
                for key, value in line.items():
                    if key in CLASSIFICATION_OBJECT_KEYS:
                        needed_keys.update({key: value})
                needed_keys.update({'Attributes': None})
                classifications[line['Objektart']].append(needed_keys)
    return classifications


def main():
    classifications = load_classification(
        DATA_DIRECTORY / 'VDLF.csv')
    # print(f'Anzahl Objekte: {len(classifications)}')
    # print(classifications.keys())
    for o in classifications:
        print(f'{o}: {len(classifications[o])}')
    # pprint(classifications)


if __name__ == '__main__':
    main()
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Was sind needed_keys?
Gib Dingen verständliche Namen. Das sind keine "benötigten Schlüssel", dass ist eine classification.

Warum ist Attributes None? Attributes soll doch eine Liste sein, in die die Attribute kommen.

Man setzt keine Schlüssel mit Update man setzt Schlüssel mit:

Code: Alles auswählen

x[key] = value
wobei x in diesem Fall der Name ist, an den das dict gebunden wurde.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Feedback1000 hat geschrieben: Montag 30. Januar 2023, 16:23 Naja, Leerstrings sind es nicht zwangsläufig, es hängt halt von den Daten in der CSV ab...
Ah, mein Fehler - ich habe das irgendwie eher fuer ein Schema gehalten. Dann ist es natuerlich sinnvoll, wenn die Daten Strings sind.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

So, konnte das ganze mit euren Hinweisen jetzt zumindest mal zusammenschustern:

Code: Alles auswählen

import csv
from collections import defaultdict
from pathlib import Path
from pprint import pprint
import time

CLASSIFICATION_IDENTIFIER = (
    'PT',  # Punkte
    'SY',  # Symbole und gerichtete Punkte
    'PL',  # Linienzüge
    'SG',  # Gruppierte Linien
    'TX',  # Texte
    'FL',  # Flächen
)

ATTRIBUTE_IDENTIFIER = 'AT'  # Attribute zu einem Objekt
DELIMITER_CSV = ';'

CLASSIFICATION_OBJECT_KEYS = (
    'Objektart', 'Messcode', 'Bemerkung', 'Objekttyp', 'Beschreibung', 'Blockname', 'Layer', 'Kurzcode', 'Gruppe')
CLASSIFICATION_ATTRIBUTE_KEYS = (
    'Wert-ID', 'Wert-Spalte', 'Wert-Pos', 'Wert-Necessary', 'Wert-UebTab', 'Wert-Faktor', 'AT-Name', 'AT-Default',
    'Ausrichtung', 'SY-Art', 'SY-InsertMode', 'XSize', 'YSize', 'XSizeMin', 'XSizeMax', 'YSizeMin', 'YSizeMax',
    'XSize-ID', 'XSize-Pos', 'YSize-ID', 'YSize-Pos', 'SY-ZusObj', 'SY-EinsetzPkt', 'SY-RiCode', 'PosRechts', 'PosHoch',
    'Massband-Pos')

DATA_DIRECTORY = Path(
    r'C:/ProgramData/rmDATA/Shared/CodeGrafik')


def load_classification(filepath):
    classifications = defaultdict(list)
    with open(filepath) as csvdatei:
        reader = csv.DictReader(csvdatei, delimiter=DELIMITER_CSV)
        for line in reader:
            if line['Objektart'] in CLASSIFICATION_IDENTIFIER:
                current_classifications = {}
                for key, value in line.items():
                    if key in CLASSIFICATION_OBJECT_KEYS:
                        current_classifications[key] = value
                current_classifications['Attribute'] = []
                classifications[line['Objektart']].append(current_classifications)
            elif line['Objektart'] == ATTRIBUTE_IDENTIFIER and current_classifications:
                current_attributes = {}
                for key, value in line.items():
                    if key in CLASSIFICATION_ATTRIBUTE_KEYS:
                        current_attributes[key] = value
                current_classifications['Attribute'].append(current_attributes)
            else:
                current_classifications = None
    return classifications


def main():
    start = time.time()
    classifications = load_classification(
        DATA_DIRECTORY / 'VDLF.csv')
    # print(f'Anzahl Objekte: {len(classifications)}')
    # print(classifications.keys())
    pprint(classifications)
    for o in classifications:
        print(f'{o}: {len(classifications[o])}')
    ende = time.time()
    print('{:5.3f}s'.format(ende - start))

if __name__ == '__main__':
    main()
Aber zufrieden bin ich noch nicht...Seht ihr noch Verbesserungs-Potential? Wie ich euch kennen, ja. Würdet ihr dieses auch mit mit teilen?
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

classifications heißt so, weil das die Mehrzahl von classification ist. Es ist eine Datenstruktur, die mehrere Elemente enthäkt.
current_classifications deutet im Namen ebenfalls darauf hin, dass es sich um etwas in der Mehrzahl handelt. Es ist aber nur eine classification, weshalb ich sie current_classification nennen würde.

Wenn man Textdateien öffnet, wie hier die CSV-Datei, sollte man nach Möglichkeit das Encoding entsprechend der Erwartung angeben. Sonst wird der Systemstandard verwendet, der von dem tatsächlichen Encoding abweichen kann.

Wenn den dem ganzen noch das i-Tüpfelchen aufsetzen möchtest: es gibt dict comprehensions, die sich an dieser Stelle anbieten würden.
Aus

Code: Alles auswählen

                current_classifications = {}
                for key, value in line.items():
                    if key in CLASSIFICATION_OBJECT_KEYS:
                        current_classifications[key] = value
                current_classifications['Attribute'] = []
                classifications[line['Objektart']].append(current_classifications)
würde dann

Code: Alles auswählen

                current_classification = {
                    k:v for k, v in line.items() if k in CLASSIFICATION_OBJECT_KEYS
                }
                current_classification['Attribute'] = []
                classifications[line['Objektart']].append(current_classification)
Und aus

Code: Alles auswählen

                current_attributes = {}
                for key, value in line.items():
                    if key in CLASSIFICATION_ATTRIBUTE_KEYS:
                        current_attributes[key] = value
                current_classifications['Attribute'].append(current_attributes)
würde

Code: Alles auswählen

                current_classification['Attribute'].append(
                    {k:v for k,v in line.items() if k in CLASSIFICATION_ATTRIBUTE_KEYS}
                )
(current_classification habe ich hier schon auf die Einzahl umbenannt)

Es ist aber ungetestet und es ist spät.
Ob man dict comprehensions nutzt ist ein bisschen eigene Geschmackssache. Zumindest in meinen Augen.

Ansonsten: Glückwunsch zum erarbeiteten Script.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

@sparrow: Deine letzten Anmerkungen konnte ich einarbeiten.
@ALL: Vielen Dank eure Hilfe.
Antworten