données utilisées : https://files.data.gouv.fr/lcsqa/concentrations-de-polluants-atmospheriques-reglementes/temps-reel/2022/
L'exemple concerne les mesures horaires de concentration de polluants de l'air pour différentes stations de mesure fixes.
La structure de données mises à disposition est la suivante (principaux champs).
Les données sont découpées par fichier CSV d'une journée (49 000 lignes). Chaque fichier a une taille de 10,5 Mo, ce qui représente un volume annuel de 3,8 Go (18 millions de lignes).
from pprint import pprint
from collections import Counter
from time import time
from datetime import datetime
import csv
from util import util
from observation import Sdataset, Sfield
from copy import copy
import pandas as pd
chemin = 'https://raw.githubusercontent.com/loco-philippe/Environmental-Sensing/main/python/Validation/air/data_lcsqa/'
data = []
nb_fichiers = 1
annee = 2022
mois = 1
jour = 1
for i in range(nb_fichiers):
file = chemin + 'FR_E2_' + str(annee) + '-' + format(mois, '02d') +'-' + format(jour+i, '02d') +'.csv'
data.append(pd.read_csv(file, sep=';'))
data2 = pd.concat(data, ignore_index=True, join='inner')
#data2[['Date de début','Date de fin']] = data2[['Date de début','Date de fin']].astype('datetime64')
data2 = data2.astype('category')
print('data2 : \n', len(data2), '\n')
print(data2.iloc[0])
data2 : 49392 Date de début 2022/01/01 00:00:00 Date de fin 2022/01/01 01:00:00 Organisme ATMO GRAND EST code zas FR44ZAG02 Zas ZAG METZ code site FR01011 nom site Metz-Centre type d'implantation Urbaine Polluant NO type d'influence Fond discriminant A Réglementaire Oui type d'évaluation mesures fixes procédure de mesure Auto NO Conf meth CHIMILU type de valeur moyenne horaire validée valeur 1.5 valeur brute 1.45 unité de mesure µg-m3 taux de saisie NaN couverture temporelle NaN couverture de données NaN code qualité A validité 1 Name: 0, dtype: object
from json_ntv import Ntv
t0 = time()
ntv = Ntv.obj(data2)
print(time()-t0)
js = ntv.to_obj(encoded=True)
print(len(js))
50.8140811920166 4601581
idxs2 = Sdataset(data2)
print('idxs (len, lenlidx, sumcodec) : ', len(idxs2), len(idxs2.idxlen), sum(idxs2.idxlen))
idxs3 = Sdataset(idxs2)
print(idxs3 == idxs2)
idxs (len, lenlidx, sumcodec) : 49392 23 8471 True
t0=time()
pprint(idxs2.category)
print('\n')
pprint(idxs2.groups)
print('\n', idxs2.tree(), '\n')
print(idxs2.tree(mode='diff'))
print(time()-t0)
{'Date de début': 'secondary', 'Date de fin': 'coupled', 'Organisme': 'secondary', 'Polluant': 'secondary', 'Réglementaire': 'unique', 'Zas': 'coupled', 'code qualité': 'secondary', 'code site': 'secondary', 'code zas': 'secondary', 'couverture de données': 'unique', 'couverture temporelle': 'unique', 'discriminant': 'secondary', 'nom site': 'secondary', 'procédure de mesure': 'secondary', 'taux de saisie': 'unique', "type d'implantation": 'secondary', "type d'influence": 'secondary', "type d'évaluation": 'secondary', 'type de valeur': 'unique', 'unité de mesure': 'secondary', 'valeur': 'secondary', 'valeur brute': 'secondary', 'validité': 'secondary'} [{'Date de début', 'Polluant', 'code qualité', 'code site', 'discriminant', 'nom site', 'procédure de mesure', "type d'influence", "type d'évaluation", 'unité de mesure'}] -1: root-derived (49392) 0 : Date de début (24) 1 : Date de fin (24) 5 : code site (532) 2 : Organisme (18) 3 : code zas (70) 4 : Zas (70) 7 : type d implantation (5) 6 : nom site (532) 8 : Polluant (9) 9 : type d influence (3) 10: discriminant (26) 11: Réglementaire (1) 12: type d évaluation (4) 13: procédure de mesure (58) 14: type de valeur (1) 15: valeur (1956) 16: valeur brute (5127) 17: unité de mesure (3) 18: taux de saisie (1) 19: couverture temporelle (1) 20: couverture de données (1) 21: code qualité (3) 22: validité (2) -1: root-diff (49392) 11: Réglementaire (0.00e+00 - 1) 14: type de valeur (0.00e+00 - 1) 16: valeur brute (1.00e+00 - 5127) 0 : Date de début (2.03e-01 - 24) 1 : Date de fin (0.00e+00 - 24) 5 : code site (1.44e-02 - 532) 2 : Organisme (0.00e+00 - 18) 3 : code zas (0.00e+00 - 70) 4 : Zas (0.00e+00 - 70) 6 : nom site (7.08e-06 - 532) 7 : type d implantation (0.00e+00 - 5) 9 : type d influence (1.32e-02 - 3) 10: discriminant (3.87e-02 - 26) 12: type d évaluation (4.01e-02 - 4) 13: procédure de mesure (3.45e-02 - 58) 8 : Polluant (5.17e-02 - 9) 17: unité de mesure (3.01e-02 - 3) 15: valeur (5.89e-06 - 1956) 21: code qualité (1.29e-01 - 3) 22: validité (0.00e+00 - 2) 18: taux de saisie (0.00e+00 - 1) 19: couverture temporelle (0.00e+00 - 1) 20: couverture de données (0.00e+00 - 1) 0.04381513595581055
t0=time()
js = idxs2.to_ntv(modecodec='full').to_obj(encoded=True)
fullsize = len(js)
print('fullsize', len(js), time()-t0)
fullsize 14737997 11.726231575012207
t0=time()
idxs4 = Sdataset.from_ntv(js)
print('new', len(idxs4), time()-t0)
t0=time()
verif = idxs4 == idxs2
print('controle égalité :', verif, time()-t0)
new 49392 15.813089609146118 controle égalité : True 0.20861244201660156
t0=time()
js = idxs2.to_ntv(modecodec='nokeys').to_obj(encoded=True)
minsize = len(js)
print('minsize', len(js), time()-t0)
t0=time()
js = idxs2.to_ntv(modecodec='nokeys').to_obj(encoded=True, format='cbor')
print('mincborsize', len(js), time()-t0)
minsize 72660 0.1234736442565918 mincborsize 80751 0.11053013801574707
champ = idxs2.nindex
t0=time()
#js = idxs2.to_ntv(modecodec='default').to_obj(encoded=True)
nt = idxs2.to_ntv(modecodec='default')
print(time()-t0)
js = nt.to_obj(encoded=True)
print(time()-t0)
defaultsize = len(js)
print('defaultsize : ', defaultsize, time()-t0, '\n')
print('indicator default : ', idxs2.indicator(fullsize, defaultsize), '\n')
t0=time()
pprint(champ('code site').couplinginfos(champ('Date de début')))
print('\n', idxs2.tree(mode='diff'))
print('\nanalyse : ', time()-t0)
21.637557983398438 25.11229372024536 defaultsize : 3407655 25.11229372024536 indicator default : {'total values': 1185408, 'mean size': 12.433, 'unique values': 8494, 'mean coding size': 2.806, 'unicity level': 0.007, 'optimize level': 0.231, 'object lightness': 0.226, 'maxgain': 0.993, 'gain': 0.769} {'diff': 508, 'dist': 12768, 'distance': 12744, 'distmax': 12768, 'distmin': 532, 'distrate': 1.0, 'disttomax': 0, 'disttomin': 12236, 'rate': 1.0, 'typecoupl': 'crossed'} -1: root-diff (49392) 11: Réglementaire (0.00e+00 - 1) 14: type de valeur (0.00e+00 - 1) 16: valeur brute (1.00e+00 - 5127) 0 : Date de début (2.03e-01 - 24) 1 : Date de fin (0.00e+00 - 24) 5 : code site (1.44e-02 - 532) 2 : Organisme (0.00e+00 - 18) 3 : code zas (0.00e+00 - 70) 4 : Zas (0.00e+00 - 70) 6 : nom site (7.08e-06 - 532) 7 : type d implantation (0.00e+00 - 5) 9 : type d influence (1.32e-02 - 3) 10: discriminant (3.87e-02 - 26) 12: type d évaluation (4.01e-02 - 4) 13: procédure de mesure (3.45e-02 - 58) 8 : Polluant (5.17e-02 - 9) 17: unité de mesure (3.01e-02 - 3) 15: valeur (5.89e-06 - 1956) 21: code qualité (1.29e-01 - 3) 22: validité (0.00e+00 - 2) 18: taux de saisie (0.00e+00 - 1) 19: couverture temporelle (0.00e+00 - 1) 20: couverture de données (0.00e+00 - 1) analyse : 0.01991581916809082
print(idxs2.analysis.getmatrix(['Polluant', 'unité de mesure']))
notcoupl = champ('Polluant').coupling(champ('unité de mesure'), derived=True)
print('nombre de non couplés : ', len(notcoupl))
print('\nliste des premières incohérences : ')
liste = [(champ('Polluant')[i], champ('unité de mesure')[i]) for i in notcoupl[:2000]]
pprint(set(liste), width=120)
{'dist': 16, 'distrate': 0.3888888888888889, 'disttomin': 7, 'disttomax': 11, 'distmin': 9, 'distmax': 27, 'diff': 6, 'distance': 13, 'rate': 0.5416666666666666, 'typecoupl': 'link'} nombre de non couplés : 48840 liste des premières incohérences : {('PM2.5', 'µg-m3'), ('PM2.5', 'µg/m3')}
print(idxs2.analysis.getmatrix(['code site', 'nom site']))
notcoupl = champ('code site').coupling(champ('nom site'), derived=False)
print('nombre de non couplés : ', len(notcoupl))
print('\nliste des premières incohérences : ')
liste = [(champ('code site')[notcoupl[i]], champ('nom site')[notcoupl[i]]) for i in range(len(notcoupl))]
pprint(set(liste), width=120)
{'dist': 534, 'distrate': 7.079846508927687e-06, 'disttomin': 2, 'disttomax': 282490, 'distmin': 532, 'distmax': 283024, 'diff': 0, 'distance': 2, 'rate': 7.079846508927687e-06, 'typecoupl': 'link'} nombre de non couplés : 168 liste des premières incohérences : {('FR19007', 'Rennes Les Halles'), ('FR19053', 'Quimper Zola'), ('FR19007', 'HALLES'), ('FR19053', 'QUIMPER ZOLA')}
notcoupl = champ('nom site').coupling(champ('code site'), derived=False)
print('nombre de non couplés : ', len(notcoupl))
print('\nliste des premières incohérences : ')
liste = [(champ('code site')[notcoupl[i]], champ('nom site')[notcoupl[i]]) for i in range(len(notcoupl))]
pprint(set(liste), width=120)
nombre de non couplés : 384 liste des premières incohérences : {('FR20048', 'SAINT EXUPERY'), ('FR23004', 'PASTEUR'), ('FR23078', 'SAINT EXUPERY'), ('FR33101', 'PASTEUR')}
print('controle égalité :', Sdataset.from_ntv(js) == idxs2)
controle égalité : True
idxs4.reindex()
idxs4.coupling(param='distance', level=500)
print(idxs4.tree())
t0=time()
js = idxs4.to_ntv(modecodec='optimize').to_obj(encoded=True)
optimizesize = len(js)
print('optimizesize : ', optimizesize, time()-t0, '\n')
print('indicator optimize : ', idxs2.indicator(fullsize, optimizesize), '\n')
t0=time()
js = idxs4.to_ntv(modecodec='optimize').to_obj(encoded=True, format='cbor')
cborsize = len(js)
print('cborsize : ', cborsize, time()-t0, '\n')
print('indicator cbor : ', idxs2.indicator(fullsize, cborsize))
-1: root-derived (49392) 0 : Date de début (24) 1 : Date de fin (24) 5 : code site (2616) 3 : code zas (2143) 2 : Organisme (18) 4 : Zas (70) 13: procédure de mesure (1299) 8 : Polluant (310) 7 : type d implantation (101) 12: type d évaluation (49) 17: unité de mesure (21) 9 : type d influence (9) 21: code qualité (3) 22: validité (2) 10: discriminant (26) 6 : nom site (2616) 11: Réglementaire (1) 14: type de valeur (1) 15: valeur (1956) 16: valeur brute (5127) 18: taux de saisie (1) 19: couverture temporelle (1) 20: couverture de données (1) optimizesize : 1250930 5.381635427474976 indicator optimize : {'total values': 1185408, 'mean size': 12.433, 'unique values': 8505, 'mean coding size': 0.973, 'unicity level': 0.007, 'optimize level': 0.085, 'object lightness': 0.078, 'maxgain': 0.993, 'gain': 0.915} cborsize : 680667 5.948225498199463 indicator cbor : {'total values': 1185408, 'mean size': 12.433, 'unique values': 8505, 'mean coding size': 0.489, 'unicity level': 0.007, 'optimize level': 0.046, 'object lightness': 0.039, 'maxgain': 0.993, 'gain': 0.954}
print('controle égalité :', Sdataset.from_ntv(js) == idxs2)
controle égalité : True
synthèse ancien:
1 fichier : full 14.4, def 3.8, opt 0.9 cbor 0.3 dic 7.5 500
3 fichiers : full 43.1, def 11.5, opt 2.5 cbor 1.3 dic 23.7 500
5 fichiers : full 71.9, def 19.3, opt 4.1 cbor 2.1 dic 41.1 500
10 fichiers : full 143.7, def 39.0, opt 8.2 cbor 4.0 dic 84.5 500 493 225 lignes
synthèse ancien last:
1 fichier : full 3.3, def 0.2, opt 0.4 cbor 0.4 500
synthèse nouveau:
1 fichier : full 10.8, def 21.9, opt 5.5 cbor 8.3 500