opendatasicilia / tansignari

"T'ansignari e t'appeddiri"
http://tansignari.opendatasicilia.it
Creative Commons Attribution 4.0 International
18 stars 10 forks source link

[script] estrarre le chiavi e i valori utilizzate di un dominio di campo #239

Closed pigreco closed 1 year ago

pigreco commented 1 year ago

(@aborruso ci sto studiando) I domini di campo possono essere caratterizzati da 'n' record, ma spesso non sono tutti utilizzati, esempio: il dominio che segue

k v
01 aree percorse da incendi
02 tagliate
03 rimboschimenti e nuovi impianti
04 viali tagliafuoco
95 altro
91 Non conosciuto
93 Non definito
94 Non applicabile

ha 8 record, ma quanti di questi sono stati utilizzati nel database ?

Con ogr2ogr è possibile "risolvere" i domini usando il seguente costrutto:

ogr2ogr -f "CSV" "D:\GitHub\ESRI_FileGeodatabase_GDAL\dati\DBGT_10K_22_V01.gdb" -resolveDomains

ottenendo una tabella simile a quella di sotto:

image

in pratica i campi con dominio vengono esplosi in due colonne:

  1. la colonna associata al dominio visualizza la chiave;
  2. la colonna nomeCampo_resolved visualizza la decodifica ovvero il valore;

il mio obiettivo è ottenere i domini di campo con i reali record utilizzati.

Un possibile workaraund è il seguente:

  1. risolvere i domini di campo (ottenendo tutte le tabelle del database in csv);
  2. per ogni file csv, e per ogni campo con dominio, estrarre la lista dei valori univoci (per esempio solo le chiavi);
  3. ricostruire i domini con le chiavi estratte e aggiungere il relativo campo valore.

ma come farlo con uno script?

aborruso commented 1 year ago

il mio obiettivo è ottenere i domini di campo con i reali record utilizzati.

@pigreco non ho capito qual è il tuo obiettivo. Puoi mettere un output di esempio?

pigreco commented 1 year ago

Il database di riferimento pesa oltre 5 GB, quindi allego solo alcuni file csv resolved su cui costruire lo script.

Sotto un esempio su un file csv GZ_FER_GZ_FER_TY.csv: image

sotto il dominio completo, con tutti i record: image

sotto la lista dei valori univoci del campo GZ_FER_TY

image

quindi l'output dello script dovrebbe restituire:

un file csv (GZ_FER_TY_resolved) con il nome del dominio e con la lista dei valori univoci, come lo screenshot di sopra.

esempio.zip

NB: un file csv può avere più domini collegati a più campi.

aborruso commented 1 year ago

@pigreco non mi odiare, non ho capito cosa vuoi in output :(

Dato uno dei file di esempio che hai inserito - ad esempio GALLER_GALLER_USO - cosa vorresti in output per quel file (da replicare poi per tutti)?

Non mi parlare di dominio, ecc, parlami dei nomi dei campi che hai nel file di input e come usarli/trasformarli in output.

Grazie

pigreco commented 1 year ago

Dato uno dei file di esempio che hai inserito - ad esempio GALLER_GALLER_USO - cosa vorresti in output per quel file (da replicare poi per tutti)?

questo l'output che mi aspetterei:

GALLER_USO 02 03 04

da replicare poi per tutti i file condivisi

aborruso commented 1 year ago

Ciao @pigreco , ho fatto un output diverso (vedi sotto).

Se vuoi il singolo file, esattamente come la tua proposta, dimmelo.

Metto il codice non appena mi dici se va bene un solo file, o uno per ogni file.

Se ne vuoi uno per ogni file, come gestisco il caso DIGA, che sembra avere due coppie di colonne chiave, valore.

image

id campo file
10 AF_ACQ_NOM_LINGUA AF_ACQ_AF_ACQ_NOM_T
91 ARGN_CLASS ARGINE
Non conosciuto ARGN_CLASS ARGINE
01 ARGN_TY ARGINE
05 ARGN_TY ARGINE
10 COMUNE_NOM_LINGUA COMUNE_COMUNE_NOM_T
10 CS_MAR_LIN_CS_MAR_NOM_LINGUA CS_MAR_CS_MAR_LIN_CS_MAR_NOM_T
02 DIGA_CLASS DIGA
91 DIGA_CLASS DIGA
01 DIGA_TY DIGA
02 DIGA_TY DIGA
10 GALLER_NOM_LINGUA GALLER_GALLER_NOM_T
02 GALLER_USO GALLER_GALLER_USO
03 GALLER_USO GALLER_GALLER_USO
04 GALLER_USO GALLER_GALLER_USO
01 GZ_FER_TY GZ_FER_GZ_FER_TY
02 GZ_FER_TY GZ_FER_GZ_FER_TY
03 GZ_FER_TY GZ_FER_GZ_FER_TY
04 GZ_FER_TY GZ_FER_GZ_FER_TY
10 INVASO_NOM_LINGUA INVASO_INVASO_NOM_T
01 ND_AAC_TY ND_AAC_ND_AAC_TY
03 ND_AAC_TY ND_AAC_ND_AAC_TY
04 ND_AAC_TY ND_AAC_ND_AAC_TY
06 ND_AAC_TY ND_AAC_ND_AAC_TY
10 ND_AAC_TY ND_AAC_ND_AAC_TY
95 ND_AAC_TY ND_AAC_ND_AAC_TY
01 ND_SAC_TY ND_SAC_ND_SAC_TY
02 OP_REG_TY OP_REG
07 OP_REG_TY OP_REG
10 PE_UINS_NM_LINGUA PE_UINS_PE_UINS_NM_T
04 PE_UINS_TY PE_UINS_PE_UINS_TY
06 PE_UINS_TY PE_UINS_PE_UINS_TY
10 PE_UINS_TY PE_UINS_PE_UINS_TY
11 PE_UINS_TY PE_UINS_PE_UINS_TY
12 PE_UINS_TY PE_UINS_PE_UINS_TY
95 PE_UINS_TY PE_UINS_PE_UINS_TY
0301 PE_UINS_TY PE_UINS_PE_UINS_TY
0302 PE_UINS_TY PE_UINS_PE_UINS_TY
0303 PE_UINS_TY PE_UINS_PE_UINS_TY
0601 PE_UINS_TY PE_UINS_PE_UINS_TY
0602 PE_UINS_TY PE_UINS_PE_UINS_TY
0603 PE_UINS_TY PE_UINS_PE_UINS_TY
0604 PE_UINS_TY PE_UINS_PE_UINS_TY
0608 PE_UINS_TY PE_UINS_PE_UINS_TY
0611 PE_UINS_TY PE_UINS_PE_UINS_TY
1003 PE_UINS_TY PE_UINS_PE_UINS_TY
1006 PE_UINS_TY PE_UINS_PE_UINS_TY
1201 PE_UINS_TY PE_UINS_PE_UINS_TY
01 PONTE_MAT PONTE_PONTE_MAT
02 PONTE_MAT PONTE_PONTE_MAT
03 PONTE_MAT PONTE_PONTE_MAT
10 PONTE_NOME_LINGUA PONTE_PONTE_NOME_T
02 PONTE_USO PONTE_PONTE_SEDE_PONTE_USO
03 PONTE_USO PONTE_PONTE_SEDE_PONTE_USO
04 PONTE_USO PONTE_PONTE_SEDE_PONTE_USO
05 PONTE_USO PONTE_PONTE_SEDE_PONTE_USO
06 PONTE_USO PONTE_PONTE_SEDE_PONTE_USO
pigreco commented 1 year ago

@aborruso ottima idea creare unico file, ma come faresti se ci fossero più coppie chiave valore nello stesso file?

per singolo file immaginerei così:

DIGA _CLASS DIGA_TY
01 02
02 04
03 07
10

ma va bene singolo file se facilmente comprensibile (SICURAMENTE farai l'append e mi sta bene)

NB: ci sono casi (ma non li ho condivisi) con 4 campi con domini, quindi 4 coppie di chiave valore nello stesso file)

aborruso commented 1 year ago

Se guardi il mio file, ho messo anche il nome campo e quindi distingui i due valori "02".

Mi sono spiegato?


Scusami per la brevità, ti sto scrivendo dal cellulare.

website: https://medium.com/tantotanto 38° 7' 48" N, 13° 21' 9" E EPSG:4326

Il sab 28 gen 2023, 15:08 Salvatore Fiandaca @.***> ha scritto:

@aborruso https://github.com/aborruso ottima idea creare unico file, ma come faresti se ci fossero più coppie chiave valore nello stesso file?

per singolo file immaginerei così: DIGA _CLASS DIGA_TY 01 02 02 04 03 07 10

— Reply to this email directly, view it on GitHub https://github.com/opendatasicilia/tansignari/issues/239#issuecomment-1407406754, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAHPDZ35LLO7YG2KJ7JN4TWUUR7RANCNFSM6AAAAAAUJAJCLY . You are receiving this because you were mentioned.Message ID: @.***>

pigreco commented 1 year ago

Mi sono spiegato?

sì, ottimo! per me va bene unico file, per come hai fatto sopra. grazie

aborruso commented 1 year ago

Ciao totò, ecco il codice.

Ho messo un po' di commenti.

Fammi sapere

#!/bin/bash

set -x
set -e
set -u
set -o pipefail

# NOTA BENE: uso Miller 6

# crea cartella di output
mkdir -p ./output

# if file exists, delete it
if [ -f ./output/toto.jsonl ]; then
  rm ./output/toto.jsonl
fi

# per ogni CSV
for i in ./*.csv; do
  # estrai nome
  filename=$(basename "$i" .csv)
  # estrai prima riga e per ogni coppia chiave-valore, se la chiave termina con "resolved", estrai il nome campo
  mlr --c2n head -n 1 then put -q 'for (k,v in $*) { if (k =~ "^.+resolved$") {print k}}' ${i} | while IFS= read -r line; do
    # rimuovi "_resolved" dal nome campo
    field=$(echo "$line" | sed 's/_resolved//')
    # e per ogni campo estratto, estrai da ogni CSV corrispondente i valori univoci del campo e aggiungi a output nome file e nome campo; il tutto in formato JSONL
    mlr --icsv --ojsonl cut -f "$field" then uniq -a then label id then put '$campo="'"$field"'";$file="'"$filename"'"' ${i} >>./output/toto.jsonl
  done
done

mlr --j2c sort -f campo -t id ./output/toto.jsonl >./output/toto.csv
pigreco commented 1 year ago

@aborruso l'unico file è una ottima soluzione: image

ma ti chiedo se fosse possibile (in modo agile per te, altrimenti non importa) aggiungere anche il valore della chiave.

id valore campo file
10 pippo AF_ACQ_NOM_LINGUA AF_ACQ_AF_ACQ_NOM_T
91 pluto ARGN_CLASS ARGINE
01 andrea ARGN_TY ARGINE
05 toto ARGN_TY ARGINE

grazie

aborruso commented 1 year ago

@pigreco, se non è essenziale mi fermo qui.

Del resto, potresti provare tu adesso :)

pigreco commented 1 year ago

Del resto, potresti provare tu adesso :)

output in due file:

#!/bin/bash

set -x
set -e
set -u
set -o pipefail

# NOTA BENE: uso Miller 6

# crea cartella di output
mkdir -p ./output

# if file exists, delete it
if [ -f ./output/toto.jsonl ]; then
  rm ./output/toto.jsonl ./output/totov.jsonl
fi

# per ogni CSV
for i in ./*.csv; do
  # estrai nome
  filename=$(basename "$i" .csv)
  # estrai prima riga e per ogni coppia chiave-valore, se la chiave termina con "resolved", estrai il nome campo
  mlr --c2n head -n 1 then put -q 'for (k,v in $*) { if (k =~ "^.+resolved$") {print k}}' ${i} | while IFS= read -r line; do
    # rimuovi "_resolved" dal nome campo
    field=$(echo "$line" | sed 's/_resolved//')
    fieldv=$(echo "$line")
    # e per ogni campo estratto, estrai da ogni CSV corrispondente i valori univoci del campo e aggiungi a output nome file e nome campo; il tutto in formato JSONL
    mlr --icsv --ojsonl cut -f "$field" then uniq -a then label id then put '$campo="'"$field"'";$file="'"$filename"'"' ${i} >>./output/toto.jsonl
    mlr --icsv --ojsonl cut -f "$fieldv" then uniq -a then label idv then put '$campov="'"$fieldv"'";$file="'"$filename"'"' ${i} >>./output/totov.jsonl
  done
done

mlr --j2c sort -f campo -t id ./output/toto.jsonl >./output/toto.csv
mlr --j2c sort -f campov -t idv ./output/totov.jsonl >./output/totov.csv

che te ne pare @aborruso ?

ora devo capire come metterli assieme image e ottenere questo: image

aborruso commented 1 year ago

che te ne pare @aborruso ?

Mi sembra che non hai le chiavi per fare il join

pigreco commented 1 year ago

Mi sembra che non hai le chiavi per fare il join

vero, ma siccome estrae i dati nello stesso ciclo e per la stessa riga, basterebbe aggiungere un id sequenziale, che ne pensi?

pigreco commented 1 year ago

@aborruso ho ultimato lo script con affiancamento dei due file, cancellazione campi inutili e riordino campi (tutto con Miller!)

#!/bin/bash

set -x
set -e
set -u
set -o pipefail

# NOTA BENE: uso Miller 6

# crea cartella di output
mkdir -p ./output

# if file exists, delete it
if [ -f ./output/toto.jsonl ]; then
  rm ./output/toto.jsonl
fi

# per ogni CSV
for i in ./*.csv; do
  # estrai nome
  filename=$(basename "$i" .csv)
  # estrai prima riga e per ogni coppia chiave-valore, se la chiave termina con "resolved", estrai il nome campo
  mlr --c2n head -n 1 then put -q 'for (k,v in $*) { if (k =~ "^.+resolved$") {print k}}' ${i} | while IFS= read -r line; do
    # rimuovi "_resolved" dal nome campo
    fieldk=$(echo "$line" | sed 's/_resolved//')
    # lascia inalterato il nome campo
    fieldv=$(echo "$line")
    # e per ogni campo estratto, estrai da ogni CSV corrispondente i valori univoci del campo e aggiungi a output nome file e nome campo; il tutto in formato JSONL
    mlr --icsv --ojsonl cut -f "$fieldk" then uniq -a then label idk then put '$campo="'"$fieldk"'";$file="'"$filename"'"' ${i} >>./output/toto.jsonl
    mlr --icsv --ojsonl cut -f "$fieldv" then uniq -a then label idv then put '$campov="'"$fieldv"'";$file="'"$filename"'"' ${i} >>./output/totov.jsonl
  done
done

mlr --j2c sort -f campo -t idk then cat -n ./output/toto.jsonl >./output/toto.csv
mlr --j2c sort -f campov -t idv then cat -n ./output/totov.jsonl >./output/totov.csv

# elimina i campi non utili
mlr --csv --implicit-csv-header --headerless-csv-output cut -x -f 4 ./output/toto.csv >./output/toto1.csv
mlr --csv --implicit-csv-header --headerless-csv-output cut -x -f 1,3 ./output/totov.csv >./output/totov1.csv

# affianca i due output
paste -d, ./output/toto1.csv ./output/totov1.csv >./output/toto_all1.csv

# sistema ordine campi
mlr --csv --fs "," reorder -f n,idk,idkv,campo,file ./output/toto_all1.csv >./output/lista_finale.csv

# cancella i file csv non più utili
rm ./output/toto1.csv
rm ./output/totov1.csv
rm /output/toto_all1.csv

affianca i due output:

image

cancella e riordina campi

image

aborruso commented 1 year ago

ho ultimato lo script con affiancamento dei due file, cancellazione campi inutili e riordino campi (tutto con Miller!)

Sono contento!

pigreco commented 1 year ago

Ricetta fatta e pubblicata

https://tansignari.opendatasicilia.it/ricette/bash/estrarre_chiavi_valori_domini/