2016-10-16 9 views
5

otrzymuje dwie tablice, powiedzmyNumpy powtórz dla 2d tablicy

arr = array([10, 24, 24, 24, 1, 21, 1, 21, 0, 0], dtype=int32) 
rep = array([3, 2, 2, 0, 0, 0, 0, 0, 0, 0], dtype=int32) 

np.repeat (arr, rep) zwraca

array([10, 10, 10, 24, 24, 24, 24], dtype=int32) 

Czy istnieje jakiś sposób, aby replikować tej funkcjonalności dla zestawu tablic 2D ?

który jest podany

arr = array([[10, 24, 24, 24, 1, 21, 1, 21, 0, 0], 
      [10, 24, 24, 1, 21, 1, 21, 32, 0, 0]], dtype=int32) 
rep = array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0], 
      [2, 2, 2, 0, 0, 0, 0, 0, 0, 0]], dtype=int32) 

jest to możliwe, aby utworzyć funkcję, która vectorizes?

PS: Liczba powtórzeń w każdym wierszu nie musi być taka sama. Podaję każdy wiersz wyników, aby upewnić się, że są tego samego rozmiaru.

def repeat2d(arr, rep): 
    # Find the max length of repetitions in all the rows. 
    max_len = rep.sum(axis=-1).max() 
    # Create a common array to hold all results. Since each repeated array will have 
    # different sizes, some of them are padded with zero. 
    ret_val = np.empty((arr.shape[0], maxlen)) 
    for i in range(arr.shape[0]): 
     # Repeated array will not have same num of cols as ret_val. 
     temp = np.repeat(arr[i], rep[i]) 
     ret_val[i,:temp.size] = temp 
    return ret_val 

Wiem o np.vectorize i wiem, że nie daje żadnych korzyści wydajnościowych w stosunku do normalnej wersji.

Odpowiedz

4

Masz zatem inną tablicę powtórzeń dla każdego rzędu? Ale całkowita liczba powtórzeń w rzędzie jest taka sama?

Po prostu wykonaj repeat na spłaszczonych tablicach i przekształć z powrotem do odpowiedniej liczby wierszy.

In [529]: np.repeat(arr,rep.flat) 
Out[529]: array([10, 10, 10, 24, 24, 24, 24, 10, 10, 24, 24, 24, 24, 1]) 
In [530]: np.repeat(arr,rep.flat).reshape(2,-1) 
Out[530]: 
array([[10, 10, 10, 24, 24, 24, 24], 
     [10, 10, 24, 24, 24, 24, 1]]) 

Jeśli liczba powtórzeń w wierszu jest różna, mamy problem z wypełnianiem wierszy o zmiennej długości. Pojawiły się w innych pytaniach SO. Nie pamiętam wszystkich szczegółów, ale myślę, że rozwiązaniem jest wzdłuż tej linii:

Zmień rep więc numery różnią:

In [547]: rep 
Out[547]: 
array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0], 
     [2, 2, 2, 1, 0, 2, 0, 0, 0, 0]]) 
In [548]: lens=rep.sum(axis=1) 
In [549]: lens 
Out[549]: array([7, 9]) 
In [550]: m=np.max(lens) 
In [551]: m 
Out[551]: 9 

stworzyć cel:

In [552]: res = np.zeros((arr.shape[0],m),arr.dtype) 

tworzenia tablica indeksowania - szczegóły trzeba opracować:

In [553]: idx=np.r_[0:7,m:m+9] 
In [554]: idx 
Out[554]: array([ 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17]) 

mieszkanie indeksowane assi gnment:

In [555]: res.flat[idx]=np.repeat(arr,rep.flat) 
In [556]: res 
Out[556]: 
array([[10, 10, 10, 24, 24, 24, 24, 0, 0], 
     [10, 10, 24, 24, 24, 24, 1, 1, 1]]) 
+0

Łączna liczba powtórzeń w wierszu nie musi być taka sama. Właśnie dlatego odkrywam maxlen, a następnie dopełniaję każdy rząd, by był tego samego rozmiaru. – Aditya369

+0

A ty dopełniasz losowymi wartościami 'pustymi'? Widziałem ukryte wstawki, które obsługują rzędy o zmiennej długości, ale nie pamiętam szczegółów. – hpaulj

+0

Tak. Wypełniam je losowymi pustymi wartościami. Chociaż wydaje mi się, że bardziej sensowne jest używanie zer w moim przypadku. – Aditya369

1

Innym rozwiązaniem podobnym do użytkownika @ hpaulj rozwiązanie:

def repeat2dvect(arr, rep): 
    lens = rep.sum(axis=-1) 
    maxlen = lens.max() 
    ret_val = np.zeros((arr.shape[0], maxlen)) 
    mask = (lens[:,None]>np.arange(maxlen)) 
    ret_val[mask] = np.repeat(arr.ravel(), rep.ravel()) 
    return ret_val 

Zamiast przechowywania indeksów, tworzę maskę bool i stosując maskę, aby ustawić wartości.