Bouts de code pour Grass🔗

Posted by Médéric Ribreux 🗓 In kb/ snippets/

#grass #gis

  1. Faire une pseudo-jointure avec Grass avec des tables DBF

Faire une pseudo-jointure avec Grass avec des tables DBF

Voici le topo: vous avez importé des données vecteur dans Grass. Ces données contiennent en plus d'autres données attributaires. Nativement, lors de l'import de la couche, Grass sépare bien les deux types d'information (exemple avec une couche nommée : COMMUNES.SHP):

Notre problème est le suivant: nous souhaitons ajouter des données attributaires dans la table COMMUNES.DBF de la manière la plus simple possible. Si c'est une opération qui peut sembler triviale, elle ne l'est pas nécéssairement: Grass ne sait pas gérer les jointures dynamiques (v.db.join) avec des tables DBF ! C'est également le cas pour les requêtes croisées (UPDATE table SET champ=(SELECT …)).

Nous devons donc ruser et contourner cette limite en ajoutant les colonnes qui nous intéressent dans la table COMMUNES.DBF, le tout, en utilisant les fonctions de GRASS. L'astuce consiste à utiliser le format SQLite en entrée pour réaliser nos opérations de requêtes puis d'exporter le résultat dans une table DBF.

Voyons le détail des opérations:

db.connect driver=sqlite database=temp_db.sqlite 
v.in.ogr "dsn=/home/user/GRASS_import/COMMUNES.shp" output=COMMUNES snap=-1 min_area=0.0001 -o
# v.db.connect -p permet d'afficher la liste des tables attributaires connectées à une couche vecteur :
v.db.connect -p COMMUNES
Vector map <COMMUNES@PERMANENT> is connected by:
layer <1> table <COMMUNES> in database </home/user/GRASS/DEP49/PERMANENT/dbf/> through driver<dbf> with key <cat>

# db.tables permet de liste les tables attributaires disponibles, indépendamment de leur connexion à une couche vecteur:
db.tables -p
COMMUNES

# Pour voir la structure d'une table, on utilise db.columns ou db.describe:
db.columns table=COMMUNES
cat
NOM_COM
INSEE_COM
STATUT
SUPERFICIE
POPULATION
INSEE_CANT
INSEE_ARR
ID_OBJ

db.describe -c table=COMMUNES
ncols: 9
nrows: 363
Column 1: cat:INTEGER:11
Column 2: NOM_COM:CHARACTER:50
Column 3: INSEE_COM:CHARACTER:5
Column 4: STATUT:CHARACTER:20
Column 5: SUPERFICIE:INTEGER:11
Column 6: POPULATION:INTEGER:11
Column 7: INSEE_CANT:CHARACTER:2
Column 8: INSEE_ARR:CHARACTER:1
Column 9: ID_OBJ:INTEGER:11
v.in.ogr "dsn=/home/user/tmp/GRASS_import/DATA.csv" output=DATA snap=-1 min_area=0.0001 -o
db.describe -c table=DATA
ncols: 6
nrows: 6
Column 1: cat:INTEGER:11
Column 2: value:INTEGER:11
Column 3: Mini:DOUBLE PRECISION:20
Column 4: Maxi:DOUBLE PRECISION:20
Column 5: Nume:INTEGER:11
Column 6: Producteur:CHARACTER:25
db.dropcol -f table=DATA column=cat
echo "CREATE TABLE COM_JOINTE AS SELECT COMMUNES.*, DATA.* FROM COMMUNES JOIN DATA ON DATA.value=COMMUNES.ID_OBJ" | db.execute
db.copy to_driver=dbf to_database=/home/user/GRASS/DEP49/PERMANENT/dbf/ to_table=COMMUNES from_driver=sqlite from_database=temp_db.sqlite from_table=COM_JOINTE
# Actuellement, notre couche COMMUNES utilise la table attributaire COMMUNES située dans une base de données SQLite:
v.db.connect -p map=COMMUNES
Vector map <COMMUNES@PERMANENT> is connected by:
layer <1> table <COMMUNES> in database <temp_db.sqlite> through driver <sqlite> with key <cat>
# On doit reconnecter la table géographique COMMUNES avec la table attributaire DBF COMMUNES:
v.db.connect -o map=COMMUNES driver=dbf database=/home/user/GRASS/DEP49/PERMANENT/dbf/ table=COMMUNES key=cat
# On supprime les tables qui ne servent plus à rien
db.droptable -f DATA
db.droptable -f COMMUNES

# Enfin, on indique qu'on souhaite se connecter en utilisant le pilote DBF par défaut pour que les prochains imports se fasse dans ce format
db.connect driver=dbf database=/home/user/GRASS/DEP49/PERMANENT/dbf/