Comment puis-je combiner un tableau de valeurs et un masque dans une matrice, qui contient chaque valeur du tableau exactement une fois, mais uniquement aux endroits où le masque est différent de zéro? Vous pourriez dire que je veux remplir la matrice de masque avec les valeurs du tableau.

Je ne me soucie pas vraiment de l'ordre des éléments originaux dans le résultat.

mask = [[0, 1, 0], [1, 0, 1], [0, 1, 0]]
values = [1, 2, 3, 4]
result = some_magical_operation(mask, values)

# output: result = [[0, 1, 0], [2, 0, 3], [0, 4, 0]]

# alternative output: result2 = [[0, 2, 0], [1, 0, 3], [0, 4, 0]]
# alternative output: result3 = [[0, 4, 0], [3, 0, 2], [0, 1, 0]]

Remarque: mes matrices réelles sont nettement moins denses que cela.

0
wotanii 23 mai 2020 à 09:34

4 réponses

Meilleure réponse
In [229]: mask = [[0, 1, 0], [1, 0, 1], [0, 1, 0]] 
     ...: values = [1, 2, 3, 4]                                                          
In [230]: mask = np.array(mask, bool)                                                    
In [231]: mask                                                                           
Out[231]: 
array([[False,  True, False],
       [ True, False,  True],
       [False,  True, False]])
In [232]: res =  np.zeros(mask.shape, int)                                               

Si mask est booléen, alors il peut être utilisé pour indexer les emplacements pertinents de res, soit pour récupérer des valeurs, soit pour les affecter.

In [233]: res[mask]                                                                      
Out[233]: array([0, 0, 0, 0])

In [234]: res[mask]= values                                                              
In [235]: res                                                                            
Out[235]: 
array([[0, 1, 0],
       [2, 0, 3],
       [0, 4, 0]])

Pour utiliser scipy.sparse, vous pouvez faire:

In [241]: from scipy import sparse                                                       

Créez une matrice creuse à partir de mask:

In [243]: M = sparse.csr_matrix(mask, dtype=int)                                         
In [244]: M                                                                              
Out[244]: 
<3x3 sparse matrix of type '<class 'numpy.longlong'>'
    with 4 stored elements in Compressed Sparse Row format>
In [245]: M.A                                                                            
Out[245]: 
array([[0, 1, 0],
       [1, 0, 1],
       [0, 1, 0]], dtype=int64)

Puis remplacez ses data valeurs par values:

In [246]: M.data                                                                         
Out[246]: array([1, 1, 1, 1], dtype=int64)                                                         
In [250]: M.data[:] = values                                                             
In [251]: M.A                                                                            
Out[251]: 
array([[0, 1, 0],
       [2, 0, 3],
       [0, 4, 0]], dtype=int64)
1
hpaulj 23 mai 2020 à 06:55

Voici quelque chose que j'ai essayé,

mask = [[0, 1, 0], [1, 0, 1], [0, 1, 0]]
val = [1, 2, 3, 4]
result=list()
k=0

for i in mask:
    for j in range(0,len(i)):
        if i[j]!=0:
            i[j]=val[k]
            k+=1
    result.append(i)
print(result)

Production:

[[0, 1, 0], [2, 0, 3], [0, 4, 0]]

Quelques modifications mineures seront également nécessaires à ce code:

  1. Vérifiez si val [k] ne manque pas d'index
1
Prathamesh Jadhav 23 mai 2020 à 06:46

Je ne sais pas s'il existe une fonction NumPy pour cela, alors j'ai créé la mienne:

import numpy as np


def some_magical_operation_ndarray(m: np.ndarray, v: np.ndarray) -> np.ndarray:
    res = np.zeros(m.shape)
    n = 0
    for i in range(m.shape[0]):
        for j in range(m.shape[1]):
            if not m[i, j] == 0:
                res[i, j] = v[n]
                n += 1
                if n == len(v):
                    n = 0
    return res


mask = np.asarray([[0, 1, 0], [1, 0, 1], [0, 1, 0]])
values = np.asarray([1, 2, 3, 4])
result = some_magical_operation_ndarray(mask, values)
print(result)

Si vous souhaitez travailler avec une liste au lieu d'un ndarray, cette solution fonctionnera:

def some_magical_operation_list(m: list, v: list) -> list:
    res = []
    n = 0
    for i in range(len(m)):
        res.append([])
        for j in range(len(m[i])):
            if not m[i][j] == 0:
                res[i].append(v[n])
                n += 1
                if n == len(v):
                    n = 0
            else:
                res[i].append(0)
    return res


mask = [[0, 1, 0], [1, 0, 1], [0, 1, 0]]
values = [1, 2, 3, 4]
result = some_magical_operation_list(mask, values)
print(result)
1
CG poly 23 mai 2020 à 06:54

Essaye ça:

_mask = np.nonzero(mask)
mask[_mask] = values

Devrait fonctionner exactement comme vous le souhaitez.

Exemple avec un ensemble de test:

mask = np.random.randint(0, 2, (7,3))
mask[_mask] = np.arange(1, _mask[0].shape[0] + 1)    # the RHS is a test equivalent to 'values'

Résultat:

>>> mask (original):
array([[0, 0, 1],
       [1, 0, 0],
       [1, 1, 1],
       [0, 1, 1],
       [0, 1, 1],
       [0, 1, 0],
       [0, 1, 1]])

>>> mask (modified):
array([[ 0,  0,  1],
       [ 2,  0,  0],
       [ 3,  4,  5],
       [ 0,  6,  7],
       [ 0,  8,  9],
       [ 0, 10,  0],
       [ 0, 11, 12]])

Faites une copie de mask et utilisez _mask sur le tableau copié si vous ne souhaitez pas modifier mask lui-même.

1
amzon-ex 23 mai 2020 à 07:13