» »

[Python + Numpy] 4D array in izbira elementov

[Python + Numpy] 4D array in izbira elementov

bluefish ::

Zgubljam se v večdimenzionalnih array-ih in mi že ni več jasno, kako se zadeve lotiti. Imam 4D numpy array velikosti (6, 3, 7, 9). Rad bi izračunal povprečje vrednosti po dimenziji 3 za vsaka dva elementa dimenzije 6.

Ja, malo zmedeno zapisano. Torej povprečje vrednosti za array
 [0, 2, :, :] in [1, 2, :, :] 

nato povprečje za
 [2, 2, :, :] in [3, 2, :, :] 

nato še
 [4, 2, :, :] in [5, 2, :, :] 

Skratka, končni rezultat bi bil trikrat array dimenzij (7, 9).

Pri trenutnih dimenzijah lahko zadevo izpeljem ročno z razkosavanjem ipd, vendar bo prvoten array rasel po prvi dimenziji (6 -> 8 -> 10 -> ...) in bi rad vse skupaj avtomatiziral.

Kak nasvet ali kaj konkretnejšega?
  • spremenil: bluefish ()

Raptor F16 ::

Govorimo o matrikah?

bluefish ::

Ja.

jype ::

Vidim, kaj bi rad, ampak dimenzij ne smeš poimenovat po velikostih, ker sem bil temeljito zmeden, ko sem prebral prvo vrstico.

Ti napišem kodo, moment.

Raptor F16 ::

jype ::

a = numpy.array([[[[x+y+z+p for x in range(9)] for y in range(7)] for z in range(3)] for p in range(6)])
numpy.mean([a[0][2],a[1][2]], axis=0)

Si to iskal?

bluefish ::

Jap, to je to. Hvala.

Zgodovina sprememb…

  • odbrisal: bluefish ()

Randomness ::

Še za primer, ko je velikost prve dimenzije poljubno sodo število.
[np.mean(a[i:i+2,2], 0) for i in range(0, a.shape[0], 2)]

giros ::

Se en dober nacin je z uporabo reshape, zelo mocna zadeva za ucnikovito delo z velikimi arrayi.

import numpy as np

a = np.random.rand(6, 3, 7, 9)

x = a.reshape(3, 2, 3, 7, 9)
x[:, :, 2, :, :].mean(axis=1)


Nisem fix, da tole da pravilen rezultat glede na to kar rabis, je pa validirano na jypeovi kodi :)

bluefish ::

Hvala obema, bom testiral.

jype je izjavil:


numpy.mean([a[0][2],a[1][2]], axis=0)

Za pare to deluje. Sicer grem čez celoten array na malce neroden način z zip, ampak OK.

Kaj pa v primeru, če bi delal podobno povprečenje na recimo petih elementih pri array-u s prvo dimenzijo 20 - (20, 3, 7, 9)?

Zgodovina sprememb…

  • spremenil: bluefish ()

giros ::

Lahko poskusis tole

x = a.reshape(4, 5, 3, 7, 9)



Prva stvar na katero sicer pomislim je: zakaj imas taksne dimenzije arraya kot jih imas in zakaj moras na tako cuden nacin povprecit. Seveda cudno je meni, ker ne razumem, kako si prisel do te tocke. Ampak vseeno, firbec.

Randomness ::

N = 5 # povprečili bomo pet elementov
[np.mean(a[i:i+N,2], 0) for i in range(0, a.shape[0], N)]

bluefish ::

Randomness je izjavil:

N = 5 # povprečili bomo pet elementov
[np.mean(a[i:i+N,2], 0) for i in range(0, a.shape[0], N)]
Super. Očitno pozna ura včeraj, ker je bilo že iz tvojega prejšnjega primera jasno, kako se zadevo prilagodi na N elementov.

bluefish ::

giros je izjavil:

Prva stvar na katero sicer pomislim je: zakaj imas taksne dimenzije arraya kot jih imas in zakaj moras na tako cuden nacin povprecit. Seveda cudno je meni, ker ne razumem, kako si prisel do te tocke. Ampak vseeno, firbec.
Tole je del malce obsežnejše skripte za obdelavo predhodno zajetih 3D slik. Na primeru dimenzij (6, 3, 7, 9): 6 slik, koordinate xyz za vsako, 7 x 9 grid točk.
Točke zajemajo podatek o razdalji do neke reference, ki se pomika pred vsakim zajemom slike. Povprečenje in še neka druga statistika se izvaja zaradi analize vpliva tresljajev,... na N zaporednih slikah, ki so zajete iz enake pozicije.

Zgodovina sprememb…

  • spremenil: bluefish ()

bluefish ::

Nov problemčič. Tole je file (.npy), ki vsebuje array: https://filebin.net/ftghfsi03g2hzxb5/da...

Izračunam z-score:

from scipy import stats

data_z = [data[i:i+N, 2] for i in range(0, data.shape[0], N)]
zScore = [np.abs(stats.zscore(data[i:i+N, 2]) for i in range(0, data.shape[0], N)]

Dobim torej data_z in zScore, ki sta lista velikosti 12 in vsebujeta array-e dimenzij (30, 5, 7).
Zdaj pa bi rad iz data_z izločil elemente, ki ne ustrezajo kriteriju. Poenostavljeno, če bi bil data_z 1D array:

data_z = data_z[(zScore < 1)]

Problem je, ker izločitev elementov spremeni dimenzije (torej 0-to pri (30, 5, 7)) in ne vem, kako bi se tega lotil.
data_z naj bi bila v vsakem primeru list z 12 array-i dimenzij 5 x 7.

Drug problem pa so nan vrednosti v zScore. Če je vrednost elementa zScore nan, naj ohrani vrednost na pripadajoči poziciji v data_z.

Zgodovina sprememb…

  • spremenil: bluefish ()

giros ::

Recimo, da hočeš samo izluščiti elemente kjer je zscore manjši od ena, hkrati pa pustiti izvirni array nedotaknjen.

V tvoji kodi (ki se btw ne požene :)) mešaš list in ndarray, kar ni najboljša ideja. Splača se ti delati samo z arrayi, ker tako maksimalno izkoristiš numpy in scipy knjižnico. Recimo takole:

data_z = data.reshape(12, 30, 3, 5, 7)[:, :, 2, :, :]
zscore = np.abs(st.zscore(data_z, axis=1))

nan_zscore = np.isnan(zscore)
zscore[nan_zscore] = data_z[nan_zscore]

zscore_less_than_one = zscore < 1

print(data_z[zscore_less_than_one])


S temi elementi potem počneš kar rabiš naprej, oziroma jih nastaviš na 0/nan/whatever.

Zgodovina sprememb…

  • spremenilo: giros ()

bluefish ::

Hvala.

Sicer je tu še vedno problem z dimenzijami. data_z[zscore_less_than_one] namreč vrne 1D array in s tem izgubim razporeditev elementov. Ohranil bi dimenzije (12, x, 5, 7) oz. (12, 5, 7, x), pri čemer je x različen glede na izločene vrednosti. To pa potem že ni več np array.

Zgodovina sprememb…

  • spremenil: bluefish ()

giros ::

Vidim kaj te muči. Pomembno je, kaj boš kasneje počel s tem. Večinoma se splača imeti array skozi celotno obdelavo. In array mora imeti v vseh dimenzijah vse elemente, kar ponavadi hočeš in se splača tega držat.

Informacija o strukturi arraya je v nan 'maski' in mogoče je v tvojem primeru to dovolj za nadaljno obdelavo. Lahko pa vzameš 'prazen' array in daš na ta način vse ostale elemente na nič oziroma na katero drugo vrednost. To ti omogoči da jih v kasnejših korakih ignoriraš.

data_z_reduced = np.zeros_like(data_z)
data_z_reduced[zscore_less_than_one] = data_z[zscore_less_than_one]


Tretja opcija je seveda da napadeš problem s python list kar se ti imho ne splača.

bluefish ::

Skoraj :)

Recimo data_z[1, :, 3, 3] ima vrednosti 50.5. Ker je vrednost zscore na tem mestu nan, bi pričakoval, da so na mestu data_z_reduced[1, :, 3, 3] vrednosti 50.5 in ne 0.
Čudno sicer, ker zscore[nan_zscore] = data_z[nan_zscore] pravilno nadomesti nan z ustrezno vrednostjo.

giros ::

Kar se zgoraj zgodi je, da se nan vrednosti v zscore nadomestijo z vrednostmi iz data_z, glede na


Drug problem pa so nan vrednosti v zScore. Če je vrednost elementa zScore nan, naj ohrani vrednost na pripadajoči poziciji v data_z.



Morda nekoliko nejasna navodila. Kar ti želiš je, da se, na poziciji nan vrednosti v zscore, v data_z vrednosti ohranijo tudi po zscore > 1. Vse gradnike za to izvest to imaš zgoraj ...

data_z_reduced[nan_zscore] = data_z[nan_zscore]


Lahko tudi združiš obe 'maski', nan in less than, z operatorjem OR, nekako takole

data_z_reduced[zscore_less_than_one | nan_zscore] = data_z[zscore_less_than_one | nan_zscore]

bluefish ::

Sem na hitro preveril podatke in zgleda, da je to ustrezna rešitev. Bo še nekaj zabave pri nadaljnjih izračunih, ampak naj bi šlo. Glede mask in podobnega bo pa treba predelat še nekaj materiala.

EDIT:

V izogib upoštevanju vrednosti 0 pri nadaljnjih izračunih sem inicializacijo data_z_reduced nadomestil z:
data_z_reduced = np.full_like(data_z, np.nan)

Po apliciranju "maske" pa nan vrednosti nato maskiral z:
data_z_reduced_ = np.ma.array(data_z_reduced, mask=np.isnan(data_z_reduced))

Zgodovina sprememb…

  • spremenil: bluefish ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[python] project euler problem

Oddelek: Programiranje
151201 (753) Spura
»

Python - pomoč (strani: 1 2 3 )

Oddelek: Programiranje
10317127 (7875) black ice
»

Coursera naloga (python)

Oddelek: Programiranje
161791 (1419) jype
»

[Python] Pomoč pri računanju Pi-ja

Oddelek: Programiranje
202307 (1939) Spura
»

[Python] učenje

Oddelek: Programiranje
372596 (1893) Isotropic

Več podobnih tem