Seite 1 von 1
Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 09:44
von Samoth
Hallo,
ich habe eine Frage. Im Moment Suche ich mir die Monate mit folgendem Code raus.
Code: Alles auswählen
#Suche Januar
for xx in range(len(dat64)):
if dat64[xx].month == 2:
print(dat64[xx-1], 'index=',xx-1)
feb_view = view[vormon:xx-1]
vormon=xx+1
break
das funktioniert soweit ganz gut, da ich so den ersten Februar finde, Index ausgebe und dann den ganzen Monat extrahiern kann.
Problem, wie mach ich das mit dem Dezember? eine 13 gibt es als monat nicht.
Wie könnte ich einen fehlenden Monat abfangen? Die Rohdaten sind einfach eine Liste aus Datetimes.
Gruß
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 10:20
von Sirius3
Bei Deiner Frage muß man raten, was Du eigentlich hast und was Du eigentlich möchtest. Ich hoffe mal, dass ich richtig rate.
Wenn man Deine vorherigen Fragen anschaut, hast Du ein Pandas-Dataframe, wo man einfach per Indizierung auf einen Monat zugreifen kann:
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 10:21
von __blackjack__
@Samoth: Das sieht insgesamt etwas komisch aus. ``for i in range(len(sequence)):`` ist in Python ein „anti-pattern“ — man kann direkt über die Elemente einer Sequenz iterieren, ohne den Umweg über einen Index. Sollte man den *zusätzlich* benötigen, gibt es die `enumerate()`-Funktion.
Wenn man über zwei Sequenzen (oder generell iterierbare Objekte) ”parallel” iterieren möchte, gibt es die `zip()`-Funktion (und `itertools.izip()` in Python 2.x). Wobei ich es ein „code smell“ ist wenn man eigentlich zusammengehörende Informationen in parallelen Datenstrukturen hält. Also hier: warum gibt es eine Liste mit Datumsobjekten und eine weitere mit den dazugehörigen Daten? Warum sind die nicht in *einer* Liste zusammengefasst?
Musst Du wahlfrei auf die Monate zugreifen oder wird da das gleiche für jeden Monat gemacht? Denn dann würde ich ja als ersten Schritt die Daten in Monate aufteilen. `itertools.groupby()` ist da ein nützliches Werkzeug für.
Der Codeausschnitt ist auch ein bisschen verwirrend. Drüber steht als Kommentar es wird der Januar gesucht, die Ergebnisvariable heisst dann aber `feb_view`‽
Fall `vormon` den Vormonat meint, sollte es `vormonat` heissen.
Ein lineares Zusammensuchen eines Monats könnte so aussehen:
Code: Alles auswählen
month = 1
result = list()
for date, value in zip(dat64, view):
if date.month == month:
result.append(value)
elif date.month > month:
break
Das käme auch damit klar und liefert ein Ergebnis wenn es mal gar kein Datum im gesuchten Monat gibt. Überleg mal was Dein Code in dem Falle machen würde.
Mit einer kleinen Hilfsklasse und dem `bisect()`-Modul könnte man die Suchzeit etwas verbessern, falls das lineare Suchen zu langsam ist. Oder aber wie schon gesagt: man könnte auch einmal alle Monate gruppieren, falls man die am Ende alle braucht.
Falls es sich hier gar nicht um Listen sondern um Spalten aus einem `pandas.DataFrame` handelt, ist alles gesagte hinfällig, denn dann sollte man `pandas` auch tatsächlich nutzen.

Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 10:23
von Samoth
Hab eine Lösung:
Code: Alles auswählen
for xx in range(len(dat64)):
if dat64[xx].month == 2:
gefunden=True
print(dat64[xx-1], 'index=',xx-1)
jan_view = view[0:xx-1]
vormon=xx+1
break
else:
gefunden=False
if gefunden==False:
for xx in range(len(dat64)):
if dat64[xx].month==1:
end=xx
gefunden=True
jan_view=view[0:end]
if gefunden==True:
print(dat64[end], 'index=', end)
if gefunden==False:
print('No Januar-Data availabel.')
jan_view = np.array([0,0,0], dtype=np.float)
jan_view.fill(np.nan)
Das Sollte alles abfangen.
Gruß
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 10:30
von Samoth
__blackjack__ hat geschrieben: Freitag 22. Juni 2018, 10:21
@Samoth: Das sieht insgesamt etwas komisch aus. ``for i in range(len(sequence)):`` ist in Python ein „anti-pattern“ — man kann direkt über die Elemente einer Sequenz iterieren, ohne den Umweg über einen Index. Sollte man den *zusätzlich* benötigen, gibt es die `enumerate()`-Funktion.
Wenn man über zwei Sequenzen (oder generell iterierbare Objekte) ”parallel” iterieren möchte, gibt es die `zip()`-Funktion (und `itertools.izip()` in Python 2.x). Wobei ich es ein „code smell“ ist wenn man eigentlich zusammengehörende Informationen in parallelen Datenstrukturen hält. Also hier: warum gibt es eine Liste mit Datumsobjekten und eine weitere mit den dazugehörigen Daten? Warum sind die nicht in *einer* Liste zusammengefasst?
Musst Du wahlfrei auf die Monate zugreifen oder wird da das gleiche für jeden Monat gemacht? Denn dann würde ich ja als ersten Schritt die Daten in Monate aufteilen. `itertools.groupby()` ist da ein nützliches Werkzeug für.
Der Codeausschnitt ist auch ein bisschen verwirrend. Drüber steht als Kommentar es wird der Januar gesucht, die Ergebnisvariable heisst dann aber `feb_view`‽
Fall `vormon` den Vormonat meint, sollte es `vormonat` heissen.
Ein lineares Zusammensuchen eines Monats könnte so aussehen:
Code: Alles auswählen
month = 1
result = list()
for date, value in zip(dat64, view):
if date.month == month:
result.append(value)
elif date.month > month:
break
Das käme auch damit klar und liefert ein Ergebnis wenn es mal gar kein Datum im gesuchten Monat gibt. Überleg mal was Dein Code in dem Falle machen würde.
Mit einer kleinen Hilfsklasse und dem `bisect()`-Modul könnte man die Suchzeit etwas verbessern, falls das lineare Suchen zu langsam ist. Oder aber wie schon gesagt: man könnte auch einmal alle Monate gruppieren, falls man die am Ende alle braucht.
Falls es sich hier gar nicht um Listen sondern um Spalten aus einem `pandas.DataFrame` handelt, ist alles gesagte hinfällig, denn dann sollte man `pandas` auch tatsächlich nutzen.
Das ist glaube ich eine Pandastabelle. Problem war damals das ich bei dem Groupy-Befehl immer einen Error zurückbekommen habe. Der Fehler bezog sich dabei auf das month (da es laut Compailer) kein month gibt.
Die Liste hat wie vermutet immer ein ganzes Jahr, d.h. ich mache die Linearsuche 12 mal. Da es so viele Lücken gibt war das für mich die einfachste Lösung.
Eingelesen habe ich die Daten wie folgt:
Code: Alles auswählen
for xx in range(len(fns)):):
plt.close()
temp=pandas.read_csv(fns[xx], delimiter=',')
readfile=fns[xx]
index=readfile.find(pattern)
index=index-10 #länge des Namens DAAD_Metar = 10
airp_name=readfile[index:index+4]
print('Plot:', airp_name)
dat64=pandas.to_datetime(temp['Var1'])
timenew=dat64.dt.to_pydatetime()
wind_dir=temp['Daten_1']
wind_spee=temp['Daten_2']
view=temp['Daten_3']
temp_dry=temp['Daten_4']
temp_wet=temp['Daten_5']
pressure=temp['Daten_6']
cover=temp['Daten_7']
cl_base=temp['Daten_8']
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 11:38
von __blackjack__
@Samoth: Welchen Datentyp ein Objekt hat, sollte man nicht glauben, sondern wissen, denn das entscheidet darüber was man mit dem Objekt machen kann, also welche Methoden es anbietet und welche Operationen es unterstützt.
Der Compiler prüft nicht auf Existenz von Attributen. Das kann er gar nicht, denn diese Information existiert in Python erst zur Laufzeit.
Und wenn es dort dann kein `month`-Attribut gibt, dann hast Du irgend etwas falsch gemacht. Beispielsweise es auf dem falschen Objekt versucht abzufragen.
Beim Einlesen ist wieder das „anti pattern“ mit der Indexschleife.
`fns` ist kein guter Name und `temperature` würde ich in den ganzen Namen auch ausschreiben, denn `temp` kann zu leicht als Abkürzung für `temporary` missverstanden werden. Bei dem Namen `temp` könnte ich jetzt beispielsweise nicht sagen für welche der beiden Varianten stehen soll.
Die Spalten hier alle aus dem `DataFrame` holst ist IMHO ein Fehler, denn das führt ja genau zu dem Problem das Du die getrennt betrachtest, am Ende ja aber doch wieder irgendwie zusammenführen musst/willst. Da wäre es einfacher sie gar nicht erst zu trennen. Vernünftige Spaltennamen könnte man denen an der Stelle vielleicht verpassen, statt die Spalten an Namen zu binden.
Was da mit dem Dateinamen gemacht wird, sollte besser kommentiert werden, oder noch besser man geht da mit einem regulären Ausdruck ran, statt mit magischen Indexwerten und -offsets zu hantieren.
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 13:06
von Sirius3
@Samoth: Du solltest dringend ein Tutorial zu Pandas durcharbeiten. Wenn Du Deine Datenstrukturen umgearbeitet hast, sollte so etwas wie mein Einzeiler bei Dir übrig bleiben. Sollte es mehr sein, wendest Du Pandas noch nicht korrekt an.
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 13:12
von Samoth
Danke für dein Feedback,
versuche ich das nächste mal zu berücksichtigen.
Bisher dacht ich immer, dass über:
a[1]...
auf die Inhalte der Tabelle zugegriffen wird.
Zumindest habe ich das so in den Tutoriels gesehen.
Wie würde man z.B. dem Quellcode dann aussehen?
Gruß
Re: Suchen von MOnaten
Verfasst: Freitag 22. Juni 2018, 13:50
von __blackjack__
@Samoth: Auf die Inhalte welcher ”Tabelle”? Was für ein Objekt ist `a` in diesem Fall und was soll ``a[1]`` als Ergebnis haben? Semantisch ist das nämlich ein Riesenunterschied ob man ``a[1]`` auf ein Numpy-Array oder eine Liste, oder auf ein `DataFrame`-Objekt anwendet. Bei Array oder Liste bekommt man das zweite Element, also beispielsweise die Werte der Zweiten Zeile wenn es sich um eine zweidimensionale Datenstruktur handelt. Bei einem `DataFrame` bekommt man dagegen die Spalte mit dem ”Namen” 1 (als `Series`-Objekt). Dabei ist nicht klar die wievielte Spalte das ist, den Namen kann man einer beliebigen Spalte geben:
Code: Alles auswählen
In [19]: df
Out[19]:
a 42 1
0 0.223496 0.332229 0.995868
1 0.278643 0.168088 0.603069
2 0.566801 0.530138 0.655717
3 0.133841 0.478031 0.058088
4 0.882052 0.110485 0.851141
5 0.437174 0.657018 0.944240
6 0.553135 0.018705 0.934758
7 0.601212 0.710126 0.410427
8 0.587195 0.444709 0.920133
9 0.027334 0.661721 0.260089
In [20]: df[1]
Out[20]:
0 0.995868
1 0.603069
2 0.655717
3 0.058088
4 0.851141
5 0.944240
6 0.934758
7 0.410427
8 0.920133
9 0.260089
Name: 1, dtype: float64
In [21]: type(df)
Out[21]: pandas.core.frame.DataFrame
In [22]: type(df[1])
Out[22]: pandas.core.series.Series
In [23]: df.values
Out[23]:
array([[ 0.22349646, 0.33222885, 0.99586826],
[ 0.27864295, 0.16808844, 0.60306853],
[ 0.56680072, 0.53013788, 0.65571666],
[ 0.13384068, 0.47803073, 0.0580883 ],
[ 0.88205197, 0.11048499, 0.85114136],
[ 0.43717405, 0.65701828, 0.94424029],
[ 0.55313457, 0.01870469, 0.9347582 ],
[ 0.60121248, 0.71012602, 0.41042673],
[ 0.58719456, 0.44470946, 0.92013258],
[ 0.02733399, 0.66172108, 0.26008861]])
In [24]: df.values[1]
Out[24]: array([ 0.27864295, 0.16808844, 0.60306853])
In [25]: type(df.values)
Out[25]: numpy.ndarray