Suchen von MOnaten

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
Samoth
User
Beiträge: 41
Registriert: Freitag 24. November 2017, 15:13

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ß
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

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:

Code: Alles auswählen

jan_view = view[view['date'].dt.month == 1]
Zuletzt geändert von Sirius3 am Freitag 22. Juni 2018, 10:22, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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. :-)
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Samoth
User
Beiträge: 41
Registriert: Freitag 24. November 2017, 15:13

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ß
Samoth
User
Beiträge: 41
Registriert: Freitag 24. November 2017, 15:13

__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']
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@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.
Samoth
User
Beiträge: 41
Registriert: Freitag 24. November 2017, 15:13

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ß
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten