Closed pigreco closed 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?
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
:
sotto il dominio completo, con tutti i record:
sotto la lista dei valori univoci del campo GZ_FER_TY
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.
NB: un file csv può avere più domini collegati a più campi.
@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
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
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.
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 |
@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)
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: @.***>
Mi sono spiegato?
sì, ottimo! per me va bene unico file, per come hai fatto sopra. grazie
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
@aborruso l'unico file è una ottima soluzione:
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
@pigreco, se non è essenziale mi fermo qui.
Del resto, potresti provare tu adesso :)
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 e ottenere questo:
che te ne pare @aborruso ?
Mi sembra che non hai le chiavi per fare il join
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?
@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:
cancella e riordina campi
ho ultimato lo script con affiancamento dei due file, cancellazione campi inutili e riordino campi (tutto con Miller!)
Sono contento!
Ricetta fatta e pubblicata
https://tansignari.opendatasicilia.it/ricette/bash/estrarre_chiavi_valori_domini/
(@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
ha 8 record, ma quanti di questi sono stati utilizzati nel database ?
Con
ogr2ogr
è possibile "risolvere" i domini usando il seguente costrutto:ottenendo una tabella simile a quella di sotto:
in pratica i campi con dominio vengono esplosi in due colonne:
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:
ma come farlo con uno script?