Sie können boolean Indizierung verwenden zusammen mit erweiterten numpy Array-Indizierung:
array3 = array1.astype(float) # this copies the array by default.
array3[array1 != 0] = array2[array1[array1 != 0]-1, 2]
das Ergebnis:
array([[ 0, 62., 62., 88.],
[ 0, 73., 64., 95.],
[ 0, 59., 67., 65.]])
Erklärung
Sie zuerst einen boolean-Array erstellen, die anzeigt, wo es nicht-Null-Einträge :
>>> non_zero_mask = array1 != 0
array([[False, True, True, True],
[False, True, True, True],
[False, True, True, True]], dtype=bool)
Dies wird verwendet werden, um die Elemente zu finden, die Shoul d ersetzt werden.
Dann müssen Sie die Werte dieser Elemente finden:
>>> non_zero_values = array1[non_zero_mask]
array([7, 4, 1, 8, 5, 2, 9, 6, 3])
Da Ihr array2
bestellt und beginnt mit dem Wert 1 brauchen wir eine subtrahieren Sie die entsprechende Zeile für den Wiederbeschaffungswert zu finden. Wenn Ihr array2
nicht sortiert Sie es sortieren könnte müssen oder eine andere Indizierung tun zwischendurch:
>>> replacement_rows = array2[non_zero_values-1]
array([[ 7., 7., 62.],
[ 4., 4., 62.],
[ 1., 1., 88.],
[ 8., 8., 73.],
[ 5., 5., 64.],
[ 2., 2., 95.],
[ 9., 9., 59.],
[ 6., 6., 67.],
[ 3., 3., 65.]])
>>> replacement_values = array2[non_zero_values-1, 2] # third element of that row!
array([ 62., 62., 88., 73., 64., 95., 59., 67., 65.])
und dann nur diese Werte auf den ursprünglichen oder neuen Array zuweisen:
array3[non_zero_mask] = replacement_values
Dieser Ansatz beruht auf die Bestellung von array2
so wird es brechen, wenn es kompliziertere Bedingungen gibt. Aber das würde entweder erfordern, diese Beziehung zwischen Wert und Index zu finden und es anstelle der einfachen -1
, die ich tat, oder eine andere Zwischenstufe np.where
/boolean Indizierung einfügen.
Erweiterte
Falls Sie haben keine sortiert array2
und Sie können es nicht sortieren Sie tun können:
>>> array3 = array1.astype(float)
>>> array3[array1 != 0] = array2[np.where(array2[:, 0][None, :] == array1[array1 != 0][:, None])[1], 2]
>>> array3
array([[ 0., 62., 62., 88.],
[ 0., 73., 64., 95.],
[ 0., 59., 67., 65.]])
da dies mit Ausstrahlung der Arrays gegeneinander arbeitet man werde Erstellen Sie ein Array mit der Größe array1.size * array1.size
.Dies ist möglicherweise nicht sehr memoreffizient, aber vollständig vektorisiert.
Numba (wenn Sie Geschwindigkeit wollen)
numba groß ist, wenn Sie beschleunigen, wollen die Dinge, die langsam sein würde, weil es keine native numpy oder scipy Version. Wenn Sie Anakonda oder CONDA es bereits installiert ist, so dass es eine sinnvolle Option sein könnte:
import numba as nb
import numpy as np
@nb.njit
def nb_replace_values(array, old_new_array):
res = np.zeros(array.shape, dtype=np.float64)
rows = array.shape[0]
columns = array.shape[1]
rows_replace_array = old_new_array.shape[0]
for row in range(rows):
for column in range(columns):
val = array[row, column]
# only replace values that are not zero
if val != 0:
# Find the value to replace the element with
for ind_replace in range(rows_replace_array):
if old_new_array[ind_replace, 0] == val:
# Match found. Replace and break the innermost loop
res[row, column] = old_new_array[ind_replace, 2]
break
return res
nb_replace_values(array1, array2)
array([[ 0., 62., 62., 88.],
[ 0., 73., 64., 95.],
[ 0., 59., 67., 65.]])
Speziell für großen Arrays dies eindeutig die schnellste und speichereffiziente Lösung sein, da keine temporären Arrays erstellt werden. Der erste Aufruf wird viel langsamer, da die Funktion im laufenden Betrieb kompiliert werden muss.
Timings:
%timeit nb_replace_values(array1, array2)
100000 Schleifen, am besten von 3: 6,23 & mgr; s pro Schleife
%%timeit
array3 = array1.astype(float)
array3[array1 != 0] = array2[np.where(array2[:, 0][None, :] == array1[array1 != 0][:, None])[1], 2]
10000 Schleifen, am besten von 3: 74,8 & mgr; s pro Schleife
# Solution provided by @PDRX
%%timeit
array3 = array1.astype(float)
for i in array2[:,0]:
i_arr1,j_arr1 = np.where(array1 == i)
i_arr2 = np.where(array2[:,0] == i)
array3[i_arr1,j_arr1] = array2[i_arr2,2]
1000 Schleifen, am besten von 3: 689 & mgr; s pro Schleife
Nun, im Beispiel I gab array2 zwar sortiert, aber im Allgemeinen wird angenommen, jede Anordnung sein, nicht unbedingt sortiert, mit zufälligen Zahlen, die vielleicht nicht in einer einheitlichen Reihenfolge sortiert werden können, solange sich diese Zahlen nicht wiederholen - denken Sie an diese Spalte als ID. Kannst du deine Antwort darauf basierend verbessern? Ich werde mein Beispiel aktualisieren. – Bella
@Bella Das ist viel schwieriger und ich habe nicht viel darüber nachgedacht. Aber siehe den letzten Teil der Antwort. Dies ist sehr ineffizient und ich würde wahrscheinlich eher "Pandas" oder eine benutzerdefinierte "numba" -Funktion für diese Fälle empfehlen. – MSeifert
Oh, ich habe deine letzte Bearbeitung noch nicht gesehen! Als ich die andere Antwort sah, verstand ich sofort, was großartig war. Ihnen ist etwas schwieriger zu bekommen, aber Sie haben Recht, ich testete beide Lösungen für die Geschwindigkeit und Ihre ist schneller, obwohl es für größere Arrays nur eine Größenordnung schneller ist. Jetzt bin ich irgendwie unschlüssig welche Antwort ich annehmen soll, da ich wohl beide behalten werde. :/Ich habe das, was Sie über die Array-Größe erwähnt haben, nicht bekommen - von dem aus kann ich Array3 als die gleiche Größe wie Array1 sehen und in beiden Lösungen gibt mir getsizeof die gleiche Größe. – Bella