Multiplier une matrice par ligne avec BYCOL

Bonjour à tous,

J'ai crée cette formule qui est fonctionnelle (dans le classeur ci-joint) :

=LET(
Plage_AN;Tableau1;
NB;E2:E4;
Plage_NB;ORGA.COLS(INDEX(NB;MOD(SEQUENCE(LIGNES(NB)*COLONNES(Plage_AN);;0);LIGNES(NB))+1);LIGNES(NB));
MAP(Plage_AN;Plage_NB;LAMBDA(x;y;x*y)))

Je souhaiterais avoir le même résultat avec BYCOL. Le souci que j'ai, c'est que je n'arrive pas à faire en sorte d'avoir une formule unique et dynamique.

Peut-être avec REDUCE ?

En vous remerciant par avance

13matrice.xlsx (11.34 Ko)

Salut JB_,

Je suis pas sur de bien comprendre, il me semble que ta formule est bien longue pour faire une opération Matrice(3,3)*Vecteur(3,1) :

=Tableau1*E2:E4

Quelque chose m'échappe ?

Hello Saboh,

Je te l'accorde , mais je suis plus dans une démarche d'exploration pour mieux comprendre le fonctionnement de certaines fonctions

Donc ce même résultat avec BYCOL m’intéresse.

Bonjour

La fonction BYCOL n'est pas adaptée dans ce cas

voir l'aide en ligne :

Ne pas fournir de fonction LAMBDA ou autre chose qu’une valeur unique retournée par la fonction LAMBDA retourne une erreur #CALC.

Avec MAKEARRAY

=MAKEARRAY(LIGNES(Tableau1);COLONNES(Tableau1);LAMBDA(i;j;INDEX(Tableau1;i;j)*INDEX(E2:E4;i)))

par ailleurs

Plage_NB;NB*SEQUENCE(;COLONNES(Plage_AN);;0);

est équivalent à

Plage_NB;ORGA.COLS(INDEX(NB;MOD(SEQUENCE(LIGNES(NB)*COLONNES(Plage_AN);;0);LIGNES(NB))+1);LIGNES(NB));

Stéphane

Ah d'accord je me disais aussi ^^

Alors en fait tu l'as certainement remarqué, tu tombes sur le cas des NESTED ARRAYS dès que tu veux renvoyer >1 cellule par BYCOL/BYROW. C'est normal d'ailleurs car ces fonctions ont pour objectif initial de faire des totaux si j'ai bien compris.

Il y a donc 2 solutions, ou bien tu peux "envelopper" le BYCOL dans une lecture ligne par ligne, et donc appliquer BYCOL sur une LIGNE UNIQUE du tableau (qui te renvoie l'équivalent d'un MAP en fait), puis VSTACK les résultats. C'est la solution avec REDUCE par exemple.

=LET(
    _tbl; Tableau1;
    _nbs; E2:E4;
    _com1; "seqI permet de parcourir la liste des lignes de _tbl";
    _seqI; SEQUENCE(ROWS(_tbl));
    _com2; "On drop la 1e ligne du REDUCE ('') qui est necessaire mais inutile.";
    _com3; "avec REDUCE+VSTACK on va accumuler les BYCOL appliqués à chaque ligne de _tbl";
    DROP(REDUCE(""; _seqI; LAMBDA(a; i;
                VSTACK(
                    a;
                    LET(
                        _com4; "recuperation de la ligne dans _tbl et du numero dans _nbs";
                        currRow; INDEX(_tbl; i; 0);
                        nbI; INDEX(_nbs; i);
                        _com5; "utilisation de BYCOL";
                        BYCOL(currRow; LAMBDA(c; c * nbI))
                    )
                )
        ));
    1)
)

Sinon tu peux utiliser ce qu'on appelle les THUNKS, ca consiste à contourner les limitations des NESTED ARRAYS en stockant les résultats intermédiaires (arrays) dans des LAMBDAS. C'est un peu bizarre à expliquer mais en gros NESTED ARRAYS = liste de liste ≠ matrice2D. Donc pour contourner on fait une liste de LAMBDA (qui sont considérés comme des valeurs), puis ensuite on va utiliser MAKEARRAY pour aller lire nos liste imbriquées et récupérer, index par index (ligne/colonne), les valeurs stockées dans les lambdas.

THUNK = groupe de valeurs considéré par Excel comme une valeur unique - en interne c'est un "LAMBDA" - . A "déplier" avec INDEX. Tu peux les nester indéfiniment.

Cependant dans ton cas précis c'est un peu plus compliqué puisque, comme pour le REDUCE, tu fais non seulement un BYCOL mais aussi un BYLIGNE. Donc il faut passer par une SEQUENCE pour récupérer la valeur dans NB. Je te met ci-après la solution "simple" = si NB était constant, puis une solution pour récupérer l'index du NB (abandonné).

=LET(
_thunk;LAMBDA(x;LAMBDA(x));
_tbl;Tableau1;_nb;E2;

_com1; "chaque résultat de BYCOL (=3 lignes) est stocké dans un Thunk.";
_com2; "donc _thunkRes contient une array (horizontale) de thunks (verticaux)";
_thunkRes;BYCOL(_tbl;LAMBDA(_c;_thunk(_c*_nb)));

_com3; "ce n'est pas necessaire ici car toujours=3, mais on peut calculer le nombre de lignes";
_com4; "en calculant le MAX des ROWS de chaque Thunk. Pour cela SCAN est très bien (VSTACK naturel)";
_rows;MAX(SCAN(0;_thunkRes;LAMBDA(a;v;ROWS(v()))));

_com5; "on reconstruit la matrice des résultats en utilisant INDEX deux fois:";
_com6; "1x pour récup la colonne, et 1x pour la ligne. Note les () pour évaluer le thunk=lambda";
_out;MAKEARRAY(COLUMNS(_thunkRes); _rows;LAMBDA(r;c; INDEX(INDEX(_thunkRes;c)();r)));

_out)

EDIT : c'est trop galère d'utiliser BYCOL avec les 3 NB, comme l'a dit raccourcix travailler directement avec les indices est juste + pratique.

Pour info les 2 solutions ci-dessus sont assez lourdes car elles demandent beaucoup de parcours des tableaux. De plus comme REDUCE a besoin de chaque résultat précédent pour construire la solution, on perd en efficacité (il y a surement des optimisations internes mais c'est comme si on forcait le mono-threading alors que ce sont des calculs qui pourraient être faits en parallèle).

RE,

Je prends note de vos réponses et regarderai tout ça ce week-end !

Merci Stéphane d'avoir raccourcix ma proposition

EDIT :

@Saboh : c'est bien ce que je souhaitais avec BYCOL ! j'étais presque sûr qu'on pouvait faire quelque chose de ce type, imbriqué avec REDUCE.

@Raccourcix : merci pour l'option MAKEARRAY.

Sujet résolu, merci pour vos participations

Rechercher des sujets similaires à "multiplier matrice ligne bycol"