Man ir 2D NumPy masīvs, un es vēlētos aizstāt visas vērtības, kas tajā ir lielākas vai vienādas ar robežvērtību T, ar 255,0. Cik man zināms, visvienkāršākais veids būtu:
shape = arr.shape
result = np.zeros(shape)
for x in range(0, shape[0]):
for y in range(0, shape[1]):
if arr[x, y] >= T:
result[x, y] = 255
Kāds ir kodolīgākais un pitoniskākais veids, kā to izdarīt?
Vai ir kāds ātrāks (iespējams, mazāk kodolīgs un/vai mazāk pitonisks) veids, kā to izdarīt?
Tas būs daļa no loga/līmeņa pielāgošanas apakšprogrammas cilvēka galvas magnētiskās rezonanses skenēšanai. 2D numpy masīvs ir attēla pikseļu dati.
Manuprāt, ātrākais un kodolīgākais veids, kā to izdarīt, ir izmantot NumPy iebūvēto Fancy indeksēšanu. Ja jums ir ndarray
ar nosaukumu arr
, jūs varat aizstāt visus elementus >255
ar vērtību x
šādi:
arr[arr > 255] = x
Es to izmēģināju savā datorā ar 500 x 500 nejaušu matricu, aizstājot visas vērtības >0,5 ar 5, un tas aizņēma vidēji 7,59 ms.
In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)
In [3]: timeit A[A > 0.5] = 5
100 loops, best of 3: 7.59 ms per loop
Tā kā jūs faktiski vēlaties citu masīvu, kas ir arr
, ja arr < 255
, un 255
citos gadījumos, to var izdarīt vienkārši:
result = np.minimum(arr, 255)
Vispārīgāk, lai noteiktu apakšējo un/vai augšējo robežu:
result = np.clip(arr, 0, 255)
Ja vēlaties piekļūt tikai vērtībām virs 255 vai kam sarežģītākam, @mtitan8'atbilde ir vispārīgāka, bet np.clip
un np.minimum
(vai np.maximum
) ir patīkamāka un daudz ātrāka jūsu gadījumā:
In [292]: timeit np.minimum(a, 255)
100000 loops, best of 3: 19.6 µs per loop
In [293]: %%timeit
.....: c = np.copy(a)
.....: c[a>255] = 255
.....:
10000 loops, best of 3: 86.6 µs per loop
Ja vēlaties to izdarīt uz vietas (t.i., modificēt arr
, nevis izveidot rezultātu
), varat izmantot np.minimum
parametru out
:
np.minimum(arr, 255, out=arr)
vai
np.clip(arr, 0, 255, arr)
(out=
vārds nav obligāts, jo argumenti ir tādā pašā secībā kā funkcijas definīcijā).)
Vietas modifikācijas gadījumā bolu indeksēšana ievērojami paātrina darbību (bez nepieciešamības atsevišķi izveidot un pēc tam modificēt kopiju), bet joprojām nav tik ātra kā minimum
:
In [328]: %%timeit
.....: a = np.random.randint(0, 300, (100,100))
.....: np.minimum(a, 255, a)
.....:
100000 loops, best of 3: 303 µs per loop
In [329]: %%timeit
.....: a = np.random.randint(0, 300, (100,100))
.....: a[a>255] = 255
.....:
100000 loops, best of 3: 356 µs per loop
Salīdzinājumam, ja jūs vēlaties ierobežot vērtības ar minimumu un maksimumu, bez clip
jums tas būtu jādara divreiz, izmantojot kaut ko līdzīgu.
np.minimum(a, 255, a)
np.maximum(a, 0, a)
vai,
a[a>255] = 255
a[a<0] = 0
Varat apsvērt iespēju izmantot numpy.putmask:
np.putmask(arr, arr>=T, 255.0)
Šeit ir snieguma salīdzinājums ar Numpy iebūvēto indeksēšanu:
In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)
In [3]: timeit np.putmask(A, A>0.5, 5)
1000 loops, best of 3: 1.34 ms per loop
In [4]: timeit A[A > 0.5] = 5
1000 loops, best of 3: 1.82 ms per loop