Bouts de code pour Grass 🔗

Posted by MĂ©dĂ©ric Ribreux 🗓 In kb/snippets/

#GIS #grass

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/