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: 11
Registriert: Donnerstag 19. September 2019, 10:15

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: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

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: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

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: 11
Registriert: Donnerstag 19. September 2019, 10:15

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: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DonKingKong: In der Python-Dokumentation gibt es beispielsweise ein Tutorial.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

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: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

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()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

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

Puh, dass ist wieder ziemlich viel Stoff, danke dafür. Ich weiß nur nicht ob ich das alles verstanden hab.

Also ich habe jetzt schon 2 von 3 Python aufgaben während dem Praktikum lösen können, aber auf die dynamische Tabelle komm ich nicht ganz klar und bin auf mich alleine gestellt.

Das mit dem kommentieren werden ich verbessern :)
Ich hab so wenig Plan vom Programmieren, dass ich gar nicht weiß, wann es nicht mehr nach einem Python Code aussieht.
Aber ich gehe auf den Ratschlag ein und lese mich mal in Numpy ein... pandas kann ich schon ein bisschen ;)

Ich hab keinen Einfluss drauf, dass die Dateien in .txt, .csv oder .tab vorliegen.
Die Zeitachse bleibt immer identisch.

Ich weiß wie ich die einzelnen Variablen bilde die ich für die Berechnung brauch.
Ich bin aber mit der Abfrage überfordert: Ist ein Signal da, dann schreib mir bitte das Singal in die Richtige "Zelle" zur Uhrzeit und Station.
Ich hab das hier "data[time][station] = signal" gelesen, k.A. ob ich das so einsetzten kann.
Und wenn ich das ganze geschafft, hab soll das ganze irgendwie noch gut aussehen, wie eine richtige Tabelle.

Irgendwie komm ich auf die Schleifen nicht so richtig klar. Hab im Internet einige Tutorials abgeschlossen, aber so richtig erschließt sich mir das ganze noch nicht so richtig.

Ich hab jetzt noch 3 Wochen, ich hoffe danach kann ich eine Lösung präsentieren :)

Beste Grüße
Don King Kong
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

Sirius3 hat geschrieben: Dienstag 15. Oktober 2019, 12:30

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']
Also der Code von Sirius3 funktioniert ganz gut und sieht auch schon ziemlich danach aus, was ich seit paar Tagen versuche.
Wie bekomme ich jetzt den array unique_stations in die oberste Zeile und timeaxes in die 1 vertikale spalte

x = np.hstack(unique_stations)
y = np.vstack(timeaxes)

hab das gefunden, aber ich weiß nicht wie ich es übergeben soll.
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

itemset wäre auch eine möglichkeit, dann müsste ich nur eine spalte und zeile hinzufügen
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum solltest Du soetwas wollen? Die Achsenbeschriftung getrennt zu halten, ist viel besser. Oder Du steigst gleich auf pandas um.
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

Okay Okay, aber wie bekomme ich den eine Achsenbeschriftung hin?
mir fehlt nur noch die Beschriftung, dann hab ich es :cry:

also ich probiere es gerade mit np.append, np.concatenate, v+hstack... bekomme blöde Fehlermeldung.

TypeError: only integer scalar arrays can be converted to a scalar index
ValueError: all the input array dimensions except for the concatenation axis must match exactly


mit pandas hab ich letzte Woche für eine Tabellenkalkulation. ist es den auch da möglich die Tabellenzellen automatisch zu füllen? ich dachte damit gehen eher nur Rechenoperationen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@DonKingKong: was willst Du denn mit der Matrix machen?
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

okay, ich probier es jetzt mit Pandas ;)
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

Sirius3 hat geschrieben: Donnerstag 24. Oktober 2019, 14:29 @DonKingKong: was willst Du denn mit der Matrix machen?
Ich mach gerade ein Praktikum im MPI, bin Naturwissenschaftler und habe 3 Python aufgaben bekommen.
Die Matrix dient bzw die aktuelle Aufgabe dient einzig und allein einer besseren Übersicht. Mein Betreuer bekommt jeden Tag eine Txtfile in der für ihn Interessante Daten drin sind, aber alles recht unübersichtlich.

Er will eine "aufgehübschte" Tabelle, er will das ich das unbedingt mit python mache, aber er selbst kann kein python... die einzige Person die mir hier helfen könnte, hat ein Arsch voll Arbeit und bin damit auf mich alleine gestellt :\

ps: mit pandas sieht es aufjedenfall gleich besser aus.
Jetzt versuche ich die Spaltennamen aus dem array zu laden
Die Zeit hab ich schon drin, jetzt Fehlen noch die Stationsnamen als Spaltennamen
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Im Grunde sieht das so aus als müsste man „Tidy Data“ rückwärts machen. :-)

https://www.jstatsoft.org/index.php/jss ... v59i10.pdf
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DonKingKong
User
Beiträge: 11
Registriert: Donnerstag 19. September 2019, 10:15

ahh ich habs, ich rast aus.... so mal schauen ob es jetzt noch in der praxis mit anderen datein funzt


AHHH so happy.

Wenn das script fertig ist, poste ich es natürlich
Antworten