mehrdimensionale Arrays durchlaufen

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
sausage
User
Beiträge: 8
Registriert: Donnerstag 22. Mai 2014, 12:53

Hallo zusammen,

Mein Problem:
Dateiname: data
data ist vom Typ list und enthält ein 3D-Array, was ich nicht durchlaufen kann. Durch data_as_array= np.asarray(data) wandle ich in array,was ohne Probleme funktioniert. data_as_array ist vom Typ float64 und hat die Größe (1,1,420). Ich brauche jetzt nur die erste Zeile/Spalte also die 420 Zahlen. Mein Code dazu:

Code: Alles auswählen

a=[]
for i in data_as_array:
    a= data_as_array[][][i]
    print a
gibt Fehlermeldungen. Ich habe viel Verschiedenes ausprobiert, aber ich bekomme es nicht hin. Ich bitte dringend um eure Hilfe!
herzlichen Dank schon mal
Zuletzt geändert von Anonymous am Donnerstag 22. Mai 2014, 14:42, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Was willst du denn genau mit den Elementen des Arrays machen? Im Normalfall möchte man auf Numpy-Arrays nicht per Index zugreifen, dann könnte man auch gleich eine Liste draus machen. Vielleicht gibt es eine bessere Lösung für dein Vorhaben.

Ansonsten solltest du dir mal die Abschnitte zu Indexing und Slicing in der Numpy-Dokumentation anschauen. Dort steht genau drin wie man das macht. Mit raten von Syntax kommst du hier nicht weit. In diesem Fall bietet sich ggf. auch das Flatten des Arrays an.
sausage hat geschrieben:gibt Fehlermeldungen. Ich habe viel Verschiedenes ausprobiert, aber ich bekomme es nicht hin. Ich bitte dringend um eure Hilfe!
herzlichen Dank schon mal
Die Fehlermeldung ist in diesem Fall zwar nicht wichtig, da offensichtlich, aber gewöhne dir bitte an die gesamte Fehlermeldung inklusive Traceback zu posten. Nich nur einen Teil den du für wichtig hältst, deine Interpretation des Fehlers oder einfach nur zu sagen, dass "ein Fehler" aufgetreten sei. Mit einer konkreten Fehlermeldung können wir etwas anfangen, sonst kann man nur raten.

Ansonsten noch der Hinweis, dass das Forum Code-Tags hat um den Code vom Text hervorzuheben. Dann kann man ihn richtig lesen und, was noch viel wichtiger ist, die Einrückung bleibt erhalten.
Das Leben ist wie ein Tennisball.
BlackJack

@sausage: Um die Elemente einzeln auszugeben brauchst Du die Liste gar nicht erst in ein Numpy-Array wandeln.

Und wenn das am Anfang als verschachtelte Liste vorliegt die dann ein ”dreidimensionales”-Array ergibt wo die erste und zweite Dimension jeweils nur ein Element enthält, dann ist das ja nicht wirklich dreidimensional und es stellt sich die Frage wo Daten in einem so komischen Format überhaupt herkommen. Das sieht zumindest fragwürdig aus.
sausage
User
Beiträge: 8
Registriert: Donnerstag 22. Mai 2014, 12:53

Vielen Dank für eure Antworten! @EyDu, ich fühle mich auch willkommen :)
@BlackJack, ich kann aber sonst die liste nicht durchlaufen, da sie Größe 1 hat und ein array mit Größe 420 enthält.

Ich würde mein Problem jetzt etwas detaillierter erzählen:

data ist eine Liste bestehend aus 10 Elementen. Diese Elemente sind als dictionaries angelegt. Jede Dictionary enthält 4 keys. Drei von diesen keys haben als Value eine Liste, die ein array mit 420 (positiven und negativen) Zahlen enthält. Der letzte key hat als Value eine Liste, die ein array mit Größe 1 ein string enthält.

Ich brauche im ersten Schritt, die 420 Zahlen einzeln zu speichern und später die arrays in positive und negative Zahlen zu zerlegen. Mein Code hierzu:

Code: Alles auswählen

temp=[]
values=[]

#aus 20 dicts das erste dict rausnehmen
first_dict=data[0]

for value in first_dict.itervalues():
    temp=[value]
    values.append(temp)
    print values
 
#2.SCHRITT: aus values die einzelnen Elemente zuweisen
elem1 = values[0:1]
elem2 = values[1:2]
elem3 = values[2:3]
elem4 = values[3:4]


#3.SCHRITT aus 4 Elementen als type list wird in type array umgewandelt.

array_elem1= np.asarray(elem1)
array_elem1_positiv=[]

#PROBLEMSTELLE :positiven Werte rauspicken
for i in elem1 :
    if i > 0:
        array_positiv= elem1([0][0][i])
        print array_positiv
Fehlermeldung:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 540, in runfile
execfile(filename, namespace)
File "C:/Python27/Scripts/DA/untitled3.py", line 57, in <module>
array_positiv= elem1([0][0])
TypeError: 'int' object has no attribute '__getitem__'

Was ich überhaupt nicht verstehe ist, dass wenn ich bei der Python Console z.B. elem1[0][0][21] angebe, kriege ich den zugehörigen Wert raus. Aber in der obigen for-Schleife geht es nicht.

Ich bin euch sehr dankbar für jede Hilfestellung!

PS: wie 'data' aussieht, habe ich versucht im angehängten Bild zu illustrieren.
Bild
BlackJack

@sausage: Dein erster an mich gerichteter Satz klingt wie eine Begründung, ich weiss nur nicht für *was* eigentlich‽

Die Grafik zu `data` ist etwas inkonsistent. Oben steht das es sich um eine Liste handelt, in der ersten Ebene steht dann aber „Dictionary” als Typ‽ Und dann passt es nicht zum Text wo steht das drei der Werte jeweils eine Liste mit einem Array mit 420 Zahlen sind. Das sehe ich in der Zeichnung nicht? Das wäre auch wie schon gesagt eine unsinnige Datenstruktur. Man will keine Listen haben die grundsätzlich nur ein Element enthalten. In Zeile 7-10 scheinst Du da dann *noch* eine weitere Liste da drum herum zu basteln. Kommt da etwa die dreidimensionale Struktur her? Weil Du statt eine unnötige Verschachteltung zu *entfernen* das *noch mal* unnötig ”verpackst”?

Im Code steht im Kommentar das es 20 Wörterbücher sind, wo im Text und in der Zeichnung steht es wären 10‽

Schritt 2 ist unnötig umständlich denn ein Slice der Länge 1 hätte man auch einfach mit einem normalen Indexzugriff ausdrücken können. Durchnummerieren von Namen ist aber eine schlechte Idee, denn dann will man in der Regel eigentlich eine Datenstruktur dafür verwenden, zum Beispiel eine Liste. Und hey, die hast Du ja schon. Also warum das an der Stelle auf vier Namen verteilen?

Namen sollte man erst binden wenn man sie auch tatsächlich braucht. Nicht am Anfang ”deklarieren”. Das macht das Programm unübersichtlicher weil Teile die eigentlich zusammengehören so über das gesamte Programm verteilt werden. `temp` sollte gar nicht ”initialsiert” werden, denn der ganz am Anfang zugewiesene Wert wird nirgends verwendet. Und die Verwendung des Namens ist auch fragwürdig — man muss nicht jedes Zwischenergebnis an einen Namen binden. Zumal das hier auch gar keinen Sinn ergibt, denn das scheint ja eine der Listen zu sein, die überflüssig sind.

Ich sehe hier auch das Problem das man gar nicht weiss welcher Wert an welchen Namen gebunden wird, weil Wörterbücher keine Ordnung haben. `itervalues()` liefert die Werte in *irgendeiner* Reihenfolge. Und da zumindest einer anders aussieht als die anderen, kann es passieren das an `elem1` am Ende gar nicht die 420 Werte gebunden werden, sondern der Wert von dem Schlüssel vom Typ Zeichenkette. An der Stelle ist das Programm also fehlerhaft.

Die Werte in ein Numpy-Array umzuwandeln macht nur Sinn wenn man dann auch die Operationen eines solchen Arrays verwendet. Wenn Du da einfach eine ``for``-Schleife in Python drüberlaufen lässt, dann hättest Du es auch als Liste belassen können, beziehungsweise wenn das in `data` in dem Wörterbuch ein Arraytyp ist, dann nimm *das* Array und verpack das nicht in zwei Listen um *das* dann in ein ”3D-Array” umzuwandeln. Ich versuche dafür gerade etwas milderes als „hochgradig schwachsinnig” zu finden — klappt irgendwie nicht. ;-)

Zur Ausnahme: Die sollte bei genauem hinsehen eigentlich klar sein. Du versuchst da `elem1` aufzurufen — was nicht geht, weil man Listen nicht aufrufen kann, aber soweit kommt es erst gar nicht — und der Ausdruck für das Argument beim Aufruf lautet ``[0][0]``. Dabei ist völlig egal was `i` hier für einen Wert hat:

Code: Alles auswählen

In [3]: i = 'irgendwas'

In [4]: [0][0][i]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-409e2b88323c> in <module>()
----> 1 [0][0][i]

TypeError: 'int' object has no attribute '__getitem__'
Schauen wir uns mal an was die einzelnen Teilausdrücke bedeuten:

Code: Alles auswählen

In [5]: [0]
Out[5]: [0]

In [6]: [0][0]
Out[6]: 0

In [7]: 0[i]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-a8e76ecf3d12> in <module>()
----> 1 0[i]

TypeError: 'int' object has no attribute '__getitem__'
[5]: Eine Liste mit einer 0 als einzigem Element.
[6]: Aus der Liste wird das Element an Index 0 geholt, also eine 0.
[7]: Der Versuch einen Indexzugriff auf einer ganzen Zahl durchzuführen. Das geht nicht.

Als allererstes solltest Du klären warum die Werte in `data` in einer unnötigen Liste stecken — wenn ich mir die Zeilen 7—10 anschaue könntest Du das selber gemacht haben — und das dann wenn möglich *abstellen*. Auf jeden Fall solltest Du das das unsinnige zweite verpacken durch ein ”auspacken” ersetzen.

Und dann müsstest Du mal klären welchen Wert Du eigentlich an `elem1` binden möchtest, denn momentan ist das ein zufälliger von den vier Werten.
BlackJack

@sausage: Noch ein Nachtrag zum Format von `data`: Es ist keine gute Idee in einem Wörterbuch Schlüssel mit verschiedenen Bedeutungen oder gar Typen auf einer Ebene zu haben. Das macht den verarbeitenden Code komplizierter weil man dort dann irgendwann anfangen muss aufgrund des Typs Entscheidungen zu treffen die man nicht machen müsste, wenn die Schlüssel alle vom gleichen (Duck-)Typ sind. Und man kann die Datenstruktur nicht mehr so einfach um zusätzliche Informationen erweitern weil man a) immer aufpassen muss das der Typ oder Wert sich mindestens soweit von den bereits vorhandenen unterscheidet, dass man ihn im Programmcode rausfiltern kann, und b) muss man dann das gesamte Programm durchgehen und die neue Information im Code berücksichtigen obwohl der die wahrscheinlich überhaupt nicht benötigt.

Wenn man anfängt Listen und Wörterbücher über mehrere Ebenen zu verschachteln, sollte man dringend über eigene Datentypen nachdenken, sonst wird das irgendwann zu unübersichtlich.

Edit: Statt einfach alles auf Modulebene runterzuschreiben, würde man das auch besser in Funktionen stecken. Die lassen sich einfacher isoliert testen, wiederverwenden, diskutieren, und machen ein Programm übersichtlicher und verständlicher weil das Problem auf Teilprobleme heruntergebrochen wird, für die es dann sinnvoll benannte Teillösungen gibt.
sausage
User
Beiträge: 8
Registriert: Donnerstag 22. Mai 2014, 12:53

@BlackJack: herzlichen Dank! ich glaube, dass ich dich mit den Datentypen etwas verwirrt habe. Das bin ich auch und deswegen suche ich nach einer Hilfe. Ich versuche es mal so zu erklären:

Vorher was Wichtiges: die Wörterbücher, oder genauer gesagt, die gesamte Datei ist fest, das darf ich nicht ändern. Und zu den Datentypen:
ich benutze Spyder als Entwicklungsumgebung und versuchte euch den Verlauf der Datei zu beschreiben.

Aber hier ein konkretes ausgedachtes Beispiel: s. das angehängte Foto
Bild
Die 10 Jahre sind jeweils als ein Element der Liste gespeichert, jedes Element ist ein Dictionary, welches 'Brot', 'Nutella','Butter' und 'Wert' enthält.

Was ich bis jetzt versucht habe, die verschiedenen Dateitypen so umzuwandeln, dass ich die entsprechenden Funktionen benutzen kann.

Meine Frage ist: Wie kann ich die täglichen Preise rauspicken und speichern?

PS: Mit folgendem Code kann ich alle Dateien plotten:

Code: Alles auswählen

for i in data:
    if i['Wert']== 'teuer'
        plt.plot(i['Brot'],i['Nutella'], color ='m')
    elif ... #usw.
BlackJack

@sausage: Mir ist immer noch nicht klar wie die Datenstruktur aussieht, denn wenn die Werte im Wörtebuch tatsächlich ein Array in einer Liste sind, dann dürfte der Plot nichts zeigen, zumindest nicht solange man keine Marker aktiviert, denn das sind aus Sicht von Matplotlib ganz viele einzelne Datenpunkte und damit gibt es keine Linien die irgendwas verbinden.

Falls es Arrays sind, macht der Plot keinen Sinn weil man die Preise von Brot gegen die von Nutella plottet was eine lustige Zickzacklinie ergibt.

Stimmt das ausgedachte Beispiel mit den tatsächlichen Daten überein? Hast Du den Code tatsächlich ausprobiert, oder ist das jetzt nur so hingeschrieben wie es vielleicht sein könnte? Das macht alles wenig Sinn — kläre doch erst einmal wie die Datenstruktur *tatsächlich* aussieht und welche Datentypen da jeweils *tatsächlich* vorliegen. Programmiern durch herumraten funktioniert nicht wirklich.

Wie man aus der zuletzt gezeigten Datenstruktur die Preise rauspicken kann hast Du doch eigentlich schon selbst im Plot-Beispiel gezeigt. Man holt sich das entsprechende Jahr aus der Liste (wobei die Indexierung bei 0 beginnt), und hat dann ein Wörterbuch. Da kann man dann mit 'Brot' zum Beispiel auf das Array mit den Brotpreisen zugreifen. Also beispielsweise die Brotpreise im ersten Jahr: ``data[0]['Brot']``. Das ist aber so trivial, dass man solche Fragen eigentlich nicht stellen sollen müsste. Falls doch, sollte man erst einmal die Grundlagen von Python lernen, bevor man konkrete Probleme angeht.

Bei `i` als Laufvariable in Schleifen erwartet übrigens so ziemlich jeder Programmierer dass es sich um ganze Zahlen handelt und nicht um irgendwelche komplexeren Objekte.
Antworten