Jak rozpoznat znamení změny pro elementy v poli NumPy

hlasů
19

Mám NumPy pole s kladnými a zápornými hodnotami v.

a = array([1,1,-1,-2,-3,4,5])

Chci vytvořit další pole, které obsahuje hodnotu na každý index, kde dochází k změna znaménka (například, pokud je aktuální prvek je pozitivní a předchozí prvek je negativní a naopak).

Pro pole výše, očekával bych, že dostat následující výsledek

array([0,0,1,0,0,1,0])

Alternativně seznam poloh v poli, kde dochází k znamení změny nebo seznam booleans místo 0 a 1 je v pořádku.

Položena 16/04/2010 v 10:04
uživatelem
V jiných jazycích...                            


6 odpovědí

hlasů
17

Něco jako

a = array([1,1,-1,-2,-3,4,5])
asign = np.sign(a)
signchange = ((np.roll(asign, 1) - asign) != 0).astype(int)
print signchange
array([0, 0, 1, 0, 0, 1, 0])

Nyní numpy.roll dělá kruhový posun, takže v případě, že poslední prvek má jinou značku než ta první, první prvek v poli signchange být 1. Pokud tomu tak není, lze samozřejmě provést jednoduchý požadovaný

signchange[0] = 0

Také se domnívá, np.sign 0 až mít vlastní značku, odlišný od buď kladné, nebo záporné hodnoty. Např „signchange“ pole pro [-1,0,1] by [0,1,1] přestože nulová linka byla „přešel“ pouze jednou. Pokud je to nežádoucí, jeden mohl vložit řádky

sz = asign == 0
while sz.any():
    asign[sz] = np.roll(asign, 1)[sz]
    sz = asign == 0

mezi řádky 2 a 3, v prvním příkladu.

Odpovězeno 16/04/2010 v 10:16
zdroj uživatelem

hlasů
1

Co takhle

[0 if x == 0 else 1 if numpy.sign(a[x-1]) != numpy.sign(y) else 0 for x, y in enumerate(a)]

numpy.sign přiřadí 0 vlastní značku, takže 0s bude znamení změny z ničeho kromě jiných 0s, což je pravděpodobně to, co chcete.

Odpovězeno 16/04/2010 v 10:17
zdroj uživatelem

hlasů
2

Odpovědi Výše ​​uvedený seznam užití comprehension a některé numpy magie získat požadovaný výsledek. Zde je velmi přímočará, i když trochu spletitý, způsob, jak dělat totéž:

import numpy as np

arr = np.array([1,1,-1,-2,-3,4,5])

result = []
for i, v in enumerate(arr):
    if i == 0:
        change = False
    elif v < 0 and arr[i-1] > 0:
        change = True
    elif v > 0 and arr[i-1] < 0:
        change = True
    else:
        change = False

    result.append(change)

print result
Odpovězeno 16/04/2010 v 10:23
zdroj uživatelem

hlasů
0

K přímému výkladu této otázce, kde se 0 to není jejich případ, je to asi jednodušší použít greaternež sign. Zde je příklad:

a = array([1, 1, -1, -2, -3, 0, 4, 0, 5, 6])

x = greater_equal(a, 0)
sign_change = x[:-1]-x[1:]

Který dává, při tisku s nastavením Tnebo Fna znaménko změnu mezi různými čísly:

 1 F 1 T -1 F -2 F -3 T 0 F 4 F 0 F 5 F 6

při tisku za použití:

print `a[0]`+"".join([(" T" if sign_change[i] else " F")+" "+`a[i+1]` for i in range(len(sign_change))])

Také si všimněte, že se jedná o jeden prvek kratší než původní pole, což dává smysl, protože se ptáte pro změnu znaménka. Chcete-li zahrnout změny mezi posledním a prvním prvkem, můžete použít roll, jak jiní navrhli.

Odpovězeno 16/04/2010 v 19:53
zdroj uživatelem

hlasů
16
(numpy.diff(numpy.sign(a)) != 0)*1
Odpovězeno 30/01/2011 v 15:18
zdroj uživatelem

hlasů
0

Tři způsoby poskytující řadu pozic v poli, kde se vyskytují na znamení změny

import numpy as np
a = np.array([1,1,-1,-2,-3,4,5])

Metoda 1: Multiply sousedících položek v poli a najít negativní

idx1=np.where(a[:-1] * a[1:] < 0 )[0] +1
idx1
Out[2]: array([2, 5], dtype=int64)

%timeit np.where(a[:-1] * a[1:] < 0 )[0] + 1
4.31 µs ± 15.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Metoda 2 (nejrychlejší): Tam, kde nejsou stejné sousedící znaky

idx2=np.where(np.sign(a[:-1]) != np.sign(a[1:]))[0] + 1
idx2
Out[4]: array([2, 5], dtype=int64)

%timeit np.where(np.sign(a[:-1]) != np.sign(a[1:]))[0] + 1
3.94 µs ± 20.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Metoda 3: Jak navrhuje ianalis. Most IMO elegantní, ale o něco pomaleji

idx3=np.where(np.diff(np.sign(a)) != 0)[0] + 1
idx3
Out[6]: array([2, 5], dtype=int64)

%timeit np.where(np.diff(np.sign(a)) != 0)[0] + 1
9.7 µs ± 36.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Odpovězeno 26/05/2017 v 08:26
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more