ndarray auf einzelne Werte zu greifen

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
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ich habe ein numpy.array, welches eine beliebige Tiefe haben kann und ich möchte einzelne Wert(integer) auslesen und einem anderen gleich großen Array zuornden. Bisher habe ich immer per

Code: Alles auswählen

ndarray[a][b][c] = data[a][b][c]
die Zuordnung gemacht, da ich die Wert a, b und c* gestellt bekomme. Das Problem ist nun, das die Arrays zwar immer die gleich Größe haben, aber halt auch 2d- oder 4d-Arrays sein können.
Nur blicke ich gerade nicht, wie ich am besten die Indizes dynamisch auslesen kann. Hätte hierzu jemand einen Tipp?

* Die Werte entsprechen keinem Muster und entspringen einem Tuple, dessen Länge gleich der Dimensionsgröße des ndarrays ist.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Entweder verstehe ich nicht, auf was du hinaus möchtest oder suchst du tatsächlich nur folgendes?

Code: Alles auswählen

t = a, b, c
ndarray[t] = data[t]
Sebastian
Das Leben ist wie ein Tennisball.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Man kann schon echt beschränkt sein. :oops:

Danke, gibt es sowas in der Art eigentlich auch für normale Listen ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Aber freilich!

[EDIT] Geh, a so a Schmarrn...
Zuletzt geändert von pillmuncher am Mittwoch 4. Mai 2011, 22:38, insgesamt 1-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Schade :cry:
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Xynon1 hat geschrieben:Schade :cry:
"Freilich" bedeutet "Natürlich", "Na klar"...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Leonidas hat geschrieben: "Freilich" bedeutet "Natürlich", "Na klar"...
Wobei man das auch als Nicht-Bayer verstehen sollte! Ich fand den Kommentar ja "pfundig" :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ich hatte das eigentlich als Ironie aufgefasst. Das die Syntax nicht bei Listen existiert ist mir schon klar, die geänderte Slice-Syntax von dem numpy.ndarray ist schließlich in C implementiert, oder ?
Wie setzt man sowas sonst um?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Nachdem ich bei meiner ersten Anwort weder genau gelesen, noch genau nachgedacht habe - in Python würde ich das in etwa so machen:

Code: Alles auswählen

class Lizzy(list):
    def __getitem__(self, index):
        if type(index) == tuple:
            tmp = self
            for each in index:
                tmp = list.__getitem__(tmp, each)
            return tmp
        else:
            return list.__getitem__(self, index)
     # etc.

li = Lizzy([['a', 'b', 'c'], ['d', 'e', 'f']])

print li[1]
print li[1,1]
Ergebnis:

Code: Alles auswählen

['d', 'e', 'f']
e
Lizzy.__setitem__ muss man dann analog dazu bauen.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Stimmt so gehts natürlich.

Sollte man aber aus "if type(index) == tuple:" nicht noch "if isinstance(index, tuple):" machen?
bzw.es könnte eigentlich jede Sequenz sein.
Zuletzt geändert von Xynon1 am Donnerstag 5. Mai 2011, 08:41, insgesamt 1-mal geändert.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Du hast recht. Vielleicht sollte man sogar "if isinstance(index, (list, tuple)):" schreiben.
In specifications, Murphy's Law supersedes Ohm's.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ist mir auch gerade aufgefallen, eigentlich könnte es jede Sequenz sein. Gibt es dafür in Python ein "Erkennungsmerkmal" ?
Ansonsten sollte man vieleicht sogar besser auf Integer prüfen, da dieser ja wirklich als Index benötigt wird.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

So, das noch:

Code: Alles auswählen

    def __setitem__(self, index, item):
        if isinstance(index, (list, tuple)):
            list.__setitem__(self[index[:-1]], index[-1], item)
        else:
            list.__setitem__(self, index, item)
Erkennungsmerkmal: Bei neueren Pythons wäre das wohl "isinstance(index, collections.Sequence)"

Prüfung auf int: noch besser, hast recht.

Schönen Tag,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Sieht gut aus, auch wenn man es warscheinlich selten bis nie gebrauchen wird, da wenn man größere Listen/Arrays hat, wohl doch gleich numpy nimmt.
Dennoch, danke, wieder was gelernt :D
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Oder aber in kurz:

Code: Alles auswählen

>>> l=[[[0,1,2],[3,4,5]],[[6,7,8],[9,10,11]]]
>>> reduce(lambda data, index: data[index], (0,1,2), l)
5
Und auf Integers als Key würde ich auch nicht testen, das erzeugt nur unnötige Einschränkungen. Vielleicht möchte man so etwas machen:

Code: Alles auswählen

>>> reduce(lambda data, index: data[index], (0,1,slice(1,3)), l)
[4, 5]
Oder so etwas:

Code: Alles auswählen

>>> d=[[{"spam":1, "eggs":2}, {"foo":3, "bar":4}], [{"baz":5, "argh":6}]]
>>> reduce(lambda data, index: data[index], (0,1,"foo"), d)
3
Das Leben ist wie ein Tennisball.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@EyDu
Das sieht doch nochmal um längen schicker aus. Könnte man die lambda-Funktion nicht noch durch list.__getitem__ ersetzen?

Obwohl ich Wörterbücher nicht damit mischen würde, hättest du natürlich recht, daran und slices habe ich nicht gedacht und vergess jetzt bloß nicht "Ellipsis" noch mit einzubauen :D

Aber wie gestaltet man damit das setzen des anderen Liste/Arrays?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@Xynon1: Dann funktioniert es ja nur mit Listen. Für's setzen müsste man sich eine Funktion schreiben die sich auf die vorhandene Abstützt.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Stimmt, und ich nehme mal an das "type(data).__getitem__" auch nicht angebracht ist, weil es im Vergleich zu der lambda-Funktion etwas unschöner ausieht.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Dann also so?

Code: Alles auswählen

class Lizzy(list):

    def __getitem__(self, index):
        if isinstance(index, (int, slice)):
            return list.__getitem__(self, index)
        else:
            return reduce(list.__getitem__, index, self)

    def __setitem__(self, index, item):
        if isinstance(index, (int, slice)):
            list.__setitem__(self, index, item)
        else:
            list.__setitem__(self[index[:-1]], index[-1], item)


li = Lizzy([['a', 'b', 'c'], ['d', 'e', 'f']])

print li[1]
print li[1,1]
print li[slice(1,3)]
print li[1, slice(1,3)]
li[0,2] = li[1,1]
print li
li[0, slice(0,3)] = li[1, slice(0,2)]
print li
Ergebnis:

Code: Alles auswählen

['d', 'e', 'f']
e
[['d', 'e', 'f']]
['e', 'f']
[['a', 'b', 'e'], ['d', 'e', 'f']]
[['d', 'e'], ['d', 'e', 'f']]
In specifications, Murphy's Law supersedes Ohm's.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Verhält sich aber irgendwie anders als ich erwarten würde:

Code: Alles auswählen

>>> li = Lizzy([['a', 'b', 'c'], ['d', 'e', 'f']])
>>> la = numpy.array(li)
>>> la
array([['a', 'b', 'c'],
       ['d', 'e', 'f']], 
      dtype='<U1')
>>> li
[['a', 'b', 'c'], ['d', 'e', 'f']]
>>> la[slice(0, 2), 0]
array(['a', 'd'], 
      dtype='<U1')
>>> li[slice(0, 2), 0]
['a', 'b', 'c']
>>> 
Mit den Slice-Ausdrücken kommt es so nicht klar, war zwar auch nicht die Bedingung, aber man würde halt was anderes erwarten.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten