2017-08-17 17 views
6

Mam dataset, który ma 4 wymiary (na razie ...) i muszę do iteracji nad nim.Jak iterować na tym n-wymiarowym zestawie danych?

Aby uzyskać dostęp do wartości w dataset, robię to:

value = dataset[i,j,k,l] 

Teraz mogę dostać shape dla dataset:

shape = [4,5,2,6] 

Wartości w shape reprezentują długości wymiar.

W jaki sposób, biorąc pod uwagę liczbę wymiarów, mogę powtórzyć nad wszystkimi elementami w moim zestawie danych? Oto przykład:

for i in range(shape[0]): 
    for j in range(shape[1]): 
     for k in range(shape[2]): 
      for l in range(shape[3]): 
       print('BOOM') 
       value = dataset[i,j,k,l] 

W przyszłości shape mogą ulec zmianie. Na przykład: shape może mieć 10 elementów zamiast bieżącego 4.

Czy istnieje ładny i czysty sposób na zrobienie tego w Pythonie 3?

+0

Myślę, że [rekurencyjne] (http : //www.python-course.eu/recursive_functions.php) rozwiązanie będzie najlepszym rozwiązaniem dla Ciebie. – Yonlif

+0

Możliwy duplikat [Iterowanie przez tablicę wielowymiarową w Pythonie] (https://stackoverflow.com/questions/971678/iterating-through-a-multidimensional-array-in-python) –

Odpowiedz

6

Można użyć itertools.product iteracyjne nad cartesian product pewnych wartości (w tym przypadku indeksy):

import itertools 
shape = [4,5,2,6] 
for idx in itertools.product(*[range(s) for s in shape]): 
    value = dataset[idx] 
    print(idx, value) 
    # i would be "idx[0]", j "idx[1]" and so on... 

Jednak jeśli jest to numpy tablicy chcesz iteracyjne nad, to mógłby być łatwiejsze w użyciu np.ndenumerate:

import numpy as np 

arr = np.random.random([4,5,2,6]) 
for idx, value in np.ndenumerate(arr): 
    print(idx, value) 
    # i would be "idx[0]", j "idx[1]" and so on... 

Prosiłeś o wyjaśnienie, co naprawdę robi itertools.product(*[range(s) for s in shape]). Więc wyjaśnię to bardziej szczegółowo.

Dla przykładu masz tej pętli:

for i in range(10): 
    for j in range(8): 
     # do whatever 

To również może być napisane przy użyciu product jak:

for i, j in itertools.product(range(10), range(8)): 
#          ^^^^^^^^---- the inner for loop 
#        ^^^^^^^^^-------------- the outer for loop 
    # do whatever 

Oznacza to product jest tylko wygodnym sposobem na zmniejszenie liczby index pętli for.

Jeśli chcesz przekonwertować zmienną liczbę for -loops do product ty zasadniczo potrzebne są dwa etapy:

# Create the "values" each for-loop iterates over 
loopover = [range(s) for s in shape] 

# Unpack the list using "*" operator because "product" needs them as 
# different positional arguments: 
prod = itertools.product(*loopover) 

for idx in prod: 
    i_0, i_1, ..., i_n = idx # index is a tuple that can be unpacked if you know the number of values. 
           # The "..." has to be replaced with the variables in real code! 
    # do whatever 

To odpowiednik:

for i_1 in range(shape[0]): 
    for i_2 in range(shape[1]): 
     ... # more loops 
      for i_n in range(shape[n]): # n is the length of the "shape" object 
       # do whatever 
+0

Nie musisz.Indeksowanie za pomocą '[i, j, k, l]' jest równoważne '[(i, j, k, l)]' i 'idx' jest po prostu' (i, j, k, l) 'dzięki czemu możesz po prostu zindeksuj go (jak pokazano) za pomocą 'dataset [idx]'. :) – MSeifert

Powiązane problemy