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

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


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 : Fri Feb 14 2003 - 14:36:09 MET