2015-06-18 12 views
5

Mam dużą tablicę numpy (zazwyczaj rzędu 500 000 x 1024, ale może być większa) i próbuję wykonać kilka procesów, które zależą od tego, gdzie wartości dodatnie w tablicy są. bardzo mały przykład tablica może byćEfficiently znalezienie zakresu indeksów dla wartości dodatnich w tablicy numpy 2D

[[ 0., 0., 0., 0., 0.,-1.,-1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 1., 1., 0., 0., 1., 5., 0., 0.], 
    [ 0., 1., 1., 0., 0., 0., 1., 0., 0.], 
    [ 0., 3., 1., 0., 0., 2., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 1., 0., 0., 0., 1., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., 0.]] 

Pierwszy jest zastąpienie żadnych zer pomiędzy dodatnimi, które są mniej niż trzy kolumny od siebie w każdym rzędzie. więc jeśli mogę wymienić tych liczb z 50, mój przykład wyjście byłoby

[[ 0., 0., 0., 0., 0.,-1.,-1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 1., 1.,50.,50., 1., 5., 0., 0.], 
    [ 0., 1., 1., 0., 0., 0., 1., 0., 0.], 
    [ 0., 3., 1.,50.,50., 2., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 1., 0., 0., 0., 1., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., 0.]] 

Drugą rzeczą, którą musisz zrobić, to napisać niektóre informacje dla każdego wiersza w oparciu o którym zakresy wartości są dodatnie. Na przykład używając mojej zmienionej tablicy, muszę być w stanie wypisać jedną instrukcję dla trzeciego rzędu, deklarując dodatnie liczby całkowite dla col [1: 7] i dwie instrukcje dla czwartego rzędu, deklarując dodatnie liczby całkowite w col [1: 3] i col [6].

Udało mi się wykorzystać metody numpy wektorowe do punktu, aby walczyć z pierwszym zadaniem, ale wciąż kończyło się odwoływaniem do pętli zarówno w kolumnach jak i wierszach (aczkolwiek w podzbiorze całej tablicy). W przeciwnym razie zastępuję wszystkie zera w danym wierszu, a nie tylko te między wartościami dodatnimi.

Ale drugie zadanie nie wydaje się znaleźć sposób to zrobić bez rowerze przez cały tablicy przy użyciu

for col in arr: 
    for row in arr: 

Chyba moje ogólne pytanie byłoby, czy istnieje sposób, aby korzystanie z metody wektorowe w numpy, aby zdefiniować zakresy indeksów kolumn, które będą się różnić dla każdego wiersza i będą zależeć od wartości w poniższej kolumnie?

Każda pomoc będzie mile widziana.

Odpowiedz

-1

przypadku pierwszego problemu: utworzyć zmienną, która posiada indeks pierwszego liczbę dodatnią można natknąć się i mieć w razie stwierdzenia, że ​​resetuje pozycję czy następna wartość jest dodatnia i liczyć (zmienną, która liczy położenie z dala od pierwsza liczba dodatnia) jest mniejsza niż 3.

Dla twojego drugiego problemu: Utwórz tablicę i dodaj indeksy lokalizacji wartości dodatnich.

String[] indices = new String[]; 
int pos = 0; 
for col in arr: 
    for row in arr: 
     if(index is positive){ 
      indices[pos] = "[" + col + ":" + row + "]"; 
      pos++; 
     } 
+0

Dziękuję za odpowiedź, ale to nadal wymaga użycia pętli do przechodzenia przez każdą kolumnę i wiersz, co jest dokładnie tym, czego staram się unikać. Moje tablice są duże i zajmuje to dużo czasu. Mam nadzieję, że jest sposób, w jaki mogę to zrobić za pomocą wbudowanych funkcji, które nie wymagają przechodzenia przez macierz. –

+0

W jaki sposób tworzysz tablice? Można technicznie utworzyć listę obiektów zawierających indeksy, wartość i to, czy jest dodatnia. Następnie możesz użyć forloop, aby pobrać i zwrócić wszystkie, które chcesz. Czas tego rozwiązania będzie wynosił O (N). Zakładając, że nie używasz wbudowanego forloop do tworzenia tablic w pierwszej kolejności. – blaqksilhouette

+0

Tworzenie macierzy odbywa się całkowicie niezależnie, ale w rzeczywistości stanowią one rodzaj maski dla rzeczywistych danych przechowywanych w osobnej tablicy o tym samym kształcie. –

-1

Druga metoda miałaby dane tworzenia obiektów, więc powiedzmy, że masz klasę:

public class Matrix{ 
    int indicex; 
    int indicey; 
    double val; 
    boolean positiveInt; 

    //default constructor 
    public Matrix(int indicex, int indicey, double val, boolean positiveInt){ 
    this.indicex = indicex; 
    this.indicey = indicey; 
    this.val = val; 
    this.positiveInt = positiveInt; 
    }  

    //getter 
    public boolean isPositive(){ 
     if(positiveInt == true){ 
       return true; 
     }else{ 
      return false; 
     } 

a następnie w klasie kierowcy trzeba mieć swoje dane są odczytywane i utworzyć obiekt nowy Matrix (indexx, indexy, val, true/false) .... i które zostaną umieszczone w tablicy, którą można wyszukać pod kątem liczb dodatnich.

List<Matrix> storeObjects = new ArrayList<Matrix>(); 
some method(){ 
    Matrix matrixObject = new Matrix(indexx, indexy, val, trueOrFalse); 
    storeObjects.add(matrixObject) 
} 

for every object in store objects 
    if(object.isPositive()){ 
     put object in a separate array of positive objects 
    } 
    } 
+0

To ma sens, wymagałoby to jeszcze sporo manipulacji końcową tablicą, aby uzyskać informacje o kolumnach w każdym wierszu (tj. za każdym razem) Muszę napisać w moim końcowym oświadczeniu. Moje główne pytanie związane z tą sugestią polega jednak na tym, że nie mogę utworzyć tej macierzy z początkowymi macierzami danych, o ile mogę powiedzieć, że nadal będę musiał wykonać pętlę elementarną w całej mojej tablicy, aby zinterpretować ją w lista macierzy najpierw? –

+0

To byłby jeden dla pętli kontra 2 ..... więc czas z O (N) kontra O (N^2) – blaqksilhouette

0

Można użyć skutecznych iteratory NumPy jak flatiter lub nditer

Na przykład dla drugiego zadania

In [1]: x = array([[ 0., 0., 0., 0., 0.,-1.,-1., 0., 0.], 
    ...:   [ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
    ...:   [ 0., 1., 1.,50.,50., 1., 5., 0., 0.], 
    ...:   [ 0., 1., 1., 0., 0., 0., 1., 0., 0.], 
    ...:   [ 0., 3., 1.,50.,50., 2., 1., 0., 0.], 
    ...:   [ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
    ...:   [ 0., 1., 0., 0., 0., 1., 1., 0., 0.], 
    ...:   [ 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) 

In [2]: islands = [] 
    ...: fl = x.flat 
    ...: while fl.index < x.size: 
    ...:  coord = fl.coords 
    ...:  if fl.next() > 0: 
    ...:   length = 1 
    ...:   while fl.next() > 0: 
    ...:    length +=1 
    ...:   islands.append([coord, length]) 

In [3]: for (row, col), length in islands: 
    ...:  print 'row:%d ; col[%d:%d]' %(row, col, col+length) 
row:2 ; col[1:7] 
row:3 ; col[1:3] 
row:3 ; col[6:7] 
row:4 ; col[1:7] 
row:6 ; col[1:2] 
row:6 ; col[5:7] 
1

NumPy niestety nie można zrobić dużo przetwarzania bez generowania więcej tablic, więc obawiam się, że jakiekolwiek rozwiązanie będzie wymagać albo jakiejś formy pętli ręcznej, jakiej używasz, albo tworzenia jednej lub więcej dodatkowych dużych tablic.Możesz być w stanie wymyślić rozwiązanie, które jest dość szybkie i wydajne w użyciu pamięci za pomocą numexpr.

Oto sposób, w jaki robimy to w sposób, który niekoniecznie jest efektywny z pamięci, ale przynajmniej wszystkie pętle będą wykonywane przez Numpy, więc powinno być o wiele szybciej niż to, co robiłeś tak długo, jak długo pasuje do Twojej pamięci. (Sprawność pamięci może być poprawiona przez przepisanie niektórych to jak operacje na miejscu, ale nie będę się o to martwić.)

Oto twój krok 1:

positive = x>0 # a boolean array marking the positive values in x 

positive0 = positive[:,0:-3] # all but last 3 columns 
positive1 = positive[:,1:-2] # all but 1st and last 2 columns; not actually used 
positive2 = positive[:,2:-1] # all but first 2 and last 1 columns 
positive3 = positive[:,3: ] # all but first 3 columns 

# In the following, the suffix 1 indicates that we're viewing things from the perspective 
# of entries in positive1 above. So, e.g., has_pos_1_to_left1 will be True at 
# any position where an entry in positive1 would be preceded by a positive entry in x 

has_pos_1_to_left1 = positive0 
has_pos_1_or_2_to_right1 = positive2 | positive3 
flanked_by_positives1 = has_pos_1_to_left1 & has_pos_1_or_2_to_right1 

zeros = (x == 0)  # indicates everywhere x is 0 
zeros1 = zeros[:,1:-2] # all but 1st and last 2 columns 

x1 = x[:,1:-2]   # all but 1st and last 2 columns 

x1[zeros1 & flanked_by_positives1] = 50 # fill in zeros that were flanked - overwrites x! 

# The preceding didn't address the next to last column, b/c we couldn't 
# look two slots to the right of it without causing error. Needs special treatment: 
x[:,-2][ zeros[:,-2] & positive[:,-1] & (positive[:,-4] or positive[:,-3])] = 50 

A oto twój krok 2:

filled_positives = x>0 # assuming we just filled in x 
diffs = numpy.diff(filled_positives) # will be 1 at first positive in any sequence, 
            # -1 after last positive, zero elsewhere 

endings = numpy.where(diffs==-1) # tuple specifying coords where positive sequences end 
           # omits final column!!! 
beginnings = numpy.where(diffs==1) # tuple specifying coords where pos seqs about to start 
            # omits column #0!!! 

powinny być proste w użyciu tych współrzędnych początku i końca, aby wydobyć informacje na temat każdego wiersza Mówiłeś potrzebne, ale należy pamiętać, że różnica ta metoda wykrywania-łapie tylko przejścia z nieprzestrzegania położenie, do pozytywnego lub odwrotnie, więc nie będzie wspominać o dodatnich ciągach rozpoczynających się w kolumnie zerowej lub kończących się w ostatniej kolumnie, więc jeśli chcesz, musisz szukać tych przejść.

Powiązane problemy