PnX-SI / GeoNature

Application de saisie et de synthèse des observations faune et flore
GNU General Public License v3.0
100 stars 102 forks source link

Suppression de doublons dans GeoNature grâce à la signature d'une donnée #1324

Closed Adrien-Pajot closed 3 years ago

Adrien-Pajot commented 3 years ago

Avec la multiplication des échanges de données, le nombre de doublons dans chaque instance GeoNature risque d'augmenter. Une solution simple pour observer les doublons semble être la génération d'une signature pour chaque donnée contenant ses caractéristiques.

Voici un exemple

create materialized view doublons_vm as
select concat(replace(concat(cast(date_min as date)), '-', ''), replace(st_x(the_geom_4326)::text, '.',''), 
replace(st_y(the_geom_4326)::text, '.',''), cd_nom) as signature, unique_id_sinp
from gn_synthese.synthese s
where geometrytype(the_geom_4326)='POINT'
order by signature

Ensuite, on compte le nombre d'uuid par signature pour savoir s'il existe des doublons.

create or replace view nb_doublon_par_signature as 
SELECT   signature, COUNT(unique_id_sinp) AS nbr_doublon
FROM     doublons_vm
GROUP BY signature
HAVING   COUNT(unique_id_sinp) > 2

On peut compter combien il y en a

select sum(nbr_doublon)-count(nbr_doublon) from nb_doublon_par_signature

Nous avons testé cette solution sur la base des écrins, 14000 doublons trouvés pour 1 400 000 données. (1/1000 quoi).

Il nous reste plus qu'à les éliminer (source et synthèse) en gardant pour chaque signature seulement le premier id_synthèse généré.

Pour ça on peut s'appuyer sur https://github.com/PnX-SI/Ressources-techniques/blob/master/GeoNature/V2/delete-from-source-synthese.sql

Je vais proposer une PR.

vprunet commented 3 years ago

Les doublons ... Quel cauchemar! Bravo pour l'effort. Nous en avons bien besoin.

Chez nous (PNM), ta requête pourrait poser deux problèmes:

Pour aller plus loin, en général le nom des observateurs est grosso modo conservé, mais toujours selon le cheminement de la donnée, l'ordre des observateurs, l'ordre nom prénom, l'écriture en majuscule ou minuscule, peuvent varier. On recherche donc plus une similarité dans le texte qu'une égalité stricte.

Enfin, pourquoi n'utilises-tu pas le cd_nom et/ou le nom cité?

Adrien-Pajot commented 3 years ago

Concernant les deux problèmes : 1/ Est-ce que les observations saisies sont réellement au même endroit et se ressemblent en tout point ? 2/ Si les coordonées varient de quelques décimales alors ceci n'est pas traité en effet, je prends seulement les données strictement identiques. Toutefois, le SINP, le GBIF et à des échelles plus locales le PN des Cévennes travaillent sur des algo de distance entre données permettant de traiter ces problématiques.

Je n'utilise pas l'observateur ici pour les doublons de données, est-ce quelque chose qu'on doit essayer d'inclure ? Avec en effet cette synomymie de champ ?

J'utilise bien sûr le cd_nom en tant que dernier paramètre du concat :

concat(replace(concat(cast(date_min as date)), '-', ''), replace(st_x(the_geom_4326)::text, '.',''), 
replace(st_y(the_geom_4326)::text, '.',''), cd_nom)
DonovanMaillard commented 3 years ago

pou info : de mon coté il faudra que je m'y penche aussi, je pensais appliquer une zone tampon en effet de quelques mètres. A noter que certains "doublons" sont voulus par les observateurs à quelques mètres près, donc je prévoyais un tampon d'1m ou 2 uniquement pour traiter les arrondis / conversions de projections au fil ds flux entre outils.

Dans l'immédiat, les doublons ne changent pas la répartition des espèces, pas la phénologie, pas la validité des données, pas le statut des espèces... bref les infomations qu'on utilise réellement avec des données d'occurrences non protocolées ne sont généralement pas très impactées par les doublons, et les données de synthèse agglomérées sont, par nature, fragiles pour les stats...

Adrien-Pajot commented 3 years ago

Cette histoire de zone tampon fait pas mal l'objet de discussions ici aussi. On essaie d'éviter de supprimer des données très proches donc pour l'instant faut voir ce qu'on en retire.

L'idée de cette première série de suppression est d'enlever l'information "inutile" qui pourrait avoir un impact sur la robustesse de profils d'espèces par exemple ou de modèles qui utiliseraient le nombre de données et pas seulement l'occurence.

Par exemple une donnée était doublée 42 fois ici. Admettons que ce taxon n'est que 50 observations....

vprunet commented 3 years ago

Oups, je n'avais pas vu le cd_nom dans la requête, désolé.

Concernant le problème des coordonnées (on rate beaucoup de doublons si on ne le considère pas) pourquoi ne pas utiliser ST_SnapToGrid pour recaler les coordonnées sur une grille?

select ST_SnapToGrid( the_geom_local, 0,0, 2, 2), the_geom_local from gn_synthese.synthese s 
where st_geometrytype(the_geom_local) = 'ST_Point'

recale sur des points tous les 2 m.

En cas de doublon, il faut aussi savoir lequel supprimer, tous n'ont pas le même niveau de détail dans la description (encore une fois lié au cheminement de la donnée).

Les données de partenaires arrivent parfois sans uuid SINP. Il suffit de remplacer unique_id_sinp par id_synthese dans la première requête pour lister tous les doublons.

Concernant les observateurs, c'est un bon critère pour repérer un jeu de données qui est arrivé par deux circuits différents. Mais ne sachant pas évaluer la similarité de deux chaines de caractères (merci si quelqu'un a une fonction magique qui fait cela), je fais cela à la main en requérant les jeux de données et dates de participation d'un observateur '%foo%'. Cela me donne une piste pour une analyse plus détaillée. C'est très fastidieux.

Adrien-Pajot commented 3 years ago

Pourquoi pas le snaptogrid ! Et on passe en fichier de conf la dimension de la grille en mètre ?

"En cas de doublon, il faut aussi savoir lequel supprimer, tous n'ont pas le même niveau de détail dans la description (encore une fois lié au cheminement de la donnée)."

Quel niveau de détail nous intéresse ici à garder qui serait différent entre deux doublons stricts ?

Enfin concernant les observateurs, est-ce important de conserver des données similaires avec deux observateurs différents ? Si c'est le cas alors il suffit de rajouter l'observateur dans le concat ?

vprunet commented 3 years ago

Quel niveau de détail nous intéresse ici à garder qui serait différent entre deux doublons stricts ?

Certains des attributs (nidification, sexe, etc) ne sont pas reportés sur tous les doublons. On peut envisager de hiérarchiser les sources (celles qui fournissent un uuid passant avant les autres).

Enfin concernant les observateurs, est-ce important de conserver des données similaires avec deux observateurs différents ? Si c'est le cas alors il suffit de rajouter l'observateur dans le concat ?

Lorsque deux observations ont la même signature, on a de fortes chances de retrouver les mêmes observateurs. La question est : est-ce qu'on considère que c'est le cas ou est-ce qu'on essaie de vérifier cela? Je pense que ce serait compliqué d'ajouter le ou les observateurs dans le concat, car la représentation de cet attribut varie selon les sources. Par contre, comparer a posteriori les observateurs de doublons potentiels (avant d'en supprimer un) doit être faisable (en tout cas, c'est immédiat pour l'oeil et le cerveau humain).

DonovanMaillard commented 3 years ago

Sur le dernier point, les outils lpo dupliquent les donnees autant de fois qu'il y a d'observateurs et chaque ligne ne comporte que l'un des membres du groupe en guise d'observateur. Mieux vaut en tenir compte car sinon 9n garde aléatoirement une donnée avec l'un des observateurs en supprimant tous les autres.

Adrien-Pajot commented 3 years ago

Certains des attributs (nidification, sexe, etc) ne sont pas reportés sur tous les doublons. On peut envisager de hiérarchiser les sources (celles qui fournissent un uuid passant avant les autres).

Il serait donc intéresser de mesurer la quantité d'information fournie. Cependant, est-ce qu'on considère comme doublon de données qui ne contiennnent pas la même information ?

Les cas qui peuvent arriver sont notamment l'évolution d'une donnée, et normalement, des paramètres comme la date de mise à jour seront pris en compte.

De fait, on peut chercher les doublons réels (strictement identiques) pour le moment et imaginer des évolutions par la suite qui prennent notamment en compte les données proches (on revient sur les histoires de distances du GBIF : https://www.gbif.org/fr/news/4U1dz8LygQvqIywiRIRpAU/new-data-clustering-feature-aims-to-improve-data-quality-and-reveal-cross-dataset-connections)

Adrien-Pajot commented 3 years ago

Selon vous, cette signature doit-elle être à terme générée lors de la création d'une donnée? (et la modification de celle-ci ?) ou recalculée et rafraîchie à part ?

jbrieuclp commented 3 years ago

Ca me semble moins évident de générer un doublon lors de la saisie d'une donnée que lors de l'import de lots de données. N'étant pas très fan de l'usage à tout va des triggers, j'opte pour une génération à la volé réalisée lors de la recherche des doublons.

Idée au passage pour comparer 2 chaines de texte (=observateurs), il est faisable de convertir une chaine en tableau de caractères et de comparer les 2 tableaux en couplant à un test sur la longueur des 2 textes de base il y a moyen d'avoir des résultats intéressant. Niveau qualité de résultat et performance il y a surement mieux, mais c'est une piste.

amandine-sahl commented 3 years ago

Pour comparer des chaines de caractères on peut utiliser différentes techniques (dont soundex, distance de Levenshtein) présentées dans le lien suivant : https://blog.crunchydata.com/blog/fuzzy-name-matching-in-postgresql Même si il y a toujours des risques de faux positifs.

jpm-cbna commented 3 years ago

Une technique aussi qui marche pas mal sur les noms latins est d'utiliser un algorithme tel que soundex mais sur une chaine de caractère inversée (en partant de la fin).

Adrien-Pajot commented 3 years ago

Merci pour ces commentaires. En l'occurence si j'utilise soundex ou équivalent ça sera au moment de la comparaison des noms d'observateurs pour garder le moins de doublons possible. Les espèces sont gérées avec les cd_nom dans la signature et non les noms latins.

camillemonchicourt commented 3 years ago

Script d'identification des doublons intégré dans la 2.7.0