Erstellen einer Dynamischen Tabelle

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
DonKingKong
User
Beiträge: 4
Registriert: Donnerstag 19. September 2019, 10:15

Donnerstag 19. September 2019, 13:51

Hallo liebe Leute,

ich bin ein Anfänger und hab gleich an meinem ersten Praktikumstag eine Brecher aufgabe bekommen, ich selbst hab keine Informatik studiert oder eine ähnliche Ausbildung genossen.

Ich hab eine Textfile bekommen und mit grep, cut und der sed Funktion die Daten aufs wesentliche reduziert.
Zeit Station Signal
0550 E789 0.000
0550 E870 0.000
0650 E471 0.000
0650 E776 0.000
0650 E789 0.000
0650 E870 0.000
0750 E362 0.000
0750 E453 0.000
0750 E471 0.000
0750 E630 0.000
0750 E641 0.000
0750 E776 0.000
0750 E779 0.000
0750 E789 0.000
0750 E833 0.000
0750 E865 0.000
0850 E453 0.000
0850 E471 0.000
0850 E630 0.000
0850 E641 0.000
0850 E776 0.000
0850 E779 0.000
0850 E789 0.000
Die Tabelle soll wie folgt aussehen
Uhrzeit/Stationen |E362|E453|E471|E480|E605|E630|E641|656|E683|E776|E779|E778|E789|E833|E865|E870
0050 - - - - - - - - - - - - - - - -
0150 - - - - - - - - - - - - - - - -
0250 - - - - - - - - - - - - - - - -
0350 - - - - - - - - - - - - - - - -
0450 - - - - - - - - - - - - - - - -
0550 - - - - - - - - - - - - 0,0 - - 0,0
0650 - - 0,0 - - - - - - - 0,0 - 0,0 - - 0,0
. ...
2350 - - - - - - - - - - - - - - - -
Links auf der Y-Achse steht die Zeit, die bleibt auch fix.
Auf der X-Achse(oben) kommen die Stationnamen, die Anzahl der Stationen variiert nach empfangenen Signal, daher wer es schön wenn die Achsenlänge Dynamisch bleibt. Mit einem Unique und Sort Befehl entferne ich alle Duplikate und sortiere die Stationen aufsteigend.
In die Spalten sollen dann, wenn die Bedingungen stimmen, also wenn die Uhrzeit und Station angeben ist, soll das Signal in die entsprechende Spalte. Wenn einer der Bedingungen nicht erfüllt ist soll ein "-" rein.
Ich hab mich jetzt in Panda und for schleifen reingelesen, weiß aber nicht so recht wie ich anfangen soll.

Vllt hat ja jemand ein Tipp für mich oder kann mir eine bestimmte Herangehensweise empfehlen

Beste Grüße
Don King Kong
Benutzeravatar
__blackjack__
User
Beiträge: 4228
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 19. September 2019, 14:16

@DonKingKong: Python-Grundlagen lernen — das muss man so oder so, auch wenn man das mit Pandas löst/lösen möchte. Das kann man aber auch ohne Pandas lösen.

Man muss sich halt mit den Kontrollstrukturen, Grunddatentypen, und ein bisschen mit Modulen aus der Standardbibliothek auseinandersetzen.

Muss das formatieren der Ausgabe so sein? Kann man nicht auch einfach als CSV- oder TSV-Datei speichern? Und warum sind die Werte in der Kopfzeile durch | getrennt während bei den Daten dann (deutlich mehr) Leerzeichen verwendet werden?

Falls Du das dann am Ende doch mit Hilfe der Pandas-Bibliothek machst: Da währen dann Schleifen in Python sehr wahrscheinlich falsch, beziehungsweise man müsste dann gut begründen können warum man da für eine (Teilaufgabe) eine Schleife benötigt.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
DonKingKong
User
Beiträge: 4
Registriert: Donnerstag 19. September 2019, 10:15

Donnerstag 19. September 2019, 14:26

Hi Blackjack, nein mit Panda muss ich es nicht unbedingt lösen, hab halt bisschen was gelesen und bin immer wieder drauf gestossen.

Ja irgendwie Kontrollstruktueren also z.B. Booleans arbeiten hab ich mir auch gedacht. Welche Module aus der Standbibliothek meinst du im speziellen?

Ich hab die Werte mit | getrennt um Spalten anzudeuten .... die müssen aber nicht mit rein.
Ich glaub formatiert muss sie nicht sein, wäre aber der übersicht wegen etwas schöner.

okok kein Panda irgendwie zwei oder eine verschachtele for schleife tut es wahrscheinlich auch

kannst du mir vllt eine Seite empfehlen mit der ich for Schleifen gut lernen kann?
__deets__
User
Beiträge: 6401
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 19. September 2019, 14:41

Ein Ansatz:

Code: Alles auswählen

import io
import csv
import itertools
from collections import defaultdict
import pprint

DATA="""Zeit Station Signal
0550 E789 0.000
0550 E870 0.000
0650 E471 0.000
0650 E776 0.000
0650 E789 0.000
0650 E870 0.000
0750 E362 0.000
0750 E453 0.000
0750 E471 0.000
0750 E630 0.000
0750 E641 0.000
0750 E776 0.000
0750 E779 0.000
0750 E789 0.000
0750 E833 0.000
0750 E865 0.000
0850 E453 0.000
0850 E471 0.000
0850 E630 0.000
0850 E641 0.000
0850 E776 0.000
0850 E779 0.000
0850 E789 0.000
"""

def main():
    # stattdessen natuerlich Datei oeffnen
    inf = io.StringIO(DATA)
    reader = csv.reader(inf, delimiter=" ")
    # erste Zeile skippen
    data = defaultdict(dict)
    stations = set()
    for time, station, signal in itertools.islice(reader, 1, None):
        data[time][station] = signal
        stations.add(station)

    stations = sorted(stations)
    print("|".join(["Uhrzeit/Stationen"] + stations))
    for time in sorted(data.keys()):
        print(time, end='')
        for station in stations:
            print(data[time].get(station, "-"), end="")
        print()


if __name__ == '__main__':
    main()
DonKingKong
User
Beiträge: 4
Registriert: Donnerstag 19. September 2019, 10:15

Donnerstag 19. September 2019, 14:47

ok cool, sehr cool, vielen dank deets. ich werd mal den code "auseinander nehmen" und ihn mir genauer anschauen. vielen dank dafür!!!1
Benutzeravatar
__blackjack__
User
Beiträge: 4228
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 19. September 2019, 15:30

@DonKingKong: In der Python-Dokumentation gibt es beispielsweise ein Tutorial.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
DonKingKong
User
Beiträge: 4
Registriert: Donnerstag 19. September 2019, 10:15

Dienstag 15. Oktober 2019, 10:31

So, ich hab mal weiter gearbeitet. Bin noch nicht ganz fertig, weil mein pc zwischenzeitlich nicht ging und ich eine andere aufgabe reingedrückt bekommen hab.

@Blackjack nochmal vielen dank für dein Ansatz. Der war mir aber ein bisschen zu kompliziert und islice ist schon ziemlich fancy.
Ich versuch mir in erster annährung das Progamieren wir ein solides Handwerk bei zu bringen

Ich wollte euch meine Lösung nicht vor enthalten und hier ist mein code :)
#!/usr/bin/python3
# -*- coding: UTF-8 -*-

import csv
import io
import numpy as np

data = np.loadtxt("data.txt", dtype=str) #einlesen der txt ueber np, beschreibung des datentyps str
time = data[:,0].astype(int) #generieren der variable time aus der file data [;,0] alles(:) aus der Spalte 0. Beschreibung des Datentyps als int
station = data[:,1] #generieren der variable station aus der file data [;,1] alles(:) aus der Spalte 1
signal =data[:,2].astype(float) #generieren der variable signal aus der file data [;,2] alles(:) aus der Spalte 2. Beschreibung des Datentyps als Float, weil es eine Kommazahl 0.00 ist

ustation = np.unique(station) #unique station, dass entfernen von Duplikaten aus der variable station ueber das np modul
tabelle = np.zeros((24,len(ustation))) # erstellt ein array/matrix aus nullen(weil np.ZERO)((aus 24 Zeilen und der laenge aus Anzahl der ustation
tabelle[:,:]=np.nan # nan = not a number, fuellt die Tabelle mit nan um die Tabelle leichter zu bearbeiten
timeaxes = np.arange(50, 2450, 100) #generieren der Zeitachse np.arange(Startwert, Endwert (immer 1 mehr angeben), Schritte)(1350 + 100 = 1450)

for i in range(len(ustation)): #erste schleife, lauf index i in range und anzahl der laenge in ustation
print(i)
sindex = np.where(station == ustation) #station index = wo ist die station == dem element aus ustation
print(ustation)
print(sindex)
print(station[sindex])
print(time[sindex])
stime = time[sindex] #station time = time[sindex] verknuepfung aus time mit station index. Es werden nur die elemente ausgegeben die time und sindex korrelieren
for t in range(len(sindex[0])): #schleife in schleife. laufindex t in range und anzahl der laenge in station index [0]?
tindex = np.where(timeaxes == stime[t]) #time index entspricht der uebereinstimmung aus timeaxes und station time
print(tindex)


Ich hoffe mein rechner klappt später wieder
jetzt bin ich dran, dass wenn ein signal vorhanden es, dieser wert in die richtige spalte in t- und sindex eingetragen wird
Benutzeravatar
__blackjack__
User
Beiträge: 4228
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Dienstag 15. Oktober 2019, 11:11

@DonKingKong: Der Ansatz war von __deets__, nicht von mir. :-)

Das was Du da machst sieht nicht nach Python aus. ``for i in range(len(sequence)):`` ist in Python ein „anti pattern“, das ist in 99,9% die falsche herangehensweise. Dazu kommt dann noch das Du mit Numpy-Arrays arbeitest, wo ``for``-Schleifen an sich schon ein Warnzeichen sind, das man etwas komisches macht, denn Numpy-Arrays verwendet man ja gerade um ``for``-Schleifen zu vermeiden und stattdessen die effizienten internen Schleifen der Numpy-Objekte/-Funktionen zu verwenden.

Wenn man mit einem mit `NaN` gefüllten 2D-Array anfangen will, wäre es konzeptionell einfacher je ein Wörterbuch zu haben das Zeiten und Stationen auf Zeilen und Spaltenindex abbildet, und dann in *einer* Schleife über die Eingabedaten zu gehen und die Indizes zu Zeit und Station zu ermitteln und dann an der Stelle im Array einzutragen.

Du kommentierst IMHO zu exzessiv und an der falschen Stelle für so lange Kommentare. Zeilen sollten nicht zu lang werden. Der Style-Guide ist mittlerweile gelockert worden und lässt auch 120 Zeichen pro Zeile noch durchgehen, aber traditionell ist die Grenze bei 80 bzw. 79 Zeichen. Viele Kommentare können auch ein Hinweis darauf sein, das man schlechte Namen gewählt hat, weil der Code dadurch selbst nicht aussagekräftig genug ist. Und/oder das der Code zu kompliziert ist. Komplexität lässt sich manchmal nicht vermeiden, dann braucht man Kommentare die erklären warum der Code das macht was er macht, aber man kann immer mal schauen ob es sich der Code nicht einfacher/verständlicher ausdrücken lässt.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Benutzeravatar
__blackjack__
User
Beiträge: 4228
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Dienstag 15. Oktober 2019, 11:26

Die letzte Idee mal als Code (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import csv
from math import nan


def map_value_to_index(values):
    return {value: index for index, value in enumerate(values)}


def main():
    with open("test.csv", encoding="ascii") as csv_file:
        rows = [
            (int(time), station, float(value))
            for time, station, value in csv.reader(csv_file, delimiter=" ")
        ]

    times = range(50, 2450, 100)
    stations = sorted(set(station for _, station, _ in rows))
    table = [[nan] * len(stations) for _ in range(len(times))]

    time_to_index = map_value_to_index(times)
    station_to_index = map_value_to_index(stations)
    for time, station, value in rows:
        table[time_to_index[time]][station_to_index[station]] = value


if __name__ == "__main__":
    main()
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Sirius3
User
Beiträge: 10585
Registriert: Sonntag 21. Oktober 2012, 17:20

Dienstag 15. Oktober 2019, 12:30

@DonKingKong: csv und io werden importiert, aber nicht benutzt.
Statt alles als Text einzulesen und danach zu konvertieren, solltest Du gleich das richtige Format angeben.

`unique` hat noch viele nützliche Parameter, wie z.B. return_inverse. Das `u` bei `ustation` ist eine kryptische Abkürzung, die man am besten ausschreibt, und `tabelle` ist so ein allgemeiner Name, dass er gar nichts aussagt.

Woher kommen die magischen Werte 24, 50, 2450 oder 100? Ist denn garantiert, dass die Zeiten in diesem 50er-Raster liegen? Sonst wäre was mit Minimumsbildung sicherer.

Das ganze dann ohne explizite Schleifen:

Code: Alles auswählen

import numpy as np
data = np.loadtxt("data.txt", dtype=[('time', int), ('station', 'S99'), ('signal', float)])

unique_stations, station_indices = numpy.unique(data['station'], return_inverse=True)

timeaxes = np.arange(50, 2450, 100)
time_indices = numpy.argmin(abs(timeaxes[:, None] - data['time']), axis=0)

tabelle = np.ndarray((len(timeaxes), len(ustation)))
tabelle[...] = np.nan
tabelle[time_indices, station_indices] = data['signal']
Antworten