Aus einer Excel-Datei mit Python bestimmte Zeile ausgeben lassen

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.
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Hallo zusammen,

ich habe eine Frage bzw. benötige eure Hilfe bei der Umsetzung eines Problems. Ich beschreibe dies einfach im folgenden einmal:

Ich habe eine Excel-Datei, in welcher in einer Spalte immer Informationen zu einem Projekt stehen. Das bedeutet, in Spalte 1 stehen allgemeine Infos wie Höhe, Breite, Zeit, Kosten,.... In Spalte 2 beginnt dann oben "Projekt 1". Darunter kommen zu diesem Projekt dann eben die Zahlenwerte aus den allgemeinen Infos.

Beispiel:

.....................Projekt 1............Projekt 2............Projekt 3
Höhe1............... 1........................3.........................5
Breite1...............5........................5.........................1
Zeit1..................4.........................3.........................8
Höhe2...............3..........................6.........................8
Breite2...............7.........................9.........................6
Zeit2...................7.........................5........................10

Die Infos zu den Angaben der Projekte wiederholen sich sozusagen alle x-Zeilen. Das bedeutet die Zeit läuft sozusagen weiter, die anhängenden Werte ändern sich.
Ziel ist es einen Code zu schreiben, der die Excel-Datei einliest, dann durchsucht und mir die anhängenden Werte der Höhe und Breite ausgibt, wenn ein gewisser Grenzwert der Zeit erreicht ist (also eine gewisse Zeit zum ersten mal erreicht wird).
Das heißt also zB: Wenn die Zeit größer als 6 ist, gib mir den zugehörigen Höhen und Breiten-Wert dafür aus. --> Projekt1: Höhe 2/Breite 7,
--> Projekt2: nicht gefunden
--> Projekt3: Höhe 5/Breite 1

Kann mir dabei jemand helfen?
Vielen Dank im Voraus :)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Was hast Du bisher versucht? Wie sieht der Code dazu aus? Wo kommst Du konkret nicht weiter?
Sollst Du die Aufgabe mit Pandas lösen? Dann wäre das Pandas-Tutorial ein erster Anlaufpunkt.
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Ja ich würde das ganze mit Pandas lösen. Allerdings suche ich schon sehr lange, habe aber keinen Plan wie ich in der Excel dann spaltenweise nach unten suche bis die Zeit einen gewissen Grenzwert angenommen/überschritten hat und mir danach das zugehörige ausgeben lasse (also sozusagen bis die Zeit einen Wert x überschritten hat, dann den wert 3 Zeilen drüber ausgeben). Und das ganze für jede Spalte...
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Erster Schritt wäre, die Daten so aufzubreiten, dass man damit Arbeiten kann, also Bezeichner und Zahl trennen und das in einen Multiindex umwandeln, dann nach Zeit > x filtern, und dann für jedes Projekt den kleinesten Index suchen, für das die Bedingung erfüllt ist. Die Breite zu diesem Index auszugeben ist dann trivial.
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Ok vielen Dank dafür. Das mit dem Daten aufbereiten und filtern hatte ich auch so versucht. Nur bin ich ein absoluter Anfänger und bekomme es nicht hin, dass dies läuft. Ich habe keine richtigen Ideen den Code aufzubauen..
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

(Überschneidet sich zeitlich mit anderen Antworten, gilt aber Grundsätzlich trotzdem.)

@python_beginner.98: Programmieren besteht in der Regel daraus, dass man das Problem in kleinere Teilprobleme zerlegt, und die Teilprobleme wieder in kleinere Teilprobleme, solange bis sich die einzelnen Teilprobleme mit Funktionen in wenigen Zeilen Code lösen lassen. Das macht man dann. Man löst ein Teilproblem mit einer kleinen Funktion, testet die, und wie sie tut was sie soll, kann man das nächste Teilproblem lösen. Irgendwann wird man zum lösen von Teilproblemen die schon vorhandenen, getesteten Funktionen verwenden, und am Ende hat man aus den ganzen getesteten Teillösungen die Gesamtlösung zusammengesetzt.

So Standard-Sollbruchstellen beim Aufteilen von Problemen sind Eingabe, Verarbeitung, und Ausgabe zu trennen. Und wenn man etwas für mehrere Dinge gleichartig machen muss, daraus eine Funktion zu machen die das für *ein* “Ding“ tut, und die dann an anderer Stelle auf alle Dinge anwenden. Ein ”Ding” in dem vorliegenden Problem wäre beispielsweise ein Projekt und ein anderes eine Spalte in der Tabelle. Man kann dann beispielsweise eine Funktion schreiben, die eine eingelesene Exceltabelle in einer geeigneten Form bekommt, und dort die Daten für ein Projekt aus einer gegebenen Spalte ausliest. Diese Funktion kann man dann an anderer Stelle für jede Projektspalte aufrufen. Die Funktion kann aus der Spalte beispielsweise ein Tupel aus Projektname und einer Liste mit Tupeln aus Höhe, Breite, und Zeit machen. Also ("Projekt 1", [(1, 5, 4), (3, 7, 7)]) für das erste Projekt aus dem Beispiel. Die gesamte Exceltabelle liesse sich als Liste von solchen Projekt-Tupeln repräsentieren.

Und dann kann man eine Funktion schreiben, die so ein Projekt-Tupel und den gesuchten Zeitpunkt bekommt, und daraus dann die gewünschten Masse heraussucht und als Ergebnis liefert, oder `None` falls es keinen passenden Eintrag gibt. Die Funktion kann man dann auf jedes Projekt-Tupel anwenden.

Statt reinen Tupeln könnten eigene Datentypen mit `collections.namedtuple()` die Lesbarkeit/Verständlichkeit des Quelltextes erhöhen.

Einlesen würde ich entweder mit Pandas, oder mit `openpyxel` machen. Letzteres hat weniger und weniger ”fette” Abhängigkeiten, man muss aber auch ein bisschen mehr selbst programmieren. Ich persönlich würde bei `openpyxel` dann noch `more_itertools` dazu nehmen, weil die Spalten ja immer in 3er-Grüppchen zusammengefasst werden müssen. Das lässt sich auch selbst programmieren, aber ich finde es a) lesbarer da eine bestehende, benannte Funktion für zu verwenden, und b) ist da schon eine Behandlung für den Fall, dass die Anzahl der Elemente nicht durch drei teilbar ist, vorgesehen, die man sonst selbst schreiben müsste, oder als möglichen Fehlerfall nicht berücksichtigt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Vielen Dank für die detaillierten Überlegungen. Allerdings habe ich eher Probleme dabei, dies als Code umzusetzen als mir alles logisch vorzustellen..dabei bräuchte ich Hilfe..

Vielen Dank im Voraus.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@python_beginner.98: Welche Hilfe denn konkret bei welchem Teilproblem und welchem konkreten Code?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Zuerst lese ich die Excel ein:

Dataset= "Testdatei1"
df = pd.read_excel (Dataset + "xlsx")

Nur wie fasse ich die Datei dann in solche Tupel zusammen (dass jede Spalte durchgegangen wird), dass mir dann nach einem zeitlichen Grenzwert die jeweiligen Werte der anderen Faktoren dazu ausgegeben werden? Ich kann dies Code-technisch nicht umsetzen..
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@python_beginner.98: Ganz ehrlich, kann ich mit Pandas auch nicht. Immer wenn ich anfange darüber nachzudenken, fällt mir auf, dass das nicht das ist wofür ich Pandas benutzen würde. Letztlich würde ich da in ”SQL” denken und das erst einmal in die saubere Langform bringen, also die Überschriften wären Werte in einer Spalte, und die drei jeweils zusammengehörenden Zeilen wären eigentlich auch Spalten. Dann kann man nach Projekt gruppieren und pro Gruppe den Index suchen. Ich würde das wahrscheinlich eher „zu Fuss“ mit `openpyxel` einlesen.

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple
from contextlib import closing

import openpyxl
from more_itertools import first_true, grouper
from prettyprinter import cpprint

Item = namedtuple("Item", "height width timestamp")
Project = namedtuple("Projekt", "name items")


def create_project_from_column(column_values):
    column_values = iter(column_values)
    return Project(
        next(column_values),
        [Item(*group) for group in grouper(column_values, 3, "strict")],
    )


def load_projects_from_excel(file_path):
    with closing(openpyxl.open(file_path)) as workbook:
        return list(
            map(
                create_project_from_column,
                workbook.worksheets[0].iter_cols(min_col=2, values_only=True),
            )
        )


def search_item(project, min_timestamp):
    return first_true(
        project.items, None, lambda project: project.timestamp > min_timestamp
    )


def main():
    projects = load_projects_from_excel("test.xlsx")
    cpprint(projects)
    print("-" * 75)
    for project in projects:
        print(project.name, ":", search_item(project, 6))


if __name__ == "__main__":
    main()
Ausgabe für die Beispieldaten:

Code: Alles auswählen

[
    Projekt(
        name='Projekt 1',
        items=[
            Item(height=1, width=5, timestamp=4),
            Item(height=3, width=7, timestamp=7)
        ]
    ),
    Projekt(
        name='Projekt 2',
        items=[
            Item(height=3, width=5, timestamp=3),
            Item(height=6, width=9, timestamp=5)
        ]
    ),
    Projekt(
        name='Projekt 3',
        items=[
            Item(height=5, width=1, timestamp=8),
            Item(height=8, width=6, timestamp=10)
        ]
    )
]
---------------------------------------------------------------------------
Projekt 1 : Item(height=3, width=7, timestamp=7)
Projekt 2 : None
Projekt 3 : Item(height=5, width=1, timestamp=8)
Was hier vielleicht noch dazu kommt ist Code der ”komische” Eingabedateien berücksichtigt. Also beispielsweise das mehr Spalten und/oder Zeilen vorkommen als eigentlich mit den Projektdaten belegt sind, weil da jemand manuell in der Datei rumgewerkelt hat und deshalb leere Zeilen und/oder Spalten existieren, die man raus filtern, oder anderweitig behandeln müsste.

`Item` und `items` könnten bessere Namen gebrauchen. Dazu braucht man aber Domänenwissen, was nur Du hast.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Vielen Dank für die Hilfe bis hier her.
Nur fällt es mir noch schwer, dies auf mein spezifisches Problem anzuwenden, deshalb hier ein Auszug meiner Excel: https://ibb.co/jbNfCLg

Es sind darin in jeder Spalte Daten eines Fahrzeugs aufgelistet. Gelb markiert ist die Zeit. Diese läuft sozusagen pro Fahrzeug (wenn es eben in eine Szene eintritt) fortlaufend nach unten. Grün markiert sind dazu die x- sowie y-Koordinaten zum jeweiligen Zeitstempel.
Das bedeutet also es steht immer der x-Wert, darunter der y-Wert, dann 3 (für aktuell) uninteressante Werte und dann der jeweilige Zeitpunkt. Dies wiederholt sich fortlaufend nach unten einige 1000 mal.

Ziel ist es nun, ab dem ersten erfassten Zeitwert jedes Fahrzeugs (bei Car 1-3 wären das ab 0s, bei Car4 wären das zB 1,768433s usw) 2 Sekunden auf den Startwert zu berechnen und dies für das jeweilige Fahrzeug als Grenzwert festzulegen. Anschließend soll der zu der errechneten Zeit anstehende x- und y-Wert ausgegeben werden.
Das wäre bei den ersten drei Fahrzeugen sozusagen (da ihr Startwert 0s sind): gebe den ersten x/y-Wert, sobald die Zeit zum ersten mal >2s ist
Beim vierten wäre es dann (da Startwert bei 1,768433s): gebe x/y-Wert, sobald die Zeit zum ersten mal >1,768433s + 2s ist

Bitte helft mir noch bei dem Schritt, den bereits oben stehenden Ansatz anzuwenden. Hierbei komme ich einfach nicht weiter.
Vielen Dank im Voraus.!!
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Kann mir bitte jemand helfen den oben von _blackjack_ erstellten Ansatz auf mein spezielles Szenario anzuwenden?
Leider hänge ich dabei...das wäre sehr wichtig.

Vielen Dank im Voraus.
Benutzeravatar
Dennis89
User
Beiträge: 1153
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,
python_beginner.98 hat geschrieben: Donnerstag 22. September 2022, 08:46 Leider hänge ich dabei...das wäre sehr wichtig.
Wobei hängst du genau? Am besten du postest immer deinen aktuellen Code mit Fehlermeldung, falls es eine gibt und beschreibst was du machen wolltest und was stattdessen passiert.


Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

@Dennis89: ich weiß nicht wie ich den oben bereits geschrieben Code in seinen Bestandteilen anpassen muss, um eben mein spezielles Beispiel anzuwenden. Der Code ist oben bereits geschrieben, darunter im Kommentar steht meine genaue Anwendung. Kannst du den Code so anpassen, dass er das geforderte Ergebnis liefert?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@python_beginner.98: nein, können wir nicht, sind ja Deine Hausaufgaben.
Wir helfen gerne bei konkreten Problemen, aber hier ist kein kostenloser Programmierservice, wo man auf Bestellung fertigen Code geliefert bekommt.
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Ok. Muss ich bei "def load_projects_from_excel(file_path):" und in der folgenden Zeile in den Klammern für (file_path) den Pfad einsetzten, in dem sich meine Excel befindet bzw. meine Excel selbst?
karolus
User
Beiträge: 141
Registriert: Samstag 22. August 2009, 22:34

python_beginner.98 hat geschrieben: Donnerstag 22. September 2022, 12:27 Ok. Muss ich bei "def load_projects_from_excel(file_path):" und in der folgenden Zeile in den Klammern für (file_path) den Pfad einsetzten, in dem sich meine Excel befindet bzw. meine Excel selbst?
Nein da nicht, aber ganz offensichtlich da wo du die Funktion aufrufst, in blackJacks Beispiel ist daß in der ``main``funktion.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich denke bei so einer Frage sollte man erst einmal ein Python-Grundlagentutorial durcharbeiten. In der Python-Dokumentation gibt es beispielsweise eines. Programmieren funktioniert nicht durch ratendes verändern von Code den man nicht versteht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
python_beginner.98
User
Beiträge: 22
Registriert: Dienstag 20. September 2022, 12:19

Vielen Dank für eure Hilfe.
Ich habe mir einige Videos angesehen und es auch geschafft den Ansatz auf meinen Anwendungsfall umzuschreiben.

Eine Frage bleibt aber trotz der vielen Videos und Überlegungen.
Oben in der einfachen Darstellung hatte ich gesagt, dass immer die Werte gesucht werden, bei denen der Timestamp größer 6s ist. Dies funktioniert soweit auch super. Genauer müsste die Umsetzung aber so sein, dass nicht immer genau die Werte bei 6s gesucht werden, sondern wenn 6s vergangen sind.
Das bedeutet, es sollte immer von allein der erste Wert der Zeit genommen werden, mit 6 addiert und dann sozusagen nach diesem "neuen" Zeitlichen wert gesucht und die Parameter dafür ausgegeben werden.

Prinzipiell kann ich das ja so umsetzten, dass ich in dem Code einfach den "Grenzwert" von 6 ersetze durch eine Formel. Allerdings habe ich keine Idee wie es funktionieren könnte, dass mir in jeder Spalte der erste zeitliche Wert genommen wird und danach mit 6 addiert wird und anschließend in den Code genommen wird.

Könnte mir dabei jemand Hinweise oder Hilfe geben.
Vielen Dank.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte zeige den jetzigen Code. Damit man das anhand dessen darstellen kann.
Antworten