2015-08-16 15 views
18

La funzionalità Cerco sembra qualcosa di simile:Numpy: Fissare array con righe di lunghezza diversa riempiendo gli elementi vuoti con gli zeri

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

result = fix(data) 
print result 

[[ 1. 2. 3. 4.] 
[ 2. 3. 1. 0.] 
[ 5. 5. 5. 5.] 
[ 1. 1. 0. 0.]] 

Questi array di dati con cui sto lavorando sono molto grandi in modo da apprezzerebbe davvero la soluzione più efficiente.

Modifica: i dati vengono letti dal disco come elenco python di elenchi.

+0

semplicemente aggiungere il tipo di dati alla chiamata funzione di matrice, 'np.array (..., dtype = np.float64) np.array (..., dtype = np.float64)', o uso 'loadtxt',' savetxt' da numpy. – zeroth

+1

@zeroth L'ho provato e ho ottenuto ValueError: impostazione di un elemento dell'array con una sequenza. Potresti spiegare di più? – user2909415

+1

È probabile che sia una matrice sparsa con la maggior parte delle voci come zero? Può essere inserito nella memoria come una matrice densa? –

risposta

13

Questo potrebbe essere uno approccio -

def numpy_fillna(data): 
    # Get lengths of each row of data 
    lens = np.array([len(i) for i in data]) 

    # Mask of valid places in each row 
    mask = np.arange(lens.max()) < lens[:,None] 

    # Setup output array and put elements from data into masked positions 
    out = np.zeros(mask.shape, dtype=data.dtype) 
    out[mask] = np.concatenate(data) 
    return out 

di ingresso del campione, in uscita -

In [222]: # Input object dtype array 
    ...: data = np.array([[1, 2, 3, 4], 
    ...:     [2, 3, 1], 
    ...:     [5, 5, 5, 5, 8 ,9 ,5], 
    ...:     [1, 1]]) 

In [223]: numpy_fillna(data) 
Out[223]: 
array([[1, 2, 3, 4, 0, 0, 0], 
     [2, 3, 1, 0, 0, 0, 0], 
     [5, 5, 5, 5, 8, 9, 5], 
     [1, 1, 0, 0, 0, 0, 0]], dtype=object) 
+0

Penso che 'lens.size' dovrebbe essere' lens.max() '- nella tua risposta questi sono uguali a fare una matrice quadrata. Ma prova con una fila irregolare più lunga del numero di righe e otterrai un errore. –

+0

La risposta accettata è quasi corretta. Presumo che fosse una svista, ma il seguente: # Maschera di posti validi in ogni maschera riga = np.arange (lens.size)

4

Questo sarebbe bello se in qualche modo vettorizzato, ma sono ancora un NOOB, quindi è tutto ciò che ho potuto pensare ora!

import numpy as np,numba as nb 
a=np.array([[1, 2, 3, 4], 
       [2, 3, 1], 
       [5, 5, 5, 5,5], 
       [1, 1]]) 
@nb.jit() 
def f(a): 
    l=len(max(a,key=len)) 
    a0=np.empty(a.shape+(l,)) 
    for n,i in enumerate(a.flat): 
     a0[n]=np.pad(i,(0,l-len(i)),mode='constant') 
    a=a0 
    return a 

print(f(a)) 
11

Si potrebbe utilizzare pandas invece di NumPy:

In [1]: import pandas as pd 

In [2]: df = pd.DataFrame([[1, 2, 3, 4], 
    ...:     [2, 3, 1], 
    ...:     [5, 5, 5, 5], 
    ...:     [1, 1]], dtype=float) 


In [3]: df.fillna(0.0).values 
Out[3]: 
array([[ 1., 2., 3., 4.], 
     [ 2., 3., 1., 0.], 
     [ 5., 5., 5., 5.], 
     [ 1., 1., 0., 0.]]) 
+0

Non sembra funzionare per livelli di nidificazione più profondi, però :( –

4

uso np.pad().

In [62]: arr 
Out[62]: 
[array([0]), 
array([83, 74]), 
array([87, 61, 23]), 
array([71, 3, 81, 77]), 
array([20, 44, 20, 53, 60]), 
array([54, 36, 74, 35, 49, 54]), 
array([11, 36, 0, 98, 29, 87, 21]), 
array([ 1, 22, 62, 51, 45, 40, 36, 86]), 
array([ 7, 22, 83, 58, 43, 59, 45, 81, 92]), 
array([68, 78, 70, 67, 77, 64, 58, 88, 13, 56])] 

In [63]: max_len = np.max([len(a) for a in arr]) 

In [64]: np.asarray([np.pad(a, (0, max_len - len(a)), 'constant', constant_values=0) for a in arr]) 
Out[64]: 
array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
     [83, 74, 0, 0, 0, 0, 0, 0, 0, 0], 
     [87, 61, 23, 0, 0, 0, 0, 0, 0, 0], 
     [71, 3, 81, 77, 0, 0, 0, 0, 0, 0], 
     [20, 44, 20, 53, 60, 0, 0, 0, 0, 0], 
     [54, 36, 74, 35, 49, 54, 0, 0, 0, 0], 
     [11, 36, 0, 98, 29, 87, 21, 0, 0, 0], 
     [ 1, 22, 62, 51, 45, 40, 36, 86, 0, 0], 
     [ 7, 22, 83, 58, 43, 59, 45, 81, 92, 0], 
     [68, 78, 70, 67, 77, 64, 58, 88, 13, 56]]) 
Problemi correlati