Numpy Array an den Positionen eines zweiten arrays verändern

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
drindl
User
Beiträge: 5
Registriert: Sonntag 18. September 2016, 12:53

Um auf eine Prüfung zu üben, würde ich gerne die folgende Aufgabe lösen. Jedoch versuche ich es bereits 1.5 Tag und komme keinen Schritt weiter. Ich bin nun langsam am verzweifeln und wäre unglaublich dankbar, wen mir jemand helfen könnte!

Aufgabe:
Write a function, dilate_part(), that takes two arguments, a two-dimensional array of any size and an n*2 array, both with integers. Change the first array at the positions indicated by the second array as follows: Replace the value by the maximum value of itself and its 4 closest neighbors. If there are less than 4 closest neighbors, take the maximum of the closest neighbors that are present.

Use the following array as first input:

import numpy as np
inp1 = np.zeros(shape=(6,8),dtype=int)
inp1[0,6] = 2
inp1[0,7] = 3
inp1[3,0] = 6
inp1[3,1:3] = 8

which is:

[[ 0 0 0 0 0 0 2 3]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 6 8 8 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]]

Use this array as second input:

inp2=np.array([[0,5],[0,7],[2,1],[3,0]])

At the end of the program, call the function as follows:

print (dilate_part(inp1,inp2))

This should yield the following output:

[[ 0 0 0 0 0 2 2 3]
[ 0 0 0 0 0 0 0 0]
[ 0 8 0 0 0 0 0 0]
[ 8 8 8 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]]

Problem
Bei der Aufgabe stellen sich mir v.a. 2 grosse Probleme:
1. Wie kann ich das erste Array an nur den Positionen des 2. Array verändern?
Eigentlich dachte ich, dass sich dieses Problem durch Indexing

Code: Alles auswählen

(inp1[inp2])
lösen lässt. Was dann aber entsteht macht keinen Sinn.
2. Wie kann man in einem numpy array auch die Randzeilen bzw. Spalten elegant mit verändern? Oder muss man für alle 4 Randbereiche eine einzelne For-Schleife erstellen und auch noch für alle 4 Ecken gesondert?

Die For-Schliefe für den mittleren Bereich habe ich versucht aufzustellen, jedoch nicht nur an den Positionen des 2. arrays.

Code: Alles auswählen

    for l in range(1, len(inp1), -1):
        for r in range (len(inp1) -1):
            inp_new[l,r]=max((inp1[l,r], inp1[l, r+1], inp1[l, r-1], inp1[l+1, r], [l-1,r]))
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@drindl: Da das Array inp12-dimensional ist, brauchst Du auch zwei Listen, die die Indizes enthalten:

Code: Alles auswählen

>>> inp1[inp2[:,0], inp2[:,1]]
[0 3 0 6]
Das mit den Rändern ist wirklich ein Problem. Entweder man löst das mit Masken oder »np.clip«, bei zweiterem wird die Funktion zum etwas komplexeren 1-Zeiler.
drindl
User
Beiträge: 5
Registriert: Sonntag 18. September 2016, 12:53

@Sirius3

Vielen Dank für deine Tipps :D Ich bin schon ein rechtes Stück weiter! Jedoch stimmt der Code (Output) leider immer noch nicht ganz.
Vielleicht siehst du ja meinen Fehler! ;-)

Hier ist mein neuer Code:

Code: Alles auswählen

In[1]
import numpy as np
inp1 = np.zeros(shape=(6,8),dtype=int)
inp1[0,6] = 2
inp1[0,7] = 3
inp1[3,0] = 6
inp1[3,1:3] = 8

inp2=np.array([[0,5],[0,4],[2,1],[3,0]])
inp_new=0*inp1
inp12 = inp1[inp2[:,0], inp2[:,1]]
P,Q = inp1.shape
ADJACENTS = [(0, 1), (-1, 0), (1, 0), (0,-1)]

for i in inp12:
    for y,row in enumerate(inp1):
        for x,val in enumerate(row):
            for dy, dx in ADJACENTS:
                if 0 <= y+dy < P and 0 <= x+dx < Q:
                    inp_new[y,x] = max((inp_new[y,x], inp1[y+dy,x+dx]))
print(inp_new)
Out[1]
[[0 0 0 0 0 2 3 2]
 [0 0 0 0 0 0 2 3]
 [6 8 8 0 0 0 0 0]
 [8 8 8 8 0 0 0 0]
 [6 8 8 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]]
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@drindl: Dein Fehler ist, dass Du den Aufgabentext falsch verstanden hast.
Antworten