2
votes

Créer une matrice à partir d'une fonction

Je souhaite créer une matrice à partir d'une fonction, telle que la (3,3) matrice C ait des valeurs égales à 1 si l'index de ligne est inférieur à un seuil k donné.

import numpy as np

k = 3
C = np.fromfunction(lambda i,j: 1 if i < k else 0, (3,3))

Cependant, ce morceau de code génère une erreur

"La valeur de vérité d'un tableau avec plus d'un élément est ambiguë. Utilisez a.any () ou a.all () "et je ne comprends pas vraiment pourquoi.


4 commentaires

Créez un tableau de zéros c = np.zeros ((3,3)) , puis c [: k,:] = 1 ?


Cela fonctionnerait, mais je suis intéressé par la nature de cette erreur.


Hein? Sûrement l = lambda i, j: 1 si i et C = np.fromfunction (np.vectorize (l), (5,3))


np.fromfunction crée simplement une grille et transmet le tout à votre fonction en un seul appel. Regardez son code.


3 Réponses :


1
votes

Comme suggéré par @MarkSetchell, vous devez vectorisez votre fonction:

C
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

et vous obtenez:

k = 3
f = lambda i,j: 1 if i < k else 0

C = np.fromfunction(np.vectorize(f), (3,3))


2 commentaires

Il a également suggéré une mise en forme avec 5 rangées pour que vous puissiez voir et vérifier le résultat!


@MarkSetchell Il est vraiment brillant.



1
votes

Le problème est que np.fromfunction n'itère pas sur tous les éléments, il ne renvoie que les indices de chaque dimension. Vous pouvez utiliser np.where () pour appliquer une condition basée sur ces indices, en choisissant parmi deux alternatives en fonction de la condition:

array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1],
       [0, 0, 0],
       [0, 0, 0]])

ce qui donne: p >

import numpy as np

k = 3
np.fromfunction(lambda i, j: np.where(i < k, 1, 0), (5,3))

Cela évite de nommer le lambda sans que les choses deviennent trop lourdes. Sur mon ordinateur portable, cette approche était environ 20 fois plus rapide que np.vectorize().


0 commentaires

2
votes

Le code pour fromfunction est:

In [680]: np.where(np.arange(3)[:,None]<2, np.ones((3,3),int), np.zeros((3,3),int))  
Out[680]: 
array([[1, 1, 1],
       [1, 1, 1],
       [0, 0, 0]])

Vous voyez qu'il appelle function une seule fois - avec tout le tableau de indices . Ce n'est pas itératif.

In [677]: np.vectorize(lambda i,j: 1 if i < 2 else 0)(idx[0],idx[1])                 
Out[677]: 
array([[1, 1, 1],
       [1, 1, 1],
       [0, 0, 0]])

Votre lambda attend des valeurs scalaires i, j , pas un tableau 3D

 lambda i,j: 1 if i < k else 0


0 commentaires