Synthèse requête BDD : recherche des dominantes multiples

From: Guillaume OLLIVIER (ollivier@iac.nc)
Date: Wed Mar 20 2002 - 22:26:22 MET

  • Next message: Yorick REYJOL: "COMMENT FAIRE DES ACC SANS .ivfa (SUITE)"

    Bonjour et merci à tous ceux qui ont répondu à la question posée :

    >>Je travaille sur un tableau de données de recouvrement avec les sp en
    >colonne et les relevés (faciès de végétation) en ligne, soit
    >
    > spA | SpB| ...|Spn
    >FaciesA 0.01 | 0 | ...| 0.2
    >FaciesB 0 | 0.5 | ... | 0
    >.... ... | ... | ... | ...
    >FaciesN 0.5 | 0.01|...| 0
    >
    >J'aimerai pouvoir connaitre pour chaque faciès l'espèce la plus
    >abondante (voire les 3 premières) de manière automatique et que le code de
    >cette ou ces espèces apparaissent dans la ligne
    >correspondant au faciès, soit :
    >
    > Sp la plus abondante
    >FaciesA Spn
    >FaciesB SpB
    >...
    >FaciesN SpA
    >
    >Une telle requête est elle possible sous Access et avec quelle démarche ?
    Et
    >avec Excell ?? d'autres outils ???
    >Faut il passer par du VB ...?

    VOICI LA SOLUTION QUE J'AI MISE EN OEUVRE (SIMPLICITE, PAS DE
    PROGRAMMATION...) :

    >Claude MONTEIL
    Sous Excel, les fonctions GRANDE.VALEUR, EQUIV et INDEX peuvent apporter une
    reponse :

    1/ calcul de la valeur la plus grande pour une ligne :
    =GRANDE.VALEUR($B2:$Z2;1)
    renvoie la valeur la plus grande de la ligne courante pour les colonnes B a
    Z

    2/ calcul de la position de cette valeur (indice) :
    =EQUIV($AA2;$B2:$Z2;0)
    renvoie la position de la valeur en colonne AA (valeur calculee en 1/)
    au sein de la plage s'étendant sur les colonnes B a Z de la ligne courante

    3/ calcul du nom de l'espece correspondante :
    =INDEX($B$1:$Z$1;$AB2)
    renvoie l'element de position indiquee dans le second parametre (valeur
    calculee en 2/)
    au sein de la plage specifiee comme 1er parametre (la liste des noms est
    supposee etre sur la 1ere ligne (colonnes B a Z).

    Le cas echeant, on peut chainer ces 3 calculs au sein d'une seule et meme
    formule :
    =INDEX($B$1:$Z$1;EQUIV(GRANDE.VALEUR($B2:$Z2;1);$B2:$Z2;0)) (ouf:-)

    Ces formules peuvent cependant etre plus lisibles si on prend soin de nommer
    les plages utilisees, celle de la premiere ligne avec un nom absolu (ex. :
    ListeNoms = $B$1:$Z$1), et celle de la ligne courante avec un nom relatif
    (ex. : LigneCourante = $B$2:$Z$2, a supposer qu'on definisse ce nom a partir
    de la 2eme ligne) :
    =INDEX(ListeNoms;EQUIV(GRANDE.VALEUR(LigneCourante;1);LigneCourante;0))
    (ouf:-)

    A noter que :
    - il y a un ecueil si une valeur apparait PLUSIEURS FOIS, auquel cas on ne
    recuperera la position (et le nom d'espece) que de la 1ere d'entre elles ...
    - le second parametre de la fonction GRANDE.VALEUR permet d'atteindre la
    seconde plus grande valeur de la plage (et ainsi de suite)

    >>>RESTE A SAVOIR SI LA SUITE DE FONCTION NE PEUT PAS ETRE AMELIOREE POUR
    AFFICHER LES ESPECES CO-DOMINANTES ????
    ______________

    Les tableaux croisés ne semblent pas être la solution, il ne s'agit pas non
    plus d'un regroupement simple sous un SGDB (cf retourner un nom de colonne
    dans un enregistrement) au moins en l'état de la structure de table
    (restructuration souvent proposée :
    Facies | sp | relevé
    A | A | 0.01
    A | B | 0
    A | n | 0.2
    B | A | 0
    mais difficile à mettre en oeuvre avec une table de 350x350)

    AUTRES SOLUTIONS PROPOSEES MAIS NON TESTEES :

    >>Daniel Chessel (Liste ADE) :
    On peut faire ce que veut Guillaume OLLIVIER dans R :
    <http://www.r-project.org/>
    avec une toute petite fonction :

    fp_function(X) {
    fun_function(x) {
    x_unlist(x)
    x1_which(x==max(x))[1]
    x[x1]_-999
    x2_which(x==max(x))[1]
    x[x2]_-999
    x3_which(x==max(x))[1]
    return(names(X)[c(x1,x2,x3)])
    }
    z_t(apply(X,1,fun))
    z_data.frame(z)
    names(z)_c("Esp1","Esp2","Esp3")
    return(z)
    }

    Un tableau de données :
    > X
    Eda Bsp Brh Bni Bpu Cen Ecd Rhi Hla Hab Par Cae Eig
    sp_1 4 7 10 9 0 0 0 5 9 0 4 0 0
    sp_2 0 0 8 0 0 0 0 0 4 0 0 0 0
    sp_3 0 5 5 0 0 0 0 2 5 0 0 0 0
    sp_4 0 3 6 0 0 0 0 3 6 0 0 0 0
    sp_5 0 5 6 0 0 0 5 0 4 0 0 0 4
    su_1 6 7 10 0 10 0 0 2 7 0 0 0 2
    su_2 0 0 9 0 0 0 0 0 0 0 0 0 0
    su_3 0 6 8 0 0 2 0 0 0 0 0 0 0
    su_4 0 7 11 0 0 2 0 0 2 0 0 5 5
    su_5 0 6 9 2 3 0 4 0 0 0 0 2 7
    au_1 4 5 8 0 9 6 0 5 9 0 7 0 0
    au_2 0 0 1 0 0 0 0 0 0 0 0 0 0
    au_3 0 9 10 0 0 0 0 0 4 0 3 0 0
    au_4 0 10 13 0 0 3 0 5 5 1 4 2 4
    au_5 2 10 12 0 4 0 8 4 4 2 5 1 6
    wi_1 3 6 7 0 6 7 0 4 8 0 4 0 0
    wi_2 0 3 6 0 0 5 0 4 3 0 1 0 0
    wi_3 0 0 3 0 0 1 0 1 0 0 0 0 0
    wi_4 0 6 10 0 0 5 1 3 5 0 2 0 0
    wi_5 1 9 11 0 3 6 8 3 5 2 5 0 0

    Le résultat :

    > fp(X)
    Esp1 Esp2 Esp3
    sp_1 Brh Bni Hla
    sp_2 Brh Hla Eda
    sp_3 Bsp Brh Hla
    sp_4 Brh Hla Bsp
    sp_5 Brh Bsp Ecd
    su_1 Brh Bpu Bsp
    su_2 Brh Eda Bsp
    su_3 Brh Bsp Cen
    su_4 Brh Bsp Cae
    su_5 Brh Eig Bsp
    au_1 Bpu Hla Brh
    au_2 Brh Eda Bsp
    au_3 Brh Bsp Hla
    au_4 Brh Bsp Rhi
    au_5 Brh Bsp Ecd
    wi_1 Hla Brh Cen
    wi_2 Brh Cen Rhi
    wi_3 Brh Cen Rhi
    wi_4 Brh Bsp Cen
    wi_5 Brh Bsp Ecd

    ___________________
    >Agustin Lobo :
    In R, given a data matrix x:

    > x
    s1 s2 s3 s4 s5 s6 s7 s8 s9 s10
    F1 119 164 151 64 176 146 157 133 167 150
    F2 89 85 136 83 107 104 94 124 106 85
    F3 113 82 113 75 92 63 42 87 74 94
    F4 198 186 194 192 189 173 197 186 195 182

    you would do just:
    >
    data.frame(dom.sps=dimnames(x)[[2]][apply(x,1,which.max)],abndce=apply(x,1,m
    ax))

    dom.sps abndce
    F1 s5 176
    F2 s3 136
    F3 s1 113
    F4 s1 198
    _____________

    >Luis Tito

    Une solution très simple consiste à utiliser les fonctions d'excel :

    fac spA spB spN Numligne max equiv decaler
    FA 0,01 0 0,2 1 0,2 3 spN
    FB 0 0,5 0 2 0,5 2 spB
    FN 0,5 0,01 0 3 0,5 1 spA

    Dans la colonne Numligne je tape seulement le "1" puis je fais une
    recopie incrémentée jusqu'à la ligne N

    Dans la colonne max je tape la formule "=max(b2:d2)" puis je fais une
    recopie incrémentée jusqu'à la ligne N

    Dans la colonne "equiv" je tape la formule "=equiv(f2;b2:d2;0)" puis je
    fais une recopie incrémentée jusqu'à la ligne N. "f2" est la cellule où
    se trouve le max de la ligne, "b2:d2" est la ligne de la plage de
    données, "0" est un code pour indiquer qu'il s'agit de valeurs
    numériques.

    Dans la colonne "decaler" je tape la formule "=decaler(a2;-e2;g2)" puis
    je fais une recopie incrémentée jusqu'à la ligne N. "a2" est la première
    cellule de la ligne, "e2" est la cellule où se trouve le numéro de ligne,
    "g2" est la cellule où se trouve le maximum de la ligne.

    Bien entendu, je fais un "couper" "collage spécial - valeurs" du contenu
    de la dernière colonne pour avoir les valeurs et non plus les formules
    dans les cellules.

    Problème : cela ne gère pas les ex-aequo et cela ne donne que le max et
    pas les trois les plus abondantes. Mais cela a le mérite de la
    simplicité, surtout si l'on ne connait pas ou que l'on n'a pas "R".

    J'espère que cela peut aider

    Luis Tito



    This archive was generated by hypermail 2b30 : Wed Mar 20 2002 - 22:34:17 MET